diff --git a/scip_indexer/SCIPIndexer.cc b/scip_indexer/SCIPIndexer.cc index a1569b3a78..b9846727ae 100644 --- a/scip_indexer/SCIPIndexer.cc +++ b/scip_indexer/SCIPIndexer.cc @@ -1000,6 +1000,9 @@ class CFGTraversal final { // Emit references for arguments for (auto &arg : send->args) { + if (arg.loc == send->receiverLoc) { // See NOTE[implicit-arg-passing]. + continue; + } // NOTE: For constructs like a += b, the instruction sequence ends up being: // $tmp = $a // $a = $tmp.+($b) diff --git a/test/scip/testdata/implicit_super_arg.rb b/test/scip/testdata/implicit_super_arg.rb new file mode 100644 index 0000000000..ac5b4dc4c8 --- /dev/null +++ b/test/scip/testdata/implicit_super_arg.rb @@ -0,0 +1,25 @@ +# typed: true + +# NOTE[implicit-arg-passing]: In this example, Sorbet generates a CFG where +# a and b are implicitly passed to a method call at the 'super'. +# In theory, we could emit references to a and b at the 'super' +# call (following Sorbet strictly), but RubyMine doesn't do this. +# So let's not emit those. +# +# This only seems to trigger when there are two parameters, not one. +# A Sorbet bug, perhaps? +# +# bb0[rubyRegionId=0, firstDead=8](): +# : C = cast(: NilClass, C); +# a: T.untyped = load_arg(a) +# b: T.untyped = load_arg(b) +# : T.untyped = load_arg() +# $4: T.class_of() = alias > +# $6: Symbol(:) = : +# $2: T.untyped = $4: T.class_of().(: C, $6: Symbol(:), : T.untyped, a: T.untyped, b: T.untyped) +# : T.noreturn = return $2: T.untyped +class C + def f(a, b) + super + end +end diff --git a/test/scip/testdata/implicit_super_arg.snapshot.rb b/test/scip/testdata/implicit_super_arg.snapshot.rb new file mode 100644 index 0000000000..30744de45a --- /dev/null +++ b/test/scip/testdata/implicit_super_arg.snapshot.rb @@ -0,0 +1,30 @@ + # typed: true + + # NOTE[implicit-arg-passing]: In this example, Sorbet generates a CFG where + # a and b are implicitly passed to a method call at the 'super'. + # In theory, we could emit references to a and b at the 'super' + # call (following Sorbet strictly), but RubyMine doesn't do this. + # So let's not emit those. + # + # This only seems to trigger when there are two parameters, not one. + # A Sorbet bug, perhaps? + # + # bb0[rubyRegionId=0, firstDead=8](): + # : C = cast(: NilClass, C); + # a: T.untyped = load_arg(a) + # b: T.untyped = load_arg(b) + # : T.untyped = load_arg() + # $4: T.class_of() = alias > + # $6: Symbol(:) = : + # $2: T.untyped = $4: T.class_of().(: C, $6: Symbol(:), : T.untyped, a: T.untyped, b: T.untyped) + # : T.noreturn = return $2: T.untyped + class C +# ^ definition [..] C# + def f(a, b) +# ^^^^^^^^^^^ definition [..] C#f(). +# ^ definition local 1~#3809224601 +# ^ definition local 2~#3809224601 + super +# ^^^^^ reference [..] >#(). + end + end