From 365ff62fca0e1fb6511a47f5f50c4af4df250dfa Mon Sep 17 00:00:00 2001 From: Matthew Jasper Date: Sat, 24 Aug 2019 18:25:34 +0100 Subject: [PATCH] Don't unwrap the result of `span_to_snippet` It can return `Err` due to macros being expanded across crates or files. --- src/librustc_mir/borrow_check/move_errors.rs | 84 ++++++++++--------- .../borrow_check/mutability_errors.rs | 4 +- .../ui/borrowck/move-error-snippets-ext.rs | 7 ++ src/test/ui/borrowck/move-error-snippets.rs | 23 +++++ .../ui/borrowck/move-error-snippets.stderr | 15 ++++ 5 files changed, 90 insertions(+), 43 deletions(-) create mode 100644 src/test/ui/borrowck/move-error-snippets-ext.rs create mode 100644 src/test/ui/borrowck/move-error-snippets.rs create mode 100644 src/test/ui/borrowck/move-error-snippets.stderr diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs index 738a091b0dd76..f10ff71b15e68 100644 --- a/src/librustc_mir/borrow_check/move_errors.rs +++ b/src/librustc_mir/borrow_check/move_errors.rs @@ -415,20 +415,21 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { "{:?}", move_place.ty(self.body, self.infcx.tcx).ty, ); - let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap(); - let is_option = move_ty.starts_with("std::option::Option"); - let is_result = move_ty.starts_with("std::result::Result"); - if is_option || is_result { - err.span_suggestion( - span, - &format!("consider borrowing the `{}`'s content", if is_option { - "Option" - } else { - "Result" - }), - format!("{}.as_ref()", snippet), - Applicability::MaybeIncorrect, - ); + if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { + let is_option = move_ty.starts_with("std::option::Option"); + let is_result = move_ty.starts_with("std::result::Result"); + if is_option || is_result { + err.span_suggestion( + span, + &format!("consider borrowing the `{}`'s content", if is_option { + "Option" + } else { + "Result" + }), + format!("{}.as_ref()", snippet), + Applicability::MaybeIncorrect, + ); + } } err } @@ -439,19 +440,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { err: &mut DiagnosticBuilder<'a>, span: Span, ) { - let snippet = self.infcx.tcx.sess.source_map().span_to_snippet(span).unwrap(); match error { GroupedMoveError::MovesFromPlace { mut binds_to, move_from, .. } => { - err.span_suggestion( - span, - "consider borrowing here", - format!("&{}", snippet), - Applicability::Unspecified, - ); + if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { + err.span_suggestion( + span, + "consider borrowing here", + format!("&{}", snippet), + Applicability::Unspecified, + ); + } if binds_to.is_empty() { let place_ty = move_from.ty(self.body, self.infcx.tcx).ty; @@ -517,27 +519,27 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .. })) ) = bind_to.is_user_variable { - let pat_snippet = self.infcx.tcx.sess.source_map() - .span_to_snippet(pat_span) - .unwrap(); - if pat_snippet.starts_with('&') { - let pat_snippet = pat_snippet[1..].trim_start(); - let suggestion; - let to_remove; - if pat_snippet.starts_with("mut") - && pat_snippet["mut".len()..].starts_with(Pattern_White_Space) - { - suggestion = pat_snippet["mut".len()..].trim_start(); - to_remove = "&mut"; - } else { - suggestion = pat_snippet; - to_remove = "&"; + if let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) + { + if pat_snippet.starts_with('&') { + let pat_snippet = pat_snippet[1..].trim_start(); + let suggestion; + let to_remove; + if pat_snippet.starts_with("mut") + && pat_snippet["mut".len()..].starts_with(Pattern_White_Space) + { + suggestion = pat_snippet["mut".len()..].trim_start(); + to_remove = "&mut"; + } else { + suggestion = pat_snippet; + to_remove = "&"; + } + suggestions.push(( + pat_span, + to_remove, + suggestion.to_owned(), + )); } - suggestions.push(( - pat_span, - to_remove, - suggestion.to_owned(), - )); } } } diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs index 937c6383be341..e7f37431e5009 100644 --- a/src/librustc_mir/borrow_check/mutability_errors.rs +++ b/src/librustc_mir/borrow_check/mutability_errors.rs @@ -711,8 +711,8 @@ fn annotate_struct_field( } /// If possible, suggest replacing `ref` with `ref mut`. -fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option<(String)> { - let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).unwrap(); +fn suggest_ref_mut(tcx: TyCtxt<'_>, binding_span: Span) -> Option { + let hi_src = tcx.sess.source_map().span_to_snippet(binding_span).ok()?; if hi_src.starts_with("ref") && hi_src["ref".len()..].starts_with(Pattern_White_Space) { diff --git a/src/test/ui/borrowck/move-error-snippets-ext.rs b/src/test/ui/borrowck/move-error-snippets-ext.rs new file mode 100644 index 0000000000000..c77f6c8276e70 --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets-ext.rs @@ -0,0 +1,7 @@ +// ignore-test + +macro_rules! aaa { + ($c:ident) => {{ + let a = $c; + }} +} diff --git a/src/test/ui/borrowck/move-error-snippets.rs b/src/test/ui/borrowck/move-error-snippets.rs new file mode 100644 index 0000000000000..64f9565382886 --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets.rs @@ -0,0 +1,23 @@ +// Test that we don't ICE after trying to construct a cross-file snippet #63800. + +// compile-flags: --test + +#[macro_use] +#[path = "move-error-snippets-ext.rs"] +mod move_error_snippets_ext; + +struct A; + +macro_rules! sss { + () => { + #[test] + fn fff() { + static D: A = A; + aaa!(D); //~ ERROR cannot move + } + }; +} + +sss!(); + +fn main() {} diff --git a/src/test/ui/borrowck/move-error-snippets.stderr b/src/test/ui/borrowck/move-error-snippets.stderr new file mode 100644 index 0000000000000..77463c48591bc --- /dev/null +++ b/src/test/ui/borrowck/move-error-snippets.stderr @@ -0,0 +1,15 @@ +error[E0507]: cannot move out of static item `D` + --> $DIR/move-error-snippets.rs:16:18 + | +LL | | #[macro_use] + | |__________________^ move occurs because `D` has type `A`, which does not implement the `Copy` trait +... +LL | aaa!(D); + | __________________^ +... +LL | sss!(); + | ------- in this macro invocation + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`.