Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion enum.c
Original file line number Diff line number Diff line change
Expand Up @@ -5147,7 +5147,7 @@ enum_compact(VALUE obj)
* end
*
* The result of the size function should represent the number of iterations
* (i.e., the number of times Enumerator::Yielder#yield is called).
* (i.e., the number of times you yield to the block argument).
* In the above example, the block calls #yield three times, and
* the size function, +-> { 3 }+, returns 3 accordingly.
* The result of the size function can be an integer, +Float::INFINITY+,
Expand Down
6 changes: 3 additions & 3 deletions enumerator.c
Original file line number Diff line number Diff line change
Expand Up @@ -4706,23 +4706,23 @@ InitVM_Enumerator(void)
rb_eStopIteration = rb_define_class("StopIteration", rb_eIndexError);
rb_define_method(rb_eStopIteration, "result", stop_result, 0);

/* Generator */
/* :nodoc: Generator */
rb_cGenerator = rb_define_class_under(rb_cEnumerator, "Generator", rb_cObject);
rb_include_module(rb_cGenerator, rb_mEnumerable);
rb_define_alloc_func(rb_cGenerator, generator_allocate);
rb_define_method(rb_cGenerator, "initialize", generator_initialize, -1);
rb_define_method(rb_cGenerator, "initialize_copy", generator_init_copy, 1);
rb_define_method(rb_cGenerator, "each", generator_each, -1);

/* Yielder */
/* :nodoc: Yielder */
rb_cYielder = rb_define_class_under(rb_cEnumerator, "Yielder", rb_cObject);
rb_define_alloc_func(rb_cYielder, yielder_allocate);
rb_define_method(rb_cYielder, "initialize", yielder_initialize, 0);
rb_define_method(rb_cYielder, "yield", yielder_yield, -2);
rb_define_method(rb_cYielder, "<<", yielder_yield_push, 1);
rb_define_method(rb_cYielder, "to_proc", yielder_to_proc, 0);

/* Producer */
/* :nodoc: Producer */
rb_cEnumProducer = rb_define_class_under(rb_cEnumerator, "Producer", rb_cObject);
rb_define_alloc_func(rb_cEnumProducer, producer_allocate);
rb_define_method(rb_cEnumProducer, "each", producer_each, 0);
Expand Down
10 changes: 3 additions & 7 deletions ext/socket/raddrinfo.c
Original file line number Diff line number Diff line change
Expand Up @@ -601,13 +601,9 @@ rb_getaddrinfo(const char *hostp, const char *portp, const struct addrinfo *hint
if (need_free) free_getaddrinfo_arg(arg);

if (timedout) {
if (arg->ai) {
rsock_raise_user_specified_timeout(arg->ai, Qnil, Qnil);
} else {
VALUE host = rb_str_new_cstr(hostp);
VALUE port = rb_str_new_cstr(portp);
rsock_raise_user_specified_timeout(NULL, host, port);
}
VALUE host = rb_str_new_cstr(hostp);
VALUE port = rb_str_new_cstr(portp);
rsock_raise_user_specified_timeout(NULL, host, port);
}

// If the current thread is interrupted by asynchronous exception, the following raises the exception.
Expand Down
8 changes: 8 additions & 0 deletions internal/class.h
Original file line number Diff line number Diff line change
Expand Up @@ -646,6 +646,14 @@ RICLASS_OWNS_M_TBL_P(VALUE iclass)
return RCLASSEXT_ICLASS_IS_ORIGIN(ext) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext);
}

static inline bool
RICLASS_FOR_REFINEMENT_P(VALUE iclass)
{
return BUILTIN_TYPE(iclass) == T_ICLASS &&
RB_TYPE_P(RBASIC(iclass)->klass, T_MODULE) &&
FL_TEST_RAW(RBASIC(iclass)->klass, RMODULE_IS_REFINEMENT);
}

static inline void
RCLASS_SET_INCLUDER(VALUE iclass, VALUE klass)
{
Expand Down
8 changes: 6 additions & 2 deletions io_buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -3554,11 +3554,15 @@ io_buffer_not(VALUE self)
struct rb_io_buffer *buffer = NULL;
TypedData_Get_Struct(self, struct rb_io_buffer, &rb_io_buffer_type, buffer);

VALUE output = rb_io_buffer_new(NULL, buffer->size, io_flags_for_size(buffer->size));
const void *base;
size_t size;
io_buffer_get_bytes_for_reading(buffer, &base, &size);

VALUE output = rb_io_buffer_new(NULL, size, io_flags_for_size(size));
struct rb_io_buffer *output_buffer = NULL;
TypedData_Get_Struct(output, struct rb_io_buffer, &rb_io_buffer_type, output_buffer);

memory_not(output_buffer->base, buffer->base, buffer->size);
memory_not(output_buffer->base, base, size);

return output;
}
Expand Down
71 changes: 69 additions & 2 deletions proc.c
Original file line number Diff line number Diff line change
Expand Up @@ -3595,6 +3595,8 @@ method_to_proc(VALUE method)
}

extern VALUE rb_find_defined_class_by_owner(VALUE current_class, VALUE target_owner);
extern int rb_method_definition_eq(const rb_method_definition_t *d1, const rb_method_definition_t *d2);
rb_cref_t * rb_vm_get_cref(const VALUE *ep);

/*
* call-seq:
Expand All @@ -3621,11 +3623,76 @@ method_super_method(VALUE method)
mid = data->me->def->body.alias.original_me->def->original_id;
}
else {
super_class = RCLASS_SUPER(RCLASS_ORIGIN(iclass));
VALUE klass = iclass;
if (RICLASS_FOR_REFINEMENT_P(klass)) {
// Refined methods need this check before superclass determination
klass = RBASIC(klass)->klass;
}
super_class = RCLASS_SUPER(RCLASS_ORIGIN(klass));
mid = data->me->def->original_id;
}
if (!super_class) return Qnil;
me = (rb_method_entry_t *)rb_callable_method_entry_with_refinements(super_class, mid, &iclass);

// For refined methods, skip refinements for the same definition, but consider
// refinements for superclass methods
const rb_method_definition_t *skip_def = RICLASS_FOR_REFINEMENT_P(iclass) ? data->me->def : NULL;

// Use the CREF of the Method/UnboundMethod, not the CREF of the caller of super_method.
// We must avoid the use of rb_callable_method_entry_with_refinements, as that will
// implicitly use the refinements activated in of the caller of super_method.
const rb_cref_t *cref = NULL;
switch (data->me->def->type) {
case VM_METHOD_TYPE_ISEQ:
cref = data->me->def->body.iseq.cref;
break;
case VM_METHOD_TYPE_BMETHOD: {
const rb_proc_t *proc;
GetProcPtr(data->me->def->body.bmethod.proc, proc);
const struct rb_block *block = &proc->block;
if (vm_block_type(block) == block_type_iseq)
cref = rb_vm_get_cref(block->as.captured.ep);
break;
}
default:
break;
}
VALUE klass = super_class;
me = NULL;
while (klass) {
const rb_callable_method_entry_t *cme = rb_callable_method_entry(klass, mid);
if (!cme) break;
if (cme->def->type != VM_METHOD_TYPE_REFINED) {
me = (rb_method_entry_t *)cme;
iclass = cme->defined_class;
break;
}
// Look through all CREF scopes for a refinement for cme->owner, mirroring
// the loop in search_refined_method.
const rb_cref_t *c;
for (c = cref; c; c = CREF_NEXT(c)) {
VALUE refs = CREF_REFINEMENTS(c);
if (NIL_P(refs)) continue;
VALUE r = rb_hash_lookup(refs, cme->owner);
if (NIL_P(r)) continue;
const rb_callable_method_entry_t *ref_cme = rb_callable_method_entry(r, mid);
if (!ref_cme) break;
if (ref_cme->def->type == VM_METHOD_TYPE_REFINED) continue;
if (skip_def && rb_method_definition_eq(ref_cme->def, skip_def)) continue;
me = (rb_method_entry_t *)ref_cme;
iclass = ref_cme->defined_class;
break;
}
if (me) break;
// No refined method found. Use orig_me if available, or normal method lookup
// in superclass otherwise.
const rb_method_entry_t *orig_me = cme->def->body.refined.orig_me;
if (orig_me) {
me = (rb_method_entry_t *)orig_me;
iclass = orig_me->defined_class ? orig_me->defined_class : cme->defined_class;
break;
}
klass = RCLASS_SUPER(cme->defined_class);
}
if (!me) return Qnil;
return mnew_internal(me, me->owner, iclass, data->recv, mid, rb_obj_class(method), FALSE, FALSE);
}
Expand Down
1 change: 1 addition & 0 deletions test/ruby/test_io_buffer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,7 @@ def test_operators_raise_on_freed_self
assert_raise(IO::Buffer::InvalidatedError) { slice & mask }
assert_raise(IO::Buffer::InvalidatedError) { slice | mask }
assert_raise(IO::Buffer::InvalidatedError) { slice ^ mask }
assert_raise(IO::Buffer::InvalidatedError) { ~slice }
end

def test_operators_raise_on_freed_mask
Expand Down
Loading