Skip to content

Commit 5b54c57

Browse files
authored
Rollup merge of rust-lang#109395 - chenyukang:yukang/fix-109291, r=cjgillot
Fix issue when there are multiple candidates for edit_distance_with_substrings Fixes rust-lang#109291
2 parents cb22866 + 4fc3c6b commit 5b54c57

File tree

3 files changed

+45
-3
lines changed

3 files changed

+45
-3
lines changed

compiler/rustc_span/src/edit_distance.rs

+29-3
Original file line numberDiff line numberDiff line change
@@ -174,10 +174,10 @@ pub fn find_best_match_for_name(
174174
fn find_best_match_for_name_impl(
175175
use_substring_score: bool,
176176
candidates: &[Symbol],
177-
lookup: Symbol,
177+
lookup_symbol: Symbol,
178178
dist: Option<usize>,
179179
) -> Option<Symbol> {
180-
let lookup = lookup.as_str();
180+
let lookup = lookup_symbol.as_str();
181181
let lookup_uppercase = lookup.to_uppercase();
182182

183183
// Priority of matches:
@@ -190,6 +190,8 @@ fn find_best_match_for_name_impl(
190190

191191
let mut dist = dist.unwrap_or_else(|| cmp::max(lookup.len(), 3) / 3);
192192
let mut best = None;
193+
// store the candidates with the same distance, only for `use_substring_score` current.
194+
let mut next_candidates = vec![];
193195
for c in candidates {
194196
match if use_substring_score {
195197
edit_distance_with_substrings(lookup, c.as_str(), dist)
@@ -198,12 +200,36 @@ fn find_best_match_for_name_impl(
198200
} {
199201
Some(0) => return Some(*c),
200202
Some(d) => {
201-
dist = d - 1;
203+
if use_substring_score {
204+
if d < dist {
205+
dist = d;
206+
next_candidates.clear();
207+
} else {
208+
// `d == dist` here, we need to store the candidates with the same distance
209+
// so we won't decrease the distance in the next loop.
210+
}
211+
next_candidates.push(*c);
212+
} else {
213+
dist = d - 1;
214+
}
202215
best = Some(*c);
203216
}
204217
None => {}
205218
}
206219
}
220+
221+
// We have a tie among several candidates, try to select the best among them ignoring substrings.
222+
// For example, the candidates list `force_capture`, `capture`, and user inputed `forced_capture`,
223+
// we select `force_capture` with a extra round of edit distance calculation.
224+
if next_candidates.len() > 1 {
225+
debug_assert!(use_substring_score);
226+
best = find_best_match_for_name_impl(
227+
false,
228+
&next_candidates,
229+
lookup_symbol,
230+
Some(lookup.len()),
231+
);
232+
}
207233
if best.is_some() {
208234
return best;
209235
}

tests/ui/suggestions/issue-109291.rs

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capture());
3+
//~^ ERROR no function or associated item name
4+
}
+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
error[E0599]: no function or associated item named `forced_capture` found for struct `Backtrace` in the current scope
2+
--> $DIR/issue-109291.rs:2:65
3+
|
4+
LL | println!("Custom backtrace: {}", std::backtrace::Backtrace::forced_capture());
5+
| ^^^^^^^^^^^^^^
6+
| |
7+
| function or associated item not found in `Backtrace`
8+
| help: there is an associated function with a similar name: `force_capture`
9+
10+
error: aborting due to previous error
11+
12+
For more information about this error, try `rustc --explain E0599`.

0 commit comments

Comments
 (0)