summaryrefslogtreecommitdiff
path: root/vm_args.c
AgeCommit message (Collapse)Author
2020-01-24Do not autosplat when calling proc with empty keyword splatJeremy Evans
With the removal of the splatted argument when using an empty keyword splat, the autosplat code considered an empty keyword splat the same as no argument at all. However, that results in autosplat behavior changing dependent on the content of the splatted hash, which is not what anyone would expect or want. This change always skips an autosplat if keywords were provided. Fixes [Bug #16560] Notes: Merged: https://github.com/ruby/ruby/pull/2861
2020-01-23Remove empty keyword splats when calling even when using ruby2_keywordsJeremy Evans
Keeping empty keyword splats for ruby2_keywords methods was necessary in 2.7 to prevent the final positional hash being treated as keywords. Now that keyword argument separation has been committed, the final positional hash is never treated as keywords, so there is no need to keep empty keyword splats when using ruby2_keywords. Notes: Merged: https://github.com/ruby/ruby/pull/2857
2020-01-03Fix unused warningsKazuhiro NISHIYAMA
http://ci.rvm.jp/results/trunk_gcc7@silicon-docker/2539622 ``` /tmp/ruby/v2/src/trunk_gcc7/class.c: In function 'rb_scan_args_parse': /tmp/ruby/v2/src/trunk_gcc7/class.c:1971:12: warning: unused variable 'tmp_buffer' [-Wunused-variable] VALUE *tmp_buffer = arg->tmp_buffer; ^~~~~~~~~~ ``` ``` In file included from /tmp/ruby/v2/src/trunk_gcc7/vm_insnhelper.c:1895:0, from /tmp/ruby/v2/src/trunk_gcc7/vm.c:349: /tmp/ruby/v2/src/trunk_gcc7/vm_args.c:212:1: warning: 'args_stored_kw_argv_to_hash' defined but not used [-Wunused-function] args_stored_kw_argv_to_hash(struct args_info *args) ^~~~~~~~~~~~~~~~~~~~~~~~~~~ ```
2020-01-02Fully separate positional arguments and keyword argumentsJeremy Evans
This removes the warnings added in 2.7, and changes the behavior so that a final positional hash is not treated as keywords or vice-versa. To handle the arg_setup_block splat case correctly with keyword arguments, we need to check if we are taking a keyword hash. That case didn't have a test, but it affects real-world code, so add a test for it. This removes rb_empty_keyword_given_p() and related code, as that is not needed in Ruby 3. The empty keyword case is the same as the no keyword case in Ruby 3. This changes rb_scan_args to implement keyword argument separation for C functions when the : character is used. For backwards compatibility, it returns a duped hash. This is a bad idea for performance, but not duping the hash breaks at least Enumerator::ArithmeticSequence#inspect. Instead of having RB_PASS_CALLED_KEYWORDS be a number, simplify the code by just making it be rb_keyword_given_p(). Notes: Merged: https://github.com/ruby/ruby/pull/2794
2019-12-23Reword keyword arguments warning messages to convey these are deprecation ↵Marc-Andre Lafortune
warnings
2019-12-21Kernel#lambda: return forwarded block as non-lambda procAlan Wu
Before this commit, Kernel#lambda can't tell the difference between a directly passed literal block and one passed with an ampersand. A block passed with an ampersand is semantically speaking already a non-lambda proc. When Kernel#lambda receives a non-lambda proc, it should simply return it. Implementation wise, when the VM calls a method with a literal block, it places the code for the block on the calling control frame and passes a pointer (block handler) to the callee. Before this commit, the VM forwards block arguments by simply forwarding the block handler, which leaves the slot for block code unused when a control frame forwards its block argument. I use the vacant space to indicate that a frame has forwarded its block argument and inspect that in Kernel#lambda to detect forwarded blocks. This is a very ad-hoc solution and relies *heavily* on the way block passing works in the VM. However, it's the most self-contained solution I have. [Bug #15620] Notes: Merged: https://github.com/ruby/ruby/pull/2289
2019-12-20vm_args.c: rephrase the warning message of keyword argument separationYusuke Endoh
(old) test.rb:4: warning: The last argument is used as the keyword parameter test.rb:1: warning: for `foo' defined here; maybe ** should be added to the call? (new) test.rb:4: warning: The last argument is used as keyword parameters; maybe ** should be added to the call test.rb:1: warning: The called method `foo' is defined here
2019-12-19Manage deprecation warnings about keyword argumentNobuyoshi Nakada
2019-12-19Adjusted the formatNobuyoshi Nakada
2019-12-10vm_core.h (iseq_unique_id): prefer uintptr_t instead of unsigned longYusuke Endoh
It produced a warning about type cast in LLP64 (i.e., windows).
2019-12-09vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointerYusuke Endoh
(This is the second try of 036bc1da6c6c9b0fa9b7f5968d897a9554dd770e.) If iseq is GC'ed, the pointer of iseq may be reused, which may hide a deprecation warning of keyword argument change. http://ci.rvm.jp/results/trunk-test1@phosphorus-docker/2474221 ``` 1) Failure: TestKeywordArguments#test_explicit_super_kwsplat [/tmp/ruby/v2/src/trunk-test1/test/ruby/test_keyword.rb:549]: --- expected +++ actual @@ -1 +1 @@ -/The keyword argument is passed as the last hash parameter.* for `m'/m +"" ``` This change ad-hocly adds iseq_unique_id for each iseq, and use it instead of iseq pointer. This covers the case where caller is GC'ed. Still, the case where callee is GC'ed, is not covered. But anyway, it is very rare that iseq is GC'ed. Even when it occurs, it just hides some warnings. It's no big deal.
2019-12-09Revert "vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointer"Yusuke Endoh
This reverts commit 036bc1da6c6c9b0fa9b7f5968d897a9554dd770e. This caused a failure on iseq_binary mode. http://ci.rvm.jp/results/trunk-iseq_binary@silicon-docker/2474587 Numbering iseqs is not trivial due to dump/load.
2019-12-09Revert "vm_args.c (rb_warn_check): Use unique_id * 2 instead of unique_id"Yusuke Endoh
This reverts commit 751a9b32e5a53336768eb878de1827245a3292bf.
2019-12-09vm_args.c (rb_warn_check): Use unique_id * 2 instead of unique_idYusuke Endoh
The function assumed that the LSB of `callee` was 0.
2019-12-09vm_args.c (rb_warn_check): Use iseq_unique_id instead of its pointerYusuke Endoh
If iseq is GC'ed, the pointer of iseq may be reused, which may hide a deprecation warning of keyword argument change. http://ci.rvm.jp/results/trunk-test1@phosphorus-docker/2474221 ``` 1) Failure: TestKeywordArguments#test_explicit_super_kwsplat [/tmp/ruby/v2/src/trunk-test1/test/ruby/test_keyword.rb:549]: --- expected +++ actual @@ -1 +1 @@ -/The keyword argument is passed as the last hash parameter.* for `m'/m +"" ``` This change ad-hocly adds iseq_unique_id for each iseq, and use it instead of iseq pointer. This covers the case where caller is GC'ed. Still, the case where callee is GC'ed, is not covered. But anyway, it is very rare that iseq is GC'ed. Even when it occurs, it just hides some warnings. It's no big deal.
2019-12-03vm_args.c: make the keyword deprecation message helpfulYusuke Endoh
``` $ ./miniruby -e 'def foo(kw: 1); end; h = {kw: 1}; foo(h)' -e:1: warning: The last argument is used as the keyword parameter -e:1: warning: for `foo' defined here; maybe ** should be added to the call? ```
2019-11-29Reduce duplicated warnings for the change of Ruby 3 keyword argumentsYusuke Endoh
By this change, the following code prints only one warning. ``` def foo(**opt); end 100.times { foo({kw:1}) } ``` A global variable `st_table *caller_to_callees` is a map from caller to a set of callee methods. It remembers that a warning is already printed for each pair of caller and callee. [Feature #16289] Notes: Merged: https://github.com/ruby/ruby/pull/2458
2019-11-27Don't modify rest array when using ruby2_keywordsJeremy Evans
Previously, the rest array was modified, but it turns out that is not necessary. Not modifying the rest array fixes cases when the rest array is used more than once. Notes: Merged: https://github.com/ruby/ruby/pull/2706
2019-11-20Always forward declaration is neededNobuyoshi Nakada
`rb_resolve_refined_method_callable` is referenced in `refine_sym_proc_call`, even when pre-compiling mjit header on mswin.
2019-11-19make functions static卜部昌平
These functions are used from within a compilation unit so we can make them static, for better binary size. This changeset reduces the size of generated ruby binary from 26,590,128 bytes to 26,584,472 bytes on my macihne. Notes: Merged: https://github.com/ruby/ruby/pull/2682
2019-10-24Handle case where ruby2_keywords method splats to ruby2_keywords methodJeremy Evans
Previously, the keyword hash was duped (which results in a regular hash), but the dup was not marked as a keyword hash, causing the hash not to be marked as keyword hash even though it should be. Notes: Merged: https://github.com/ruby/ruby/pull/2609
2019-10-15Dup hash with keyword flag when converted to keywordsJeremy Evans
When ruby2_keywords is used on a method, keywords passed to the method are flagged. When the hash is passed as the last element of an argument splat to another method, the hash should be treated as a keyword splat. When keyword splatting a hash, a duplicate of the hash is made. So when auto-splatting the hash with the keyword flag, a duplicate of the hash should also be made. This fixes cases where the hash is later passed to another method and would be treated as keywords there: class Object ruby2_keywords def foo(*a) bar(*a) end def bar(*a) baz(*a) end def baz(*a, **kw) [a, kw] end end foo(:a=>1) Previously, this would pass the :a=>1 as keywords to bar and also as keywords to baz. Now it only passes :a=>1 as keywords to bar, but bar passes :a=>1 as a positional hash to baz (which in this case generates a warning in 2.7).
2019-09-29Remove VM_NO_KEYWORDS, replace with RB_NO_KEYWORDSJeremy Evans
VM_NO_KEYWORDS was introduced first in vm_core.h, but it is best to only use a single definition for this.
2019-09-27Adjusted spaces [ci skip]Nobuyoshi Nakada
2019-09-26Add rb_adjust_argv_kw_splat to internal.hJeremy Evans
We are calling this in a few other files, it is better to have it in a header than adding prototypes to the other files. Notes: Merged: https://github.com/ruby/ruby/pull/2491
2019-09-25Add Module#ruby2_keywords for passing keywords through regular argument splatsJeremy Evans
This approach uses a flag bit on the final hash object in the regular splat, as opposed to a previous approach that used a VM frame flag. The hash flag approach is less invasive, and handles some cases that the VM frame flag approach does not, such as saving the argument splat array and splatting it later: ruby2_keywords def foo(*args) @args = args bar end def bar baz(*@args) end def baz(*args, **kw) [args, kw] end foo(a:1) #=> [[], {a: 1}] foo({a: 1}, **{}) #=> [[{a: 1}], {}] foo({a: 1}) #=> 2.7: [[], {a: 1}] # and warning foo({a: 1}) #=> 3.0: [[{a: 1}], {}] It doesn't handle some cases that the VM frame flag handles, such as when the final hash object is replaced using Hash#merge, but those cases are probably less common and are unlikely to properly support keyword argument separation. Use ruby2_keywords to handle argument delegation in the delegate library. Notes: Merged: https://github.com/ruby/ruby/pull/2477
2019-09-17Fix keyword argument separation issues with sym procs when using refinementsJeremy Evans
Make sure that vm_yield_with_cfunc can correctly set the empty keyword flag by passing 2 as the kw_splat value when calling it in vm_invoke_ifunc_block. Make sure calling.kw_splat is set to 1 and not 128 in vm_sendish, so we can safely check for different kw_splat values. vm_args.c needs to call add_empty_keyword, and to make JIT happy, the function needs to be exported. Rename the function to rb_adjust_argv_kw_splat to more accurately reflect what it does, and mark it as MJIT exported. Notes: Merged: https://github.com/ruby/ruby/pull/2462
2019-09-17Pass keyword argument flag when rb_call_super_kw calls method_missingJeremy Evans
This makes method_missing take a flag for whether keyword arguments were passed. Adds tests both for rb_call_super_kw usage as well as general usage of super calling method_missing in Ruby methods. Notes: Merged: https://github.com/ruby/ruby/pull/2462
2019-09-11Emit missing keyword argument separation warnings for define_methodJeremy Evans
Previously, the warning functions skipped warning in these cases. This removes the skipping, and uses a less descriptive warning instead. This affected both last argument to keyword warnings and keyword split warnings.
2019-09-08Fix invalid keyword argument separation warning for delegating callsJeremy Evans
This removes an invalid keyword argument separation warning for code such as: ```ruby def foo(arg) arg end kw = {} foo(*[1], **kw) ``` This warning was caused because the remove_empty_keyword_hash was set based on a comparison with two variables, and in this case, one of the variables was updated after the check and we need to use the updated variable. Simplify things by just inlining the comparison.
2019-09-06Enable keyword argument warnings when called from CJeremy Evans
Previously, Ruby did not warn in these cases, and in some cases did not have the same behavior. This makes calls from C handled the same way as calls from Ruby. Notes: Merged: https://github.com/ruby/ruby/pull/2432
2019-09-05Mark rb_warn_keyword_to_last_hash as static inlineJeremy Evans
mame pointed out that vm_args.c is included in vm_insnhelper.c.
2019-09-05Mark rb_warn_keyword_to_last_hash at MJIT_FUNC_EXPORTEDJeremy Evans
Hopefully this fixes MJIT errors on AppVeyor.
2019-09-05Convert empty keyword hash to required positional argument and warnJeremy Evans
In general, we want to ignore empty keyword hashes. The only case where we want to allow them for backwards compatibility is when they are necessary to satify the final required positional argument. In that case, we want to not ignore them, but we do want to warn, as that will be going away in Ruby 3. This commit implements this support for regular methods and attr_writer methods. In order to allow send to forward arguments correctly, send no longer removes empty keyword hashes. It is the responsibility of the final method to remove the empty keyword hashes now. This change was necessary as otherwise send could remove the empty keyword hashes before the regular or attr_writer methods could move them to required positional arguments. For completeness, add tests for keyword handling regular methods calls. This makes rb_warn_keyword_to_last_hash non-static in vm_args.c so it can be reused in vm_insnhelper.c, and also moves declarations before statements in the rb_warn_* functions in vm_args.c.
2019-09-05vm_argc.c (vm_caller_setup_arg_kw): "cfunc" argument is no longer usedYusuke Endoh
2019-09-05Set calling->kw_splat = 1 in vm_caller_setup_arg_kwYusuke Endoh
There are two styles that argv contains keyword arguments: one is VM_CALL_KWARG which contains value elements in argv (to avoid a hash object creation if possible), and the other is VM_CALL_KW_SPLAT which contains one last hash in argv. vm_caller_setup_arg_kw translates argv from the VM_CALL_KWARG style to the VM_CALL_KW_SPLAT style. `calling->kw_splat` means that argv is the VM_CALL_KW_SPLAT style. So, instead of setting `calling->kw_splat` at many places, it would be better to do so when vm_caller_setup_arg_kw is called.
2019-09-05Add rb_funcall_with_block_kwJeremy Evans
This is needed for C functions to call methods with keyword arguments. This is a copy of rb_funcall_with_block with an extra argument for the keyword flag. There isn't a clean way to implement this that doesn't involve changing a lot of function signatures, because rb_call doesn't support a way to mark that the call has keyword arguments. So hack this in using a CALL_PUBLIC_KW call_type, which we switch for CALL_PUBLIC later in the call stack. We do need to modify rm_vm_call0 to take an argument for whether keyword arguments are used, since the call_type is no longer available at that point. Use the passed in value to set the appropriate keyword flag in both calling and ci_entry.
2019-09-05Propagate kw_splat informationYusuke Endoh
The kw_splat flag is whether the original call passes keyword or not. Some types of methods (e.g., bmethod and sym_proc) drops the information. This change tries to propagate the flag to the final callee, as far as I can.
2019-09-01Split warning messages for tag-jumpNobuyoshi Nakada
2019-08-30Add rb_iseq_locationJeremy Evans
This wraps iseq_location and should fix the leaked global test.
2019-08-30Use more accurate source location in keyword argument separation warningsJeremy Evans
This shows locations in places it didn't before, such as for proc calls, and fixes the location for super calls. This requires making iseq_location non-static and MJIT exported, which I hope will not cause problems.
2019-08-30Warn for keyword to last hash parameter when method has no optional/rest ↵Jeremy Evans
parameters Previously, there was no warning in this case, even though we will be changing the behavior in Ruby 3. Fixes [Bug #14130]
2019-08-30Remove a verbose warning that is no longer neededJeremy Evans
This warns about a case that we will continue to support.
2019-08-30When splitting a keyword hash, dup it first to not mutate itJeremy Evans
Notes: Merged: https://github.com/ruby/ruby/pull/2395
2019-08-30Implement keyword argument to last positional hash emulationJeremy Evans
For methods that accept keyword arguments but do not accept a keyword splat, if a keyword splat is passed, or keywords are used with a non-symbol key, check the hash. If the hash contains all symbols, keep the same behavior as before. If the hash contains all non-symbols, move the hash to the last positional hash and warn. If the hash contains symbols and non-Symbols, split the hash and use the symbol keys for the keyword hash and non-symbol keys for the positional hash and warn. Notes: Merged: https://github.com/ruby/ruby/pull/2395
2019-08-30Make keyword_hash_split staticJeremy Evans
Notes: Merged: https://github.com/ruby/ruby/pull/2395
2019-08-30Support **nil syntax for specifying a method does not accept keyword argumentsJeremy Evans
This syntax means the method should be treated as a method that uses keyword arguments, but no specific keyword arguments are supported, and therefore calling the method with keyword arguments will raise an ArgumentError. It is still allowed to double splat an empty hash when calling the method, as that does not pass any keyword arguments. Notes: Merged: https://github.com/ruby/ruby/pull/2395
2019-08-30Restore splitting of hashes into positional and keyword arguments, add warningJeremy Evans
This restores compatibility with Ruby 2.6, splitting the last positional hash into positional and keyword arguments if it contains both symbol and non-symbol keys. However, in this case it will warn, as the behavior in Ruby 3 will be to not split the hash and keep it as a positional argument. This does not affect the handling of mixed symbol and non-symbol keys in bare keywords. Those are still treated as keywords now, as they were before this patch. This results in different behavior than Ruby 2.6, which would split the bare keywords and use the non-Symbol keys as a positional arguments. Notes: Merged: https://github.com/ruby/ruby/pull/2395
2019-08-30Only promote last hash to keyword if all keys are symbolsJeremy Evans
If all keys are not symbols, then the non-symbol keys would not be treated as keywords in previous versions. It doesn't make sense to treat these hashes as keywords to break compatibility and warn about behavior changes in Ruby 2.7 when the Ruby 3.0 behavior will be the same as the Ruby 2.6 for these hashes. Notes: Merged: https://github.com/ruby/ruby/pull/2395
2019-08-30Fix hash to keyword warning to apply in all casesJeremy Evans
Previously, it only applied if the call had more positional arguments than the method it was calling accepted. Notes: Merged: https://github.com/ruby/ruby/pull/2395