From fa199c5f27cf09fa02ff7632a713ea613f731944 Mon Sep 17 00:00:00 2001 From: Yuki Okushi Date: Wed, 11 Dec 2019 23:04:29 +0900 Subject: [PATCH] Don't suggest wrong snippet in closure --- .../borrow_check/diagnostics/move_errors.rs | 16 ++++++++++++---- .../ui/suggestions/option-content-move2.rs | 16 ++++++++++++++++ .../ui/suggestions/option-content-move2.stderr | 18 ++++++++++++++++++ 3 files changed, 46 insertions(+), 4 deletions(-) create mode 100644 src/test/ui/suggestions/option-content-move2.rs create mode 100644 src/test/ui/suggestions/option-content-move2.stderr diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs index 938836db9ae..cc634101f0a 100644 --- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs +++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs @@ -223,18 +223,24 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn report(&mut self, error: GroupedMoveError<'tcx>) { let (mut err, err_span) = { - let (span, original_path, kind): (Span, &Place<'tcx>, &IllegalMoveOriginKind<'_>) = + let (span, use_spans, original_path, kind,): + ( + Span, + Option, + &Place<'tcx>, + &IllegalMoveOriginKind<'_>, + ) = match error { GroupedMoveError::MovesFromPlace { span, ref original_path, ref kind, .. } | GroupedMoveError::MovesFromValue { span, ref original_path, ref kind, .. } => { - (span, original_path, kind) + (span, None, original_path, kind) } GroupedMoveError::OtherIllegalMove { use_spans, ref original_path, ref kind } => { - (use_spans.args_or_use(), original_path, kind) + (use_spans.args_or_use(), Some(use_spans), original_path, kind) }, }; debug!("report: original_path={:?} span={:?}, kind={:?} \ @@ -250,6 +256,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { original_path, target_place, span, + use_spans, ) } IllegalMoveOriginKind::InteriorOfTypeWithDestructor { container_ty: ty } => { @@ -296,6 +303,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { move_place: &Place<'tcx>, deref_target_place: &Place<'tcx>, span: Span, + use_spans: Option, ) -> DiagnosticBuilder<'a> { // Inspect the type of the content behind the // borrow to provide feedback about why this @@ -416,7 +424,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { 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 { + if (is_option || is_result) && use_spans.map_or(true, |v| !v.for_closure()) { err.span_suggestion( span, &format!("consider borrowing the `{}`'s content", if is_option { diff --git a/src/test/ui/suggestions/option-content-move2.rs b/src/test/ui/suggestions/option-content-move2.rs new file mode 100644 index 00000000000..88e8a5b7aee --- /dev/null +++ b/src/test/ui/suggestions/option-content-move2.rs @@ -0,0 +1,16 @@ +struct NotCopyable; + +fn func H, H: FnMut()>(_: F) {} + +fn parse() { + let mut var = None; + func(|| { + // Shouldn't suggest `move ||.as_ref()` here + move || { + //~^ ERROR: cannot move out of `var` + var = Some(NotCopyable); + } + }); +} + +fn main() {} diff --git a/src/test/ui/suggestions/option-content-move2.stderr b/src/test/ui/suggestions/option-content-move2.stderr new file mode 100644 index 00000000000..71f745374e5 --- /dev/null +++ b/src/test/ui/suggestions/option-content-move2.stderr @@ -0,0 +1,18 @@ +error[E0507]: cannot move out of `var`, a captured variable in an `FnMut` closure + --> $DIR/option-content-move2.rs:9:9 + | +LL | let mut var = None; + | ------- captured outer variable +... +LL | move || { + | ^^^^^^^ move out of `var` occurs here +LL | +LL | var = Some(NotCopyable); + | --- + | | + | move occurs because `var` has type `std::option::Option`, which does not implement the `Copy` trait + | move occurs due to use in closure + +error: aborting due to previous error + +For more information about this error, try `rustc --explain E0507`.