-
-
Save ko1/804a0034fb0ec0bdcb67f492932dc976 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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