@@ -102,12 +102,26 @@ impl flags::Scip {
102
102
// This is called after definitions have been deduplicated by token_ids_emitted. The purpose
103
103
// is to detect reuse of symbol names because this causes ambiguity about their meaning.
104
104
let mut record_error_if_symbol_already_used =
105
- |symbol : String , relative_path : & str , line_index : & LineIndex , text_range : TextRange | {
105
+ |symbol : String ,
106
+ is_inherent_impl : bool ,
107
+ relative_path : & str ,
108
+ line_index : & LineIndex ,
109
+ text_range : TextRange | {
106
110
let is_local = symbol. starts_with ( "local " ) ;
107
111
if !is_local && !nonlocal_symbols_emitted. insert ( symbol. clone ( ) ) {
108
- let source_location =
109
- text_range_to_string ( relative_path, line_index, text_range) ;
110
- duplicate_symbol_errors. push ( ( source_location, symbol) ) ;
112
+ // See #18772. Duplicate SymbolInformation for inherent impls is omitted.
113
+ if is_inherent_impl {
114
+ false
115
+ } else {
116
+ let source_location =
117
+ text_range_to_string ( relative_path, line_index, text_range) ;
118
+ duplicate_symbol_errors. push ( ( source_location, symbol) ) ;
119
+ // Keep duplicate SymbolInformation. This behavior is preferred over
120
+ // omitting so that the issue might be visible within downstream tools.
121
+ true
122
+ }
123
+ } else {
124
+ true
111
125
}
112
126
} ;
113
127
@@ -126,13 +140,13 @@ impl flags::Scip {
126
140
tokens. into_iter ( ) . for_each ( |( text_range, id) | {
127
141
let token = si. tokens . get ( id) . unwrap ( ) ;
128
142
129
- let ( symbol, enclosing_symbol) =
130
- if let Some ( TokenSymbols { symbol, enclosing_symbol } ) =
143
+ let ( symbol, enclosing_symbol, is_inherent_impl ) =
144
+ if let Some ( TokenSymbols { symbol, enclosing_symbol, is_inherent_impl } ) =
131
145
symbol_generator. token_symbols ( id, token)
132
146
{
133
- ( symbol, enclosing_symbol)
147
+ ( symbol, enclosing_symbol, is_inherent_impl )
134
148
} else {
135
- ( "" . to_owned ( ) , None )
149
+ ( "" . to_owned ( ) , None , false )
136
150
} ;
137
151
138
152
if !symbol. is_empty ( ) {
@@ -144,17 +158,20 @@ impl flags::Scip {
144
158
if token_ids_emitted. insert ( id) {
145
159
// token_ids_emitted does deduplication. This checks that this results
146
160
// in unique emitted symbols, as otherwise references are ambiguous.
147
- record_error_if_symbol_already_used (
161
+ let should_emit = record_error_if_symbol_already_used (
148
162
symbol. clone ( ) ,
163
+ is_inherent_impl,
149
164
relative_path. as_str ( ) ,
150
165
& line_index,
151
166
text_range,
152
167
) ;
153
- symbols. push ( compute_symbol_info (
154
- symbol. clone ( ) ,
155
- enclosing_symbol,
156
- token,
157
- ) ) ;
168
+ if should_emit {
169
+ symbols. push ( compute_symbol_info (
170
+ symbol. clone ( ) ,
171
+ enclosing_symbol,
172
+ token,
173
+ ) ) ;
174
+ }
158
175
}
159
176
} else {
160
177
token_ids_referenced. insert ( id) ;
@@ -227,12 +244,13 @@ impl flags::Scip {
227
244
continue ;
228
245
}
229
246
230
- let TokenSymbols { symbol, enclosing_symbol } = symbol_generator
247
+ let TokenSymbols { symbol, enclosing_symbol, .. } = symbol_generator
231
248
. token_symbols ( id, token)
232
249
. expect ( "To have been referenced, the symbol must be in the cache." ) ;
233
250
234
251
record_error_if_symbol_already_used (
235
252
symbol. clone ( ) ,
253
+ false ,
236
254
relative_path. as_str ( ) ,
237
255
& line_index,
238
256
text_range,
@@ -395,6 +413,9 @@ struct TokenSymbols {
395
413
symbol : String ,
396
414
/// Definition that contains this one. Only set when `symbol` is local.
397
415
enclosing_symbol : Option < String > ,
416
+ /// True if this symbol is for an inherent impl. This is used to only emit `SymbolInformation`
417
+ /// for a struct's first inherent impl, since their symbol names are not disambiguated.
418
+ is_inherent_impl : bool ,
398
419
}
399
420
400
421
struct SymbolGenerator {
@@ -421,6 +442,14 @@ impl SymbolGenerator {
421
442
MonikerResult :: Moniker ( moniker) => TokenSymbols {
422
443
symbol : scip:: symbol:: format_symbol ( moniker_to_symbol ( moniker) ) ,
423
444
enclosing_symbol : None ,
445
+ is_inherent_impl : moniker
446
+ . identifier
447
+ . description
448
+ . get ( moniker. identifier . description . len ( ) - 2 )
449
+ . map_or ( false , |descriptor| {
450
+ descriptor. desc == MonikerDescriptorKind :: Type
451
+ && descriptor. name == "impl"
452
+ } ) ,
424
453
} ,
425
454
MonikerResult :: Local { enclosing_moniker } => {
426
455
let local_symbol = scip:: types:: Symbol :: new_local ( local_count) ;
@@ -431,6 +460,7 @@ impl SymbolGenerator {
431
460
. as_ref ( )
432
461
. map ( moniker_to_symbol)
433
462
. map ( scip:: symbol:: format_symbol) ,
463
+ is_inherent_impl : false ,
434
464
}
435
465
}
436
466
} )
0 commit comments