Skip to content

Commit 1eb0f64

Browse files
committed
Suggest Span without source changes when source code is unavailable
Signed-off-by: xizheyin <[email protected]>
1 parent f8e355c commit 1eb0f64

File tree

3 files changed

+105
-6
lines changed

3 files changed

+105
-6
lines changed

compiler/rustc_errors/src/emitter.rs

Lines changed: 46 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2014,12 +2014,52 @@ impl HumanEmitter {
20142014
debug!(?suggestions);
20152015

20162016
if suggestions.is_empty() {
2017-
// Here we check if there are suggestions that have actual code changes. We sometimes
2018-
// suggest the same code that is already there, instead of changing how we produce the
2019-
// suggestions and filtering there, we just don't emit the suggestion.
2020-
// Suggestions coming from macros can also have malformed spans. This is a heavy handed
2021-
// approach to avoid ICEs by ignoring the suggestion outright.
2022-
return Ok(());
2017+
// Check if this is because source file is unavailable
2018+
let has_unavailable_source =
2019+
suggestion.substitutions.iter().flat_map(|sub| &sub.parts).any(|part| {
2020+
if let Ok(lines) = sm.span_to_lines(part.span) {
2021+
!sm.ensure_source_file_source_present(&lines.file)
2022+
} else {
2023+
false
2024+
}
2025+
});
2026+
// Only when source unavailable, use the original suggestion spans for proper location display
2027+
if has_unavailable_source {
2028+
// When source is unavailable, use the original suggestion spans for proper location display
2029+
let suggestion_span = if !suggestion.substitutions.is_empty() {
2030+
// Use the span from the first substitution part
2031+
let parts: Vec<_> = suggestion
2032+
.substitutions
2033+
.iter()
2034+
.flat_map(|sub| &sub.parts)
2035+
.map(|part| part.span)
2036+
.collect();
2037+
if !parts.is_empty() { MultiSpan::from_spans(parts) } else { span.clone() }
2038+
} else {
2039+
span.clone()
2040+
};
2041+
2042+
return self.emit_messages_default_inner(
2043+
&suggestion_span,
2044+
&[(suggestion.msg.to_owned(), Style::HeaderMsg)],
2045+
args,
2046+
&None,
2047+
level,
2048+
max_line_num_len,
2049+
true,
2050+
false,
2051+
);
2052+
} else {
2053+
// If source is available but suggestions are empty
2054+
// this is because of some reason in `splice_lines`, skip
2055+
//
2056+
// Here we check if there are suggestions that have actual code changes.
2057+
// We sometimes suggest the same code that is already there, instead of changing how we produce the
2058+
// suggestions and filtering there, we just don't emit the suggestion.
2059+
// Suggestions coming from macros can also have malformed spans. This is a heavy handed
2060+
// approach to avoid ICEs by ignoring the suggestion outright.
2061+
return Ok(());
2062+
}
20232063
}
20242064

20252065
let mut buffer = StyledBuffer::new();
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
enum Foo<T> {
2+
Bar {
3+
v23: T,
4+
y: isize
5+
}
6+
}
7+
8+
fn f(x: &Foo) { //~ ERROR missing generics for enum `Foo` [E0107]
9+
match *x {
10+
Foo::Bar { y: y, v23: x } => {
11+
assert_eq!(x, 1);
12+
assert_eq!(y, 2); //~ ERROR can't compare `&isize` with `{integer}` [E0277]
13+
}
14+
}
15+
}
16+
17+
pub fn main() {
18+
let x = Foo::Bar { x: 1, y: 2 }; //~ ERROR variant `Foo<_>::Bar` has no field named `x` [E0559]
19+
f(&x);
20+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
error[E0107]: missing generics for enum `Foo`
2+
--> $DIR/help-show-std-source.rs:8:10
3+
|
4+
LL | fn f(x: &Foo) {
5+
| ^^^ expected 1 generic argument
6+
|
7+
note: enum defined here, with 1 generic parameter: `T`
8+
--> $DIR/help-show-std-source.rs:1:6
9+
|
10+
LL | enum Foo<T> {
11+
| ^^^ -
12+
help: add missing generic argument
13+
|
14+
LL | fn f(x: &Foo<T>) {
15+
| +++
16+
17+
error[E0277]: can't compare `&isize` with `{integer}`
18+
--> $DIR/help-show-std-source.rs:12:13
19+
|
20+
LL | assert_eq!(y, 2);
21+
| ^^^^^^^^^^^^^^^^ no implementation for `&isize == {integer}`
22+
|
23+
= help: the trait `PartialEq<{integer}>` is not implemented for `&isize`
24+
= note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
25+
help: consider dereferencing here
26+
--> $SRC_DIR/core/src/macros/mod.rs:LL:COL
27+
28+
error[E0559]: variant `Foo<_>::Bar` has no field named `x`
29+
--> $DIR/help-show-std-source.rs:18:24
30+
|
31+
LL | let x = Foo::Bar { x: 1, y: 2 };
32+
| ^ `Foo<_>::Bar` does not have this field
33+
|
34+
= note: available fields are: `v23`
35+
36+
error: aborting due to 3 previous errors
37+
38+
Some errors have detailed explanations: E0107, E0277, E0559.
39+
For more information about an error, try `rustc --explain E0107`.

0 commit comments

Comments
 (0)