Skip to content

Commit 5de7980

Browse files
fix: Fix crash with duplicate alias locs. (#31)
1 parent 14f1b30 commit 5de7980

File tree

3 files changed

+42
-4
lines changed

3 files changed

+42
-4
lines changed

scip_indexer/SCIPIndexer.cc

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
// NOTE: Protobuf headers should go first since they use poisoned functions.
22
#include "proto/SCIP.pb.h"
33

4+
#include <algorithm>
45
#include <fstream>
56
#include <iterator>
67
#include <memory>
@@ -977,14 +978,25 @@ class CFGTraversal final {
977978
todo.emplace_back(namedSym, loc);
978979
}
979980
}
981+
bool foundDupes = false;
980982
// Sort for determinism
981983
fast_sort(todo, [&](const SymbolWithLoc &p1, const SymbolWithLoc &p2) -> bool {
982-
ENFORCE(p1.second.beginPos() != p2.second.beginPos(),
983-
"found alias instructions with same start offset in {}, source:\n{}\nsym1 = {}, sym2 = {}\n",
984-
file.data(gs).path(), core::Loc(file, p1.second).toString(gs), p1.first.showRaw(gs),
985-
p2.first.showRaw(gs));
984+
if (p1.second.beginPos() == p2.second.beginPos()) {
985+
// TODO: This code path is hit when there is a module_function on top of a sig.
986+
// In that case, the 'T' and 'X' in 'T::X' in a sig end up with two occurrences each.
987+
// We should check if this is a Sorbet bug or deliberate.
988+
ENFORCE(p1.first == p2.first,
989+
"found different symbols at same location in {}, source:\n{}\nsym1 = {}\nsym2 = {}\n",
990+
file.data(gs).path(), core::Loc(file, p1.second).toString(gs), p1.first.showRaw(gs),
991+
p2.first.showRaw(gs));
992+
foundDupes = true;
993+
}
986994
return p1.second.beginPos() < p2.second.beginPos();
987995
});
996+
if (foundDupes) {
997+
auto last = unique(todo.begin(), todo.end());
998+
todo.erase(last, todo.end());
999+
}
9881000
// NOTE:(varun) Not 100% sure if emitting a reference here. Here's why it's written this
9891001
// way right now. This code path is hit in two different kinds of situations:
9901002
// - You have a reference to a nested class etc. inside a method body.

test/scip/testdata/types.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,11 @@
33
def f()
44
T.let(true, T::Boolean)
55
end
6+
7+
module M
8+
module_function
9+
sig { returns(T::Boolean) }
10+
def b
11+
true
12+
end
13+
end

test/scip/testdata/types.snapshot.rb

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,21 @@ def f()
66
# ^ reference scip-ruby gem TODO TODO T#
77
# ^^^^^^^ reference scip-ruby gem TODO TODO T#Boolean.
88
end
9+
10+
module M
11+
# ^ definition scip-ruby gem TODO TODO M#
12+
module_function
13+
sig { returns(T::Boolean) }
14+
# ^^^ reference scip-ruby gem TODO TODO Sorbet#Private#Static#<Class:ResolvedSig>#sig().
15+
# ^^^ reference scip-ruby gem TODO TODO Sorbet#Private#Static#<Class:ResolvedSig>#sig().
16+
# ^ reference scip-ruby gem TODO TODO T#
17+
# ^^^^^^^ reference scip-ruby gem TODO TODO T#Boolean.
18+
# ^^^^^^^ reference scip-ruby gem TODO TODO T#Boolean.
19+
# ^^^^^^^^^^ reference scip-ruby gem TODO TODO Sorbet#Private#Static#ResolvedSig#
20+
# ^^^^^^^^^^ reference scip-ruby gem TODO TODO Sorbet#Private#Static#ResolvedSig#
21+
def b
22+
# ^^^^^ definition scip-ruby gem TODO TODO M#b().
23+
# ^^^^^ definition scip-ruby gem TODO TODO <Class:M>#b().
24+
true
25+
end
26+
end

0 commit comments

Comments
 (0)