diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index 5d22a8b8e30ab..5b1fffd21d184 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -350,22 +350,27 @@ impl AnnotateSnippetEmitter { "all spans must be disjoint", ); + let lo = subst.parts.iter().map(|part| part.span.lo()).min()?; + let lo_file = sm.lookup_source_file(lo); + let hi = subst.parts.iter().map(|part| part.span.hi()).max()?; + let hi_file = sm.lookup_source_file(hi); + + // The different spans might belong to different contexts, if so ignore suggestion. + if lo_file.stable_id != hi_file.stable_id { + return None; + } + + // We can't splice anything if the source is unavailable. + if !sm.ensure_source_file_source_present(&lo_file) { + return None; + } + // Account for cases where we are suggesting the same code that's already // there. This shouldn't happen often, but in some cases for multipart // suggestions it's much easier to handle it here than in the origin. subst.parts.retain(|p| is_different(sm, &p.snippet, p.span)); - let item_span = subst.parts.first()?; - let file = sm.lookup_source_file(item_span.span.lo()); - if should_show_source_code( - &self.ignored_directories_in_source_blocks, - sm, - &file, - ) { - Some(subst) - } else { - None - } + if subst.parts.is_empty() { None } else { Some(subst) } }) .collect::>(); @@ -745,14 +750,20 @@ fn shrink_file( ) -> Option<(Span, String, usize)> { let lo_byte = spans.iter().map(|s| s.lo()).min()?; let lo_loc = sm.lookup_char_pos(lo_byte); - let lo = lo_loc.file.line_bounds(lo_loc.line.saturating_sub(1)).start; let hi_byte = spans.iter().map(|s| s.hi()).max()?; let hi_loc = sm.lookup_char_pos(hi_byte); - let hi = lo_loc.file.line_bounds(hi_loc.line.saturating_sub(1)).end; + + if lo_loc.file.stable_id != hi_loc.file.stable_id { + // this may happen when spans cross file boundaries due to macro expansion. + return None; + } + + let lo = lo_loc.file.line_bounds(lo_loc.line.saturating_sub(1)).start; + let hi = hi_loc.file.line_bounds(hi_loc.line.saturating_sub(1)).end; let bounding_span = Span::with_root_ctxt(lo, hi); - let source = sm.span_to_snippet(bounding_span).unwrap_or_default(); + let source = sm.span_to_snippet(bounding_span).ok()?; let offset_line = sm.doctest_offset_line(file_name, lo_loc.line); Some((bounding_span, source, offset_line)) diff --git a/tests/ui/delegation/ice-line-bounds-issue-148732.rs b/tests/ui/delegation/ice-line-bounds-issue-148732.rs new file mode 100644 index 0000000000000..699e7d86f2581 --- /dev/null +++ b/tests/ui/delegation/ice-line-bounds-issue-148732.rs @@ -0,0 +1,8 @@ +reuse a as b { + //~^ ERROR cannot find function `a` in this scope + //~| ERROR functions delegation is not yet fully implemented + dbg!(b); + //~^ ERROR missing lifetime specifier +} + +fn main() {} diff --git a/tests/ui/delegation/ice-line-bounds-issue-148732.stderr b/tests/ui/delegation/ice-line-bounds-issue-148732.stderr new file mode 100644 index 0000000000000..c65b1560818d7 --- /dev/null +++ b/tests/ui/delegation/ice-line-bounds-issue-148732.stderr @@ -0,0 +1,34 @@ +error[E0106]: missing lifetime specifier + --> $DIR/ice-line-bounds-issue-148732.rs:4:5 + | +LL | dbg!(b); + | ^^^^^^^ expected named lifetime parameter + | + = note: this error originates in the macro `dbg` (in Nightly builds, run with -Z macro-backtrace for more info) + | + +error[E0425]: cannot find function `a` in this scope + --> $DIR/ice-line-bounds-issue-148732.rs:1:7 + | +LL | reuse a as b { + | ^ not found in this scope + +error[E0658]: functions delegation is not yet fully implemented + --> $DIR/ice-line-bounds-issue-148732.rs:1:1 + | +LL | / reuse a as b { +LL | | +LL | | +LL | | dbg!(b); +LL | | +LL | | } + | |_^ + | + = note: see issue #118212 for more information + = help: add `#![feature(fn_delegation)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0106, E0425, E0658. +For more information about an error, try `rustc --explain E0106`. diff --git a/tests/ui/structs/ice-line-bounds-issue-148684.rs b/tests/ui/structs/ice-line-bounds-issue-148684.rs new file mode 100644 index 0000000000000..56065fb0de309 --- /dev/null +++ b/tests/ui/structs/ice-line-bounds-issue-148684.rs @@ -0,0 +1,9 @@ +struct A { + b: Vec, + c: usize, +} + +fn main() { + A(2, vec![]) + //~^ ERROR expected function, tuple struct or tuple variant, found struct `A` +} diff --git a/tests/ui/structs/ice-line-bounds-issue-148684.stderr b/tests/ui/structs/ice-line-bounds-issue-148684.stderr new file mode 100644 index 0000000000000..f26d96cd1172b --- /dev/null +++ b/tests/ui/structs/ice-line-bounds-issue-148684.stderr @@ -0,0 +1,16 @@ +error[E0423]: expected function, tuple struct or tuple variant, found struct `A` + --> $DIR/ice-line-bounds-issue-148684.rs:7:5 + | +LL | / struct A { +LL | | b: Vec, +LL | | c: usize, +LL | | } + | |_- `A` defined here +... +LL | A(2, vec![]) + | ^^^^^^^^^^^^ + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0423`.