diff options
Diffstat (limited to 'compiler/rustc_borrowck/src/diagnostics/mod.rs')
-rw-r--r-- | compiler/rustc_borrowck/src/diagnostics/mod.rs | 123 |
1 files changed, 86 insertions, 37 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 534d9ecae..4e2271a30 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -70,7 +70,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location: Location, place: PlaceRef<'tcx>, diag: &mut Diagnostic, - ) { + ) -> bool { debug!("add_moved_or_invoked_closure_note: location={:?} place={:?}", location, place); let mut target = place.local_or_deref_local(); for stmt in &self.body[location.block].statements[location.statement_index..] { @@ -78,7 +78,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let StatementKind::Assign(box (into, Rvalue::Use(from))) = &stmt.kind { debug!("add_fnonce_closure_note: into={:?} from={:?}", into, from); match from { - Operand::Copy(ref place) | Operand::Move(ref place) + Operand::Copy(place) | Operand::Move(place) if target == place.local_or_deref_local() => { target = into.local_or_deref_local() @@ -101,12 +101,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("add_moved_or_invoked_closure_note: id={:?}", id); if Some(self.infcx.tcx.parent(id)) == self.infcx.tcx.lang_items().fn_once_trait() { let closure = match args.first() { - Some(Operand::Copy(ref place)) | Some(Operand::Move(ref place)) + Some(Operand::Copy(place) | Operand::Move(place)) if target == place.local_or_deref_local() => { place.local_or_deref_local().unwrap() } - _ => return, + _ => return false, }; debug!("add_moved_or_invoked_closure_note: closure={:?}", closure); @@ -125,7 +125,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::place_to_string_for_capture(self.infcx.tcx, hir_place) ), ); - return; + return true; } } } @@ -149,9 +149,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ty::place_to_string_for_capture(self.infcx.tcx, hir_place) ), ); + return true; } } } + false } /// End-user visible description of `place` if one can be found. @@ -350,7 +352,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { def.non_enum_variant() }; - if !including_tuple_field.0 && variant.ctor_kind == CtorKind::Fn { + if !including_tuple_field.0 && variant.ctor_kind() == Some(CtorKind::Fn) { return None; } Some(variant.fields[field.index()].name.to_string()) @@ -437,9 +439,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if !is_terminator { continue; } else if let Some(Terminator { - kind: TerminatorKind::Call { ref func, from_hir_call: false, .. }, + kind: TerminatorKind::Call { func, from_hir_call: false, .. }, .. - }) = bbd.terminator + }) = &bbd.terminator { if let Some(source) = BorrowedContentSource::from_call(func.ty(self.body, tcx), tcx) @@ -588,22 +590,45 @@ impl UseSpans<'_> { } } - // Add a span label to the arguments of the closure, if it exists. + /// Add a span label to the arguments of the closure, if it exists. pub(super) fn args_span_label(self, err: &mut Diagnostic, message: impl Into<String>) { if let UseSpans::ClosureUse { args_span, .. } = self { err.span_label(args_span, message); } } - // Add a span label to the use of the captured variable, if it exists. - // only adds label to the `path_span` - pub(super) fn var_span_label_path_only(self, err: &mut Diagnostic, message: impl Into<String>) { - if let UseSpans::ClosureUse { path_span, .. } = self { - err.span_label(path_span, message); + /// Add a span label to the use of the captured variable, if it exists. + /// only adds label to the `path_span` + pub(super) fn var_path_only_subdiag( + self, + err: &mut Diagnostic, + action: crate::InitializationRequiringAction, + ) { + use crate::session_diagnostics::CaptureVarPathUseCause::*; + use crate::InitializationRequiringAction::*; + if let UseSpans::ClosureUse { generator_kind, path_span, .. } = self { + match generator_kind { + Some(_) => { + err.subdiagnostic(match action { + Borrow => BorrowInGenerator { path_span }, + MatchOn | Use => UseInGenerator { path_span }, + Assignment => AssignInGenerator { path_span }, + PartialAssignment => AssignPartInGenerator { path_span }, + }); + } + None => { + err.subdiagnostic(match action { + Borrow => BorrowInClosure { path_span }, + MatchOn | Use => UseInClosure { path_span }, + Assignment => AssignInClosure { path_span }, + PartialAssignment => AssignPartInClosure { path_span }, + }); + } + } } } - // Add a span label to the use of the captured variable, if it exists. + /// Add a span label to the use of the captured variable, if it exists. pub(super) fn var_span_label( self, err: &mut Diagnostic, @@ -623,6 +648,35 @@ impl UseSpans<'_> { } } + /// Add a subdiagnostic to the use of the captured variable, if it exists. + pub(super) fn var_subdiag( + self, + err: &mut Diagnostic, + kind: Option<rustc_middle::mir::BorrowKind>, + f: impl Fn(Option<GeneratorKind>, Span) -> crate::session_diagnostics::CaptureVarCause, + ) { + use crate::session_diagnostics::CaptureVarKind::*; + if let UseSpans::ClosureUse { generator_kind, capture_kind_span, path_span, .. } = self { + if capture_kind_span != path_span { + err.subdiagnostic(match kind { + Some(kd) => match kd { + rustc_middle::mir::BorrowKind::Shared + | rustc_middle::mir::BorrowKind::Shallow + | rustc_middle::mir::BorrowKind::Unique => { + Immute { kind_span: capture_kind_span } + } + + rustc_middle::mir::BorrowKind::Mut { .. } => { + Mut { kind_span: capture_kind_span } + } + }, + None => Move { kind_span: capture_kind_span }, + }); + }; + err.subdiagnostic(f(generator_kind, path_span)); + } + } + /// Returns `false` if this place is not used in a closure. pub(super) fn for_closure(&self) -> bool { match *self { @@ -757,33 +811,30 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }; debug!("move_spans: moved_place={:?} location={:?} stmt={:?}", moved_place, location, stmt); - if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = stmt.kind { - match **kind { - AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) => { - debug!("move_spans: def_id={:?} places={:?}", def_id, places); - if let Some((args_span, generator_kind, capture_kind_span, path_span)) = - self.closure_span(def_id, moved_place, places) - { - return ClosureUse { - generator_kind, - args_span, - capture_kind_span, - path_span, - }; - } - } - _ => {} + if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind + && let AggregateKind::Closure(def_id, _) | AggregateKind::Generator(def_id, _, _) = **kind + { + debug!("move_spans: def_id={:?} places={:?}", def_id, places); + if let Some((args_span, generator_kind, capture_kind_span, path_span)) = + self.closure_span(def_id, moved_place, places) + { + return ClosureUse { + generator_kind, + args_span, + capture_kind_span, + path_span, + }; } } // StatementKind::FakeRead only contains a def_id if they are introduced as a result // of pattern matching within a closure. - if let StatementKind::FakeRead(box (cause, ref place)) = stmt.kind { + if let StatementKind::FakeRead(box (cause, place)) = stmt.kind { match cause { FakeReadCause::ForMatchedPlace(Some(closure_def_id)) | FakeReadCause::ForLet(Some(closure_def_id)) => { debug!("move_spans: def_id={:?} place={:?}", closure_def_id, place); - let places = &[Operand::Move(*place)]; + let places = &[Operand::Move(place)]; if let Some((args_span, generator_kind, capture_kind_span, path_span)) = self.closure_span(closure_def_id, moved_place, places) { @@ -870,7 +921,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { debug!("borrow_spans: use_span={:?} location={:?}", use_span, location); let target = match self.body[location.block].statements.get(location.statement_index) { - Some(&Statement { kind: StatementKind::Assign(box (ref place, _)), .. }) => { + Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) => { if let Some(local) = place.as_local() { local } else { @@ -886,9 +937,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } for stmt in &self.body[location.block].statements[location.statement_index + 1..] { - if let StatementKind::Assign(box (_, Rvalue::Aggregate(ref kind, ref places))) = - stmt.kind - { + if let StatementKind::Assign(box (_, Rvalue::Aggregate(kind, places))) = &stmt.kind { let (&def_id, is_generator) = match kind { box AggregateKind::Closure(def_id, _) => (def_id, false), box AggregateKind::Generator(def_id, _, _) => (def_id, true), |