From 9a57b047033034c30a3351d08ad648735299c8cf Mon Sep 17 00:00:00 2001 From: Koichi Sasada Date: Mon, 15 Apr 2024 17:06:03 +0900 Subject: [PATCH] `super{}` doesn't use block `super(){}`, `super{}` and `super(&b)` doesn't use the given block so warn unused block warning when calling a method which doesn't use block with above `super` expressions. e.g.: `def f = super{B1}` (warn on `f{B2}` because `B2` is not used. --- compile.c | 10 +++++++++- test/ruby/test_method.rb | 38 ++++++++++++++++++++++---------------- 2 files changed, 31 insertions(+), 17 deletions(-) diff --git a/compile.c b/compile.c index 30321a7af80c5f..0fb3b855838d36 100644 --- a/compile.c +++ b/compile.c @@ -9369,10 +9369,10 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i unsigned int flag = 0; struct rb_callinfo_kwarg *keywords = NULL; const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block; + int use_block = 1; INIT_ANCHOR(args); ISEQ_COMPILE_DATA(iseq)->current_block = NULL; - ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.use_block = 1; if (type == NODE_SUPER) { VALUE vargc = setup_args(iseq, args, RNODE_SUPER(node)->nd_args, &flag, &keywords); @@ -9381,6 +9381,10 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) { ADD_INSN(args, node, splatkw); } + + if (flag & VM_CALL_ARGS_BLOCKARG) { + use_block = 0; + } } else { /* NODE_ZSUPER */ @@ -9474,6 +9478,10 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i } } + if (use_block && parent_block == NULL) { + ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.use_block = 1; + } + flag |= VM_CALL_SUPER | VM_CALL_FCALL; if (type == NODE_ZSUPER) flag |= VM_CALL_ZSUPER; ADD_INSN(ret, node, putself); diff --git a/test/ruby/test_method.rb b/test/ruby/test_method.rb index 34b58a1f51016e..a41704cf069055 100644 --- a/test/ruby/test_method.rb +++ b/test/ruby/test_method.rb @@ -1663,28 +1663,34 @@ def initialize assert_in_out_err '-w', <<-'RUBY' do |_out, err, _status| class C0 - def foo = nil - def bar = nil - def baz = nil - def qux = nil + def f1 = nil + def f2 = nil + def f3 = nil + def f4 = nil + def f5 = nil + def f6 = nil end class C1 < C0 - def foo = super - def bar = super() - def baz(&_) = super(&_) - def qux = super(&nil) + def f1 = super # zsuper / use + def f2 = super() # super / use + def f3(&_) = super(&_) # super / use + def f4 = super(&nil) # super / unuse + def f5 = super(){} # super / unuse + def f6 = super{} # zsuper / unuse end - C1.new.foo{} # no warning - C1.new.bar{} # no warning - C1.new.baz{} # no warning - # C1.new.qux{} # TODO: warning line:16 but not supported yet. + C1.new.f1{} # no warning + C1.new.f2{} # no warning + C1.new.f3{} # no warning + C1.new.f4{} # warning + C1.new.f5{} # warning + C1.new.f6{} # warning RUBY - assert_equal 0, err.size - # TODO - # assert_equal 1, err.size - # assert_match(/-:16: warning.+qux/, err.join) + assert_equal 3, err.size, err.join("\n") + assert_match(/-:22: warning.+f4/, err.join) + assert_match(/-:23: warning.+f5/, err.join) + assert_match(/-:24: warning.+f6/, err.join) end end end