From 4b5f39637933ba35e1f9286fa197fbca7341431f Mon Sep 17 00:00:00 2001 From: Takumi Shotoku Date: Sat, 5 Sep 2026 17:47:59 +0900 Subject: [PATCH] Report super outside a method instead of crashing Only a method definition sets lenv.forward_args, which a bare `super` shares with `...` forwarding, so `define_method(:foo) { |x| super }` ran a bare `raise` and surfaced as a RuntimeError with no message. Report a diagnostic instead and treat the call as taking no arguments. Ruby's own wording differs by context, an implicit argument passing error from define_method and "super called outside of method" at the top level, and TypeProf only knows that forward_args is missing, so the message quotes neither. --- lib/typeprof/core/ast/call.rb | 12 +++++++++--- scenario/diagnostics/super-outside-method.rb | 9 +++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 scenario/diagnostics/super-outside-method.rb diff --git a/lib/typeprof/core/ast/call.rb b/lib/typeprof/core/ast/call.rb index 2d794240e..e2768f0bd 100644 --- a/lib/typeprof/core/ast/call.rb +++ b/lib/typeprof/core/ast/call.rb @@ -124,7 +124,13 @@ def install0(genv) end if @forwarding_arguments - forward_a_args = (@lenv.forward_args || raise).to_actual_arguments( + forward_args = @lenv.forward_args + # `...` needs a method definition, so only a bare `super` can reach here + @changes.add_diagnostic(:code_range, "implicit argument passing of super is not supported here") unless forward_args + end + + if forward_args + forward_a_args = forward_args.to_actual_arguments( genv, @changes, self, @@ -211,11 +217,11 @@ def install0(genv) blk_ty = @block_pass.install(genv) elsif @anonymous_block_forwarding blk_ty = @lenv.get_var(:"*anonymous_block") - elsif @forwarding_arguments + elsif forward_args blk_ty = forward_a_args.block end - if @forwarding_arguments + if forward_args a_args = a_args.with_block(blk_ty, omittable: !@block_body && !@block_pass && !@anonymous_block_forwarding) else a_args = a_args.with_block(blk_ty) diff --git a/scenario/diagnostics/super-outside-method.rb b/scenario/diagnostics/super-outside-method.rb new file mode 100644 index 000000000..a7d7e2b17 --- /dev/null +++ b/scenario/diagnostics/super-outside-method.rb @@ -0,0 +1,9 @@ +## update +define_method(:foo) do |x| + super +end + +## diagnostics +(1,0)-(1,13): undefined method: Object#define_method +(2,2)-(2,7): implicit argument passing of super is not supported here +(2,2)-(2,7): undefined method: Object#define_method