Skip to content

Instantly share code, notes, and snippets.

@ko1
Created February 29, 2024 08:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ko1/804a0034fb0ec0bdcb67f492932dc976 to your computer and use it in GitHub Desktop.
Save ko1/804a0034fb0ec0bdcb67f492932dc976 to your computer and use it in GitHub Desktop.
diff --git a/array.rb b/array.rb
index 8e809b35c9..f63ff00056 100644
--- a/array.rb
+++ b/array.rb
@@ -43,6 +43,8 @@ class Array
# Related: #each_index, #reverse_each.
def each
Primitive.attr! :inline_block
+ Primitive.attr! :use_block
+
unless defined?(yield)
return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)'
end
diff --git a/compile.c b/compile.c
index e68f06ef1f..11cd7edd83 100644
--- a/compile.c
+++ b/compile.c
@@ -2100,6 +2100,7 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons
if (block_id) {
body->param.block_start = arg_size++;
body->param.flags.has_block = TRUE;
+ body->param.flags.use_block = 1;
}
iseq_calc_param_size(iseq);
@@ -5918,6 +5919,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret,
ADD_INSN(ret, line_node, putnil);
ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_YIELD), 0,
PUSH_VAL(DEFINED_YIELD));
+ ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.use_block = 1;
return;
case NODE_BACK_REF:
@@ -8635,6 +8637,9 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node)
else if (strcmp(RSTRING_PTR(string), "inline_block") == 0) {
ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_INLINE_BLOCK;
}
+ else if (strcmp(RSTRING_PTR(string), "use_block") == 0) {
+ ISEQ_BODY(iseq)->param.flags.use_block = 1;
+ }
else {
goto unknown_arg;
}
@@ -9585,6 +9590,7 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_INSN2(ret, node, invokesuper,
new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL),
parent_block);
+ ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.use_block = 1;
if (popped) {
ADD_INSN(ret, node, pop);
@@ -9621,6 +9627,7 @@ compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i
ADD_SEQ(ret, args);
ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE));
+ ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.use_block = 1;
if (popped) {
ADD_INSN(ret, node, pop);
@@ -12689,7 +12696,10 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq)
(body->param.flags.has_block << 6) |
(body->param.flags.ambiguous_param0 << 7) |
(body->param.flags.accepts_no_kwarg << 8) |
- (body->param.flags.ruby2_keywords << 9);
+ (body->param.flags.ruby2_keywords << 9) |
+ (body->param.flags.anon_rest << 10) |
+ (body->param.flags.anon_kwrest << 11) |
+ (body->param.flags.use_block << 12);
#if IBF_ISEQ_ENABLE_LOCAL_BUFFER
# define IBF_BODY_OFFSET(x) (x)
@@ -12905,6 +12915,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset)
load_body->param.flags.ruby2_keywords = (param_flags >> 9) & 1;
load_body->param.flags.anon_rest = (param_flags >> 10) & 1;
load_body->param.flags.anon_kwrest = (param_flags >> 11) & 1;
+ load_body->param.flags.use_block = (param_flags >> 12) & 1;
load_body->param.size = param_size;
load_body->param.lead_num = param_lead_num;
load_body->param.opt_num = param_opt_num;
diff --git a/dir.rb b/dir.rb
index 632c49eee9..42b475ab2c 100644
--- a/dir.rb
+++ b/dir.rb
@@ -408,6 +408,7 @@ def self.[](*args, base: nil, sort: true)
# specifies that patterns may match short names if they exist; Windows only.
#
def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true)
+ Primitive.attr! :use_block
Primitive.dir_s_glob(pattern, flags, base, sort)
end
end
diff --git a/iseq.c b/iseq.c
index 36fbe9d2f4..771dcc7783 100644
--- a/iseq.c
+++ b/iseq.c
@@ -538,6 +538,11 @@ iseq_location_setup(rb_iseq_t *iseq, VALUE name, VALUE path, VALUE realpath, int
RB_OBJ_WRITE(iseq, &loc->label, name);
RB_OBJ_WRITE(iseq, &loc->base_label, name);
loc->first_lineno = first_lineno;
+
+ if (ISEQ_BODY(iseq)->local_iseq == iseq && strcmp(RSTRING_PTR(name), "initialize") == 0) {
+ ISEQ_BODY(iseq)->param.flags.use_block = 1;
+ }
+
if (code_location) {
loc->node_id = node_id;
loc->code_location = *code_location;
diff --git a/lib/optparse.rb b/lib/optparse.rb
index 51dbfd0ad2..cf8f954c24 100644
--- a/lib/optparse.rb
+++ b/lib/optparse.rb
@@ -461,7 +461,7 @@ def self.candidate(key, icase = false, pat = nil, &block)
candidates
end
- def candidate(key, icase = false, pat = nil)
+ def candidate(key, icase = false, pat = nil, &_)
Completion.candidate(key, icase, pat, &method(:each))
end
@@ -739,7 +739,7 @@ class RequiredArgument < self
#
# Raises an exception if argument is not present.
#
- def parse(arg, argv)
+ def parse(arg, argv, &_)
unless arg
raise MissingArgument if argv.empty?
arg = argv.shift
diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb
index c6edfb473c..a269a66a15 100644
--- a/lib/rdoc/context.rb
+++ b/lib/rdoc/context.rb
@@ -710,7 +710,7 @@ def display(method_attr) # :nodoc:
# This method exists to make it easy to work with Context subclasses that
# aren't part of RDoc.
- def each_ancestor # :nodoc:
+ def each_ancestor &_ # :nodoc:
end
##
diff --git a/lib/rubygems/vendor/optparse/lib/optparse.rb b/lib/rubygems/vendor/optparse/lib/optparse.rb
index 5937431720..e69fa2af92 100644
--- a/lib/rubygems/vendor/optparse/lib/optparse.rb
+++ b/lib/rubygems/vendor/optparse/lib/optparse.rb
@@ -459,7 +459,7 @@ def self.candidate(key, icase = false, pat = nil, &block)
candidates
end
- def candidate(key, icase = false, pat = nil)
+ def candidate(key, icase = false, pat = nil, &_)
Completion.candidate(key, icase, pat, &method(:each))
end
@@ -730,7 +730,7 @@ class RequiredArgument < self
#
# Raises an exception if argument is not present.
#
- def parse(arg, argv)
+ def parse(arg, argv, &_)
unless arg
raise MissingArgument if argv.empty?
arg = argv.shift
diff --git a/pack.rb b/pack.rb
index d505eaee35..b6e29c3eab 100644
--- a/pack.rb
+++ b/pack.rb
@@ -17,6 +17,7 @@ class String
# returns that array.
# See {Packed Data}[rdoc-ref:packed_data.rdoc].
def unpack(fmt, offset: 0)
+ Primitive.attr! :use_block
Primitive.pack_unpack(fmt, offset)
end
diff --git a/tool/mk_builtin_loader.rb b/tool/mk_builtin_loader.rb
index 07c8291249..4abd497f0e 100644
--- a/tool/mk_builtin_loader.rb
+++ b/tool/mk_builtin_loader.rb
@@ -6,7 +6,7 @@
SUBLIBS = {}
REQUIRED = {}
-BUILTIN_ATTRS = %w[leaf inline_block]
+BUILTIN_ATTRS = %w[leaf inline_block use_block]
def string_literal(lit, str = [])
while lit
diff --git a/tool/test/testunit/test_parallel.rb b/tool/test/testunit/test_parallel.rb
index f79c3a1d80..6882fd6c5f 100644
--- a/tool/test/testunit/test_parallel.rb
+++ b/tool/test/testunit/test_parallel.rb
@@ -119,7 +119,7 @@ def test_done
result = Marshal.load($1.chomp.unpack1("m"))
assert_equal(5, result[0])
- pend "TODO: result[1] returns 17. We should investigate it" do
+ pend "TODO: result[1] returns 17. We should investigate it" do # TODO: misusage of pend (pend doens't use given block)
assert_equal(12, result[1])
end
assert_kind_of(Array,result[2])
diff --git a/trace_point.rb b/trace_point.rb
index e61b4b6802..b136e9b399 100644
--- a/trace_point.rb
+++ b/trace_point.rb
@@ -94,6 +94,7 @@ class TracePoint
# Access from other threads is also forbidden.
#
def self.new(*events)
+ Primitive.attr! :use_block
Primitive.tracepoint_new_s(events)
end
@@ -131,6 +132,7 @@ def self.stat
# trace.enabled? #=> true
#
def self.trace(*events)
+ Primitive.attr! :use_block
Primitive.tracepoint_trace_s(events)
end
@@ -196,6 +198,7 @@ def self.trace(*events)
# out calls by itself from :line handler, otherwise it will call itself infinitely).
#
def self.allow_reentry
+ Primitive.attr! :use_block
Primitive.tracepoint_allow_reentry
end
@@ -258,6 +261,7 @@ def self.allow_reentry
# #=> RuntimeError: access from outside
#
def enable(target: nil, target_line: nil, target_thread: :default)
+ Primitive.attr! :use_block
Primitive.tracepoint_enable_m(target, target_line, target_thread)
end
@@ -294,6 +298,7 @@ def enable(target: nil, target_line: nil, target_thread: :default)
# trace.disable { p tp.lineno }
# #=> RuntimeError: access from outside
def disable
+ Primitive.attr! :use_block
Primitive.tracepoint_disable_m
end
diff --git a/vm_backtrace.c b/vm_backtrace.c
index fa00c06f63..b4c83f41e7 100644
--- a/vm_backtrace.c
+++ b/vm_backtrace.c
@@ -193,8 +193,8 @@ location_lineno_m(VALUE self)
VALUE rb_mod_name0(VALUE klass, bool *permanent);
-static VALUE
-gen_method_name(VALUE owner, VALUE name)
+VALUE
+rb_gen_method_name(VALUE owner, VALUE name)
{
bool permanent;
if (RB_TYPE_P(owner, T_CLASS) || RB_TYPE_P(owner, T_MODULE)) {
@@ -227,7 +227,7 @@ retry:
case ISEQ_TYPE_MAIN:
return ISEQ_BODY(iseq)->location.label;
case ISEQ_TYPE_METHOD:
- return gen_method_name(owner, ISEQ_BODY(iseq)->location.label);
+ return rb_gen_method_name(owner, ISEQ_BODY(iseq)->location.label);
case ISEQ_TYPE_BLOCK:
case ISEQ_TYPE_PLAIN: {
int level = 0;
@@ -261,7 +261,7 @@ static VALUE
location_label(rb_backtrace_location_t *loc)
{
if (loc->cme && loc->cme->def->type == VM_METHOD_TYPE_CFUNC) {
- return gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
+ return rb_gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
}
else {
VALUE owner = Qnil;
@@ -431,7 +431,7 @@ location_to_str(rb_backtrace_location_t *loc)
file = GET_VM()->progname;
lineno = 0;
}
- name = gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
+ name = rb_gen_method_name(loc->cme->owner, rb_id2str(loc->cme->def->original_id));
}
else {
file = rb_iseq_path(loc->iseq);
diff --git a/vm_core.h b/vm_core.h
index 5300b9d3b7..0267ed434e 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -418,6 +418,7 @@ struct rb_iseq_constant_body {
unsigned int ruby2_keywords: 1;
unsigned int anon_rest: 1;
unsigned int anon_kwrest: 1;
+ unsigned int use_block: 1;
} flags;
unsigned int size;
diff --git a/vm_insnhelper.c b/vm_insnhelper.c
index 6136cb1465..795dea3e55 100644
--- a/vm_insnhelper.c
+++ b/vm_insnhelper.c
@@ -2965,6 +2965,8 @@ vm_call_single_noarg_leaf_builtin(rb_execution_context_t *ec, rb_control_frame_t
return builtin_invoker0(ec, calling->recv, NULL, (rb_insn_func_t)bf->func_ptr);
}
+VALUE rb_gen_method_name(VALUE owner, VALUE name); // in vm_backtrace.c
+
static inline int
vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling,
const rb_iseq_t *iseq, VALUE *argv, int param_size, int local_size)
@@ -2973,6 +2975,14 @@ vm_callee_setup_arg(rb_execution_context_t *ec, struct rb_calling_info *calling,
const struct rb_callcache *cc = calling->cc;
bool cacheable_ci = vm_ci_markable(ci);
+ if (UNLIKELY(!ISEQ_BODY(iseq)->param.flags.use_block &&
+ calling->block_handler != VM_BLOCK_HANDLER_NONE &&
+ !(vm_ci_flag(calling->cd->ci) & VM_CALL_SUPER))) {
+ VALUE name = rb_gen_method_name(vm_cc_cme(calling->cc)->defined_class, ISEQ_BODY(iseq)->location.base_label);
+
+ rb_warn("a block is given for a block unused method '%s'", RSTRING_PTR(name));
+ }
+
if (LIKELY(!(vm_ci_flag(ci) & VM_CALL_KW_SPLAT))) {
if (LIKELY(rb_simple_iseq_p(iseq))) {
rb_control_frame_t *cfp = ec->cfp;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment