`umethod.bind_call(obj, ...)` is semantically equivalent to
`umethod.bind(obj).call(...)`. This idiom is used in some libraries to
call a method that is overridden. The added method does the same
without allocation of intermediate Method object. [Feature #15955]
```
class Foo
def add_1(x)
x + 1
end
end
class Bar < Foo
def add_1(x) # override
x + 2
end
end
obj = Bar.new
p obj.add_1(1) #=> 3
p Foo.instance_method(:add_1).bind(obj).call(1) #=> 2
p Foo.instance_method(:add_1).bind_call(obj, 1) #=> 2
```
These tests were guarded by a RUBY_ENGINE of "ruby" even though they test an official Ruby feature (pread/pwrite added in Ruby 2.5). This commit moves them to the top level of the test case so they will run on other implementations.
When searching for this constant, I landed on the correct page https://ruby-doc.org/core-2.6.4/Math.html however I was using CMD+f to search for "Euler" and did not find it. If we add the full name for this constant then it will be easier to search for and find.
typedef struct _COORD {
SHORT X;
SHORT Y; // I wanted to take this...
} COORD, *PCOORD;
typedef struct _CONSOLE_SCREEN_BUFFER_INFO {
COORD dwSize;
COORD dwCursorPosition; // ...of this one
WORD wAttributes; // But it's combined with first 2bytes of this
SMALL_RECT srWindow;
COORD dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO;
If wAttributes has non-zero value, the code breaks.
[feature #16035]
This goes one step farther than what nobu did in [feature #13498]
With this patch, special objects such as static symbols, integers, etc can be used as either key or values inside WeakMap. They simply don't have a finalizer defined on them.
This is useful if you need to deduplicate value objects
We can check the function pointer passed to rb_define_private_method
like how we do so in rb_define_method. Doing so revealed some
problematic usages of rb_obj_dummy. They had to be split according
to their arity.
We can check the function pointer passed to
rb_define_protected_method like how we do so in rb_define_method.
This changeset revealed no prototypes mismatches.
We can check the function pointer passed to rb_define_method_id
like how we do so in rb_define_method. This method is relatively
rarely used so there are less problems found than the other APIs.
We can check the function pointer passed to rb_define_global_function
like we do so in rb_define_method. It turns out that almost anybody
is misunderstanding the API.
We can check the function pointer passed to rb_define_module_function
like how we do so in rb_define_method. The difference is that this
changeset reveales lots of atiry mismatches.
The rb_define_method function takes a pointer to ANYARGS-ed functions,
which in fact varies 18 different prototypes. We still need to
preserve ANYARGS for storages but why not check the consistencies if
possible.
Q&As:
Q: Where did the magic number "18" came from in the description above?
A: Count the case branch of vm_method.c:call_cfunc_invoker_func().
Note also that the 18 branches has lasted for at least 25 years.
See also 200e0ee2fd.
Q: What is this __weakref__ thing?
A: That is a kind of function overloading mechanism that GCC provides.
In this case for instance rb_define_method0 is an alias of
rb_define_method, with a strong type.
Q: What is this __transparent_union__ thing?
A: That is another kind of function overloading mechanism that GCC
provides. In this case the attributed function pointer is either
VALUE(*)(int,VALUE*,VALUE) or VALUE(*)(int,const VALUE*,VALUE).
This is better than void* or ANYARGS because we can reject all
other possibilities than the two.
Q: What does this rb_define_method macro mean?
A: It selects appropriate alias of the rb_define_method function,
depending on the arity.
Q: Why the prototype change of rb_f_notimplement?
A: Function pointer to rb_f_notimplement is special cased in
vm_method.c:rb_add_method_cfunc(). That should be handled by the
__builtin_choose_expr chain inside of rb_define_method macro
expansion. In order to do so, comparison like (func ==
rb_f_notimplement) is inappropriate for __builtin_choose_expr's
expression (which must be a compile-time integer constant but the
address of rb_f_notimplement is not fixed until the linker). So
instead we are using __builtin_types_compatible_p, and in doing so
we need to distinguish rb_f_notimplement from others, by type.