Skip to content

Commit e17fa36

Browse files
committed
Suggest Span without source changes when source code is unavailable
1 parent a06c1ca commit e17fa36

7 files changed

Lines changed: 120 additions & 3 deletions

File tree

compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ pub struct AnnotateSnippetEmitter {
4747
track_diagnostics: bool,
4848
terminal_url: TerminalUrl,
4949
theme: OutputTheme,
50+
show_suggestions_with_unavailable_source: bool,
5051
}
5152

5253
impl Debug for AnnotateSnippetEmitter {
@@ -63,6 +64,10 @@ impl Debug for AnnotateSnippetEmitter {
6364
.field("track_diagnostics", &self.track_diagnostics)
6465
.field("terminal_url", &self.terminal_url)
6566
.field("theme", &self.theme)
67+
.field(
68+
"show_suggestions_with_unavailable_source",
69+
&self.show_suggestions_with_unavailable_source,
70+
)
6671
.finish()
6772
}
6873
}
@@ -136,6 +141,7 @@ impl AnnotateSnippetEmitter {
136141
track_diagnostics: false,
137142
terminal_url: TerminalUrl::No,
138143
theme: OutputTheme::Ascii,
144+
show_suggestions_with_unavailable_source: false,
139145
}
140146
}
141147

@@ -307,6 +313,11 @@ impl AnnotateSnippetEmitter {
307313
SuggestionStyle::HideCodeInline
308314
| SuggestionStyle::ShowCode
309315
| SuggestionStyle::ShowAlways => {
316+
let unavailable_source_span = if self.show_suggestions_with_unavailable_source {
317+
self.suggestion_span_with_unavailable_source(sm, &suggestion)
318+
} else {
319+
None
320+
};
310321
let substitutions = suggestion
311322
.substitutions
312323
.into_iter()
@@ -341,8 +352,19 @@ impl AnnotateSnippetEmitter {
341352
return None;
342353
}
343354

344-
// We can't splice anything if the source is unavailable.
345-
if !sm.ensure_source_file_source_present(&lo_file) {
355+
// We can't splice anything if the source is unavailable. When the
356+
// span-only fallback is enabled, also avoid rendering source that was
357+
// intentionally hidden from diagnostics.
358+
let can_show_source = if self.show_suggestions_with_unavailable_source {
359+
should_show_source_code(
360+
&self.ignored_directories_in_source_blocks,
361+
sm,
362+
&lo_file,
363+
)
364+
} else {
365+
sm.ensure_source_file_source_present(&lo_file)
366+
};
367+
if !can_show_source {
346368
return None;
347369
}
348370

@@ -356,6 +378,30 @@ impl AnnotateSnippetEmitter {
356378
.collect::<Vec<_>>();
357379

358380
if substitutions.is_empty() {
381+
if let Some(span) = unavailable_source_span {
382+
let msg = format_diag_message(&suggestion.msg, args).to_string();
383+
report.push(std::mem::replace(
384+
&mut group,
385+
Group::with_title(
386+
annotate_snippets::Level::HELP.secondary_title(msg),
387+
),
388+
));
389+
390+
let file_ann = collect_annotations(args, &span, sm);
391+
let level = annotate_snippets::Level::HELP;
392+
for (file_idx, (file, annotations)) in file_ann.into_iter().enumerate()
393+
{
394+
group = self.unannotated_messages(
395+
annotations,
396+
&file.name,
397+
sm,
398+
file_idx,
399+
&mut report,
400+
group,
401+
&level,
402+
);
403+
}
404+
}
359405
continue;
360406
}
361407
let mut msg = format_diag_message(&suggestion.msg, args).to_string();
@@ -645,6 +691,36 @@ impl AnnotateSnippetEmitter {
645691
}
646692
group
647693
}
694+
695+
fn suggestion_span_with_unavailable_source(
696+
&self,
697+
sm: &Arc<SourceMap>,
698+
suggestion: &CodeSuggestion,
699+
) -> Option<MultiSpan> {
700+
let spans = suggestion
701+
.substitutions
702+
.iter()
703+
.flat_map(|subst| &subst.parts)
704+
.filter_map(|part| {
705+
if sm.is_valid_span(part.span).is_err() {
706+
debug!("suggestion contains an invalid span: {:?}", part);
707+
return None;
708+
}
709+
let lines = sm.span_to_lines(part.span).ok()?;
710+
if should_show_source_code(
711+
&self.ignored_directories_in_source_blocks,
712+
sm,
713+
&lines.file,
714+
) {
715+
None
716+
} else {
717+
Some(part.span)
718+
}
719+
})
720+
.collect::<Vec<_>>();
721+
722+
if spans.is_empty() { None } else { Some(MultiSpan::from_spans(spans)) }
723+
}
648724
}
649725

650726
fn emit_to_destination(

compiler/rustc_errors/src/json.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ pub struct JsonEmitter {
5454
macro_backtrace: bool,
5555
track_diagnostics: bool,
5656
terminal_url: TerminalUrl,
57+
show_suggestions_with_unavailable_source: bool,
5758
}
5859

5960
impl JsonEmitter {
@@ -76,6 +77,7 @@ impl JsonEmitter {
7677
macro_backtrace: false,
7778
track_diagnostics: false,
7879
terminal_url: TerminalUrl::No,
80+
show_suggestions_with_unavailable_source: false,
7981
}
8082
}
8183

@@ -373,6 +375,7 @@ impl Diagnostic {
373375
.terminal_url(je.terminal_url)
374376
.ui_testing(je.ui_testing)
375377
.ignored_directories_in_source_blocks(je.ignored_directories_in_source_blocks.clone())
378+
.show_suggestions_with_unavailable_source(je.show_suggestions_with_unavailable_source)
376379
.theme(if je.json_rendered.unicode { OutputTheme::Unicode } else { OutputTheme::Ascii })
377380
.emit_diagnostic(diag);
378381

compiler/rustc_session/src/options.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2629,6 +2629,8 @@ written to standard error output)"),
26292629
"make the current crate share its generic instantiations"),
26302630
shell_argfiles: bool = (false, parse_bool, [UNTRACKED],
26312631
"allow argument files to be specified with POSIX \"shell-style\" argument quoting"),
2632+
show_suggestions_with_unavailable_source: bool = (false, parse_bool, [UNTRACKED],
2633+
"show span-only suggestions when the source code is unavailable"),
26322634
simulate_remapped_rust_src_base: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
26332635
"simulate the effect of remap-debuginfo = true at bootstrapping by remapping path \
26342636
to rust's source base directory. only meant for testing purposes"),

compiler/rustc_session/src/session.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,6 +947,8 @@ impl Session {
947947
fn default_emitter(sopts: &config::Options, source_map: Arc<SourceMap>) -> Box<DynEmitter> {
948948
let macro_backtrace = sopts.unstable_opts.macro_backtrace;
949949
let track_diagnostics = sopts.unstable_opts.track_diagnostics;
950+
let show_suggestions_with_unavailable_source =
951+
sopts.unstable_opts.show_suggestions_with_unavailable_source;
950952
let terminal_url = match sopts.unstable_opts.terminal_urls {
951953
TerminalUrl::Auto => {
952954
match (std::env::var("COLORTERM").as_deref(), std::env::var("TERM").as_deref()) {
@@ -974,6 +976,9 @@ fn default_emitter(sopts: &config::Options, source_map: Arc<SourceMap>) -> Box<D
974976
.track_diagnostics(track_diagnostics)
975977
.terminal_url(terminal_url)
976978
.theme(if unicode { OutputTheme::Unicode } else { OutputTheme::Ascii })
979+
.show_suggestions_with_unavailable_source(
980+
show_suggestions_with_unavailable_source,
981+
)
977982
.ignored_directories_in_source_blocks(
978983
sopts.unstable_opts.ignore_directory_in_diagnostics_source_blocks.clone(),
979984
);
@@ -995,7 +1000,8 @@ fn default_emitter(sopts: &config::Options, source_map: Arc<SourceMap>) -> Box<D
9951000
.diagnostic_width(sopts.diagnostic_width)
9961001
.macro_backtrace(macro_backtrace)
9971002
.track_diagnostics(track_diagnostics)
998-
.terminal_url(terminal_url),
1003+
.terminal_url(terminal_url)
1004+
.show_suggestions_with_unavailable_source(show_suggestions_with_unavailable_source),
9991005
),
10001006
}
10011007
}

src/tools/compiletest/src/runtest.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1694,6 +1694,7 @@ impl<'test> TestCx<'test> {
16941694
compiler.args(&["--json", "future-incompat"]);
16951695
}
16961696
compiler.arg("-Zui-testing");
1697+
compiler.arg("-Zshow-suggestions-with-unavailable-source");
16971698
compiler.arg("-Zdeduplicate-diagnostics=no");
16981699
}
16991700
TestMode::Ui => {
@@ -1704,6 +1705,7 @@ impl<'test> TestCx<'test> {
17041705
compiler.arg("-Ccodegen-units=1");
17051706
// Hide line numbers to reduce churn
17061707
compiler.arg("-Zui-testing");
1708+
compiler.arg("-Zshow-suggestions-with-unavailable-source");
17071709
compiler.arg("-Zdeduplicate-diagnostics=no");
17081710
compiler.arg("-Zwrite-long-types-to-disk=no");
17091711
// FIXME: use this for other modes too, for perf?
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
//@ compile-flags: -Zignore-directory-in-diagnostics-source-blocks={{src-base}}/compiletest-self-test
2+
3+
macro_rules! my_assert {
4+
($left:expr, $right:expr) => {
5+
if !($left == $right) {} //~ ERROR can't compare `&isize` with `{integer}` [E0277]
6+
};
7+
}
8+
9+
fn main() {
10+
let y: &isize = &1;
11+
my_assert!(y, 2);
12+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
error[E0277]: can't compare `&isize` with `{integer}`
2+
--> $DIR/help-show-std-source.rs:5:19
3+
|
4+
= note: no implementation for `&isize == {integer}`
5+
::: $DIR/help-show-std-source.rs:11:4
6+
|
7+
= note: in this macro invocation
8+
|
9+
= help: the trait `PartialEq<{integer}>` is not implemented for `&isize`
10+
= note: this error originates in the macro `my_assert` (in Nightly builds, run with -Z macro-backtrace for more info)
11+
help: consider dereferencing here
12+
--> $DIR/help-show-std-source.rs:11:15
13+
14+
error: aborting due to 1 previous error
15+
16+
For more information about this error, try `rustc --explain E0277`.

0 commit comments

Comments
 (0)