diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 95400ac2ca3b0..5ec247d7e91a4 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -2014,12 +2014,52 @@ impl HumanEmitter { debug!(?suggestions); if suggestions.is_empty() { - // Here we check if there are suggestions that have actual code changes. We sometimes - // suggest the same code that is already there, instead of changing how we produce the - // suggestions and filtering there, we just don't emit the suggestion. - // Suggestions coming from macros can also have malformed spans. This is a heavy handed - // approach to avoid ICEs by ignoring the suggestion outright. - return Ok(()); + // Check if this is because source file is unavailable + let has_unavailable_source = + suggestion.substitutions.iter().flat_map(|sub| &sub.parts).any(|part| { + if let Ok(lines) = sm.span_to_lines(part.span) { + !sm.ensure_source_file_source_present(&lines.file) + } else { + false + } + }); + // Only when source unavailable, use the original suggestion spans for proper location display + if has_unavailable_source { + // When source is unavailable, use the original suggestion spans for proper location display + let suggestion_span = if !suggestion.substitutions.is_empty() { + // Use the span from the first substitution part + let parts: Vec<_> = suggestion + .substitutions + .iter() + .flat_map(|sub| &sub.parts) + .map(|part| part.span) + .collect(); + if !parts.is_empty() { MultiSpan::from_spans(parts) } else { span.clone() } + } else { + span.clone() + }; + + return self.emit_messages_default_inner( + &suggestion_span, + &[(suggestion.msg.to_owned(), Style::HeaderMsg)], + args, + &None, + level, + max_line_num_len, + true, + false, + ); + } else { + // If source is available but suggestions are empty + // this is because of some reason in `splice_lines`, skip + // + // Here we check if there are suggestions that have actual code changes. + // We sometimes suggest the same code that is already there, instead of changing how we produce the + // suggestions and filtering there, we just don't emit the suggestion. + // Suggestions coming from macros can also have malformed spans. This is a heavy handed + // approach to avoid ICEs by ignoring the suggestion outright. + return Ok(()); + } } let mut buffer = StyledBuffer::new(); diff --git a/tests/ui/compiletest-self-test/help-show-std-source.rs b/tests/ui/compiletest-self-test/help-show-std-source.rs new file mode 100644 index 0000000000000..3edd2ecd8639d --- /dev/null +++ b/tests/ui/compiletest-self-test/help-show-std-source.rs @@ -0,0 +1,20 @@ +enum Foo { + Bar { + v23: T, + y: isize + } +} + +fn f(x: &Foo) { //~ ERROR missing generics for enum `Foo` [E0107] + match *x { + Foo::Bar { y: y, v23: x } => { + assert_eq!(x, 1); + assert_eq!(y, 2); //~ ERROR can't compare `&isize` with `{integer}` [E0277] + } + } +} + +pub fn main() { + let x = Foo::Bar { x: 1, y: 2 }; //~ ERROR variant `Foo<_>::Bar` has no field named `x` [E0559] + f(&x); +} diff --git a/tests/ui/compiletest-self-test/help-show-std-source.stderr b/tests/ui/compiletest-self-test/help-show-std-source.stderr new file mode 100644 index 0000000000000..867cd2c71f201 --- /dev/null +++ b/tests/ui/compiletest-self-test/help-show-std-source.stderr @@ -0,0 +1,39 @@ +error[E0107]: missing generics for enum `Foo` + --> $DIR/help-show-std-source.rs:8:10 + | +LL | fn f(x: &Foo) { + | ^^^ expected 1 generic argument + | +note: enum defined here, with 1 generic parameter: `T` + --> $DIR/help-show-std-source.rs:1:6 + | +LL | enum Foo { + | ^^^ - +help: add missing generic argument + | +LL | fn f(x: &Foo) { + | +++ + +error[E0277]: can't compare `&isize` with `{integer}` + --> $DIR/help-show-std-source.rs:12:13 + | +LL | assert_eq!(y, 2); + | ^^^^^^^^^^^^^^^^ no implementation for `&isize == {integer}` + | + = help: the trait `PartialEq<{integer}>` is not implemented for `&isize` + = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) +help: consider dereferencing here + --> $SRC_DIR/core/src/macros/mod.rs:LL:COL + +error[E0559]: variant `Foo<_>::Bar` has no field named `x` + --> $DIR/help-show-std-source.rs:18:24 + | +LL | let x = Foo::Bar { x: 1, y: 2 }; + | ^ `Foo<_>::Bar` does not have this field + | + = note: available fields are: `v23` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0277, E0559. +For more information about an error, try `rustc --explain E0107`.