diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-17 12:18:32 +0000 |
commit | 4547b622d8d29df964fa2914213088b148c498fc (patch) | |
tree | 9fc6b25f3c3add6b745be9a2400a6e96140046e9 /compiler/rustc_borrowck/src/diagnostics | |
parent | Releasing progress-linux version 1.66.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-4547b622d8d29df964fa2914213088b148c498fc.tar.xz rustc-4547b622d8d29df964fa2914213088b148c498fc.zip |
Merging upstream version 1.67.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_borrowck/src/diagnostics')
10 files changed, 424 insertions, 248 deletions
diff --git a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs index 02071ed6b..1550958ab 100644 --- a/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/bound_region_errors.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed}; use rustc_infer::infer::canonical::Canonical; use rustc_infer::infer::error_reporting::nice_region_error::NiceRegionError; @@ -5,14 +8,14 @@ use rustc_infer::infer::region_constraints::Constraint; use rustc_infer::infer::region_constraints::RegionConstraintData; use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::infer::{InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt as _}; -use rustc_infer::traits::{Normalized, ObligationCause, TraitEngine, TraitEngineExt}; +use rustc_infer::traits::ObligationCause; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::RegionVid; use rustc_middle::ty::UniverseIndex; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::Span; use rustc_trait_selection::traits::query::type_op; -use rustc_trait_selection::traits::{SelectionContext, TraitEngineExt as _}; +use rustc_trait_selection::traits::ObligationCtxt; use rustc_traits::{type_op_ascribe_user_type_with_span, type_op_prove_predicate_with_cause}; use std::fmt; @@ -158,6 +161,7 @@ trait TypeOpInfo<'tcx> { error_region: Option<ty::Region<'tcx>>, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>; + #[instrument(level = "debug", skip(self, mbcx))] fn report_error( &self, mbcx: &mut MirBorrowckCtxt<'_, 'tcx>, @@ -167,6 +171,7 @@ trait TypeOpInfo<'tcx> { ) { let tcx = mbcx.infcx.tcx; let base_universe = self.base_universe(); + debug!(?base_universe); let Some(adjusted_universe) = placeholder.universe.as_u32().checked_sub(base_universe.as_u32()) @@ -238,11 +243,11 @@ impl<'tcx> TypeOpInfo<'tcx> for PredicateQuery<'tcx> { placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { - let (ref infcx, key, _) = + let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); - type_op_prove_predicate_with_cause(infcx, &mut *fulfill_cx, key, cause); - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) + let ocx = ObligationCtxt::new(&infcx); + type_op_prove_predicate_with_cause(&ocx, key, cause); + try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) } } @@ -279,24 +284,20 @@ where placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { - let (ref infcx, key, _) = + let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); - - let mut selcx = SelectionContext::new(infcx); + let ocx = ObligationCtxt::new(&infcx); // FIXME(lqd): Unify and de-duplicate the following with the actual // `rustc_traits::type_op::type_op_normalize` query to allow the span we need in the // `ObligationCause`. The normalization results are currently different between - // `AtExt::normalize` used in the query and `normalize` called below: the former fails - // to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. Check - // after #85499 lands to see if its fixes have erased this difference. + // `QueryNormalizeExt::query_normalize` used in the query and `normalize` called below: + // the former fails to normalize the `nll/relate_tys/impl-fn-ignore-binder-via-bottom.rs` test. + // Check after #85499 lands to see if its fixes have erased this difference. let (param_env, value) = key.into_parts(); - let Normalized { value: _, obligations } = - rustc_trait_selection::traits::normalize(&mut selcx, param_env, cause, value.value); - fulfill_cx.register_predicate_obligations(infcx, obligations); + let _ = ocx.normalize(&cause, param_env, value.value); - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) + try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) } } @@ -327,11 +328,11 @@ impl<'tcx> TypeOpInfo<'tcx> for AscribeUserTypeQuery<'tcx> { placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { - let (ref infcx, key, _) = + let (infcx, key, _) = mbcx.infcx.tcx.infer_ctxt().build_with_canonical(cause.span, &self.canonical_query); - let mut fulfill_cx = <dyn TraitEngine<'_>>::new(infcx.tcx); - type_op_ascribe_user_type_with_span(infcx, &mut *fulfill_cx, key, Some(cause.span)).ok()?; - try_extract_error_from_fulfill_cx(fulfill_cx, infcx, placeholder_region, error_region) + let ocx = ObligationCtxt::new(&infcx); + type_op_ascribe_user_type_with_span(&ocx, key, Some(cause.span)).ok()?; + try_extract_error_from_fulfill_cx(&ocx, placeholder_region, error_region) } } @@ -372,28 +373,28 @@ impl<'tcx> TypeOpInfo<'tcx> for crate::type_check::InstantiateOpaqueType<'tcx> { } } -#[instrument(skip(fulfill_cx, infcx), level = "debug")] +#[instrument(skip(ocx), level = "debug")] fn try_extract_error_from_fulfill_cx<'tcx>( - mut fulfill_cx: Box<dyn TraitEngine<'tcx> + 'tcx>, - infcx: &InferCtxt<'tcx>, + ocx: &ObligationCtxt<'_, 'tcx>, placeholder_region: ty::Region<'tcx>, error_region: Option<ty::Region<'tcx>>, ) -> Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>> { // We generally shouldn't have errors here because the query was // already run, but there's no point using `delay_span_bug` // when we're going to emit an error here anyway. - let _errors = fulfill_cx.select_all_or_error(infcx); - let region_constraints = infcx.with_region_constraints(|r| r.clone()); + let _errors = ocx.select_all_or_error(); + let region_constraints = ocx.infcx.with_region_constraints(|r| r.clone()); try_extract_error_from_region_constraints( - infcx, + ocx.infcx, placeholder_region, error_region, ®ion_constraints, - |vid| infcx.region_var_origin(vid), - |vid| infcx.universe_of_region(infcx.tcx.mk_region(ty::ReVar(vid))), + |vid| ocx.infcx.region_var_origin(vid), + |vid| ocx.infcx.universe_of_region(ocx.infcx.tcx.mk_region(ty::ReVar(vid))), ) } +#[instrument(level = "debug", skip(infcx, region_var_origin, universe_of_region))] fn try_extract_error_from_region_constraints<'tcx>( infcx: &InferCtxt<'tcx>, placeholder_region: ty::Region<'tcx>, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 583bc2e28..5e3745f17 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -7,7 +7,7 @@ use rustc_errors::{ }; use rustc_hir as hir; use rustc_hir::intravisit::{walk_block, walk_expr, Visitor}; -use rustc_hir::{AsyncGeneratorKind, GeneratorKind}; +use rustc_hir::{AsyncGeneratorKind, GeneratorKind, LangItem}; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::ObligationCause; use rustc_middle::mir::tcx::PlaceTy; @@ -23,7 +23,6 @@ use rustc_span::hygiene::DesugaringKind; use rustc_span::symbol::sym; use rustc_span::{BytePos, Span, Symbol}; use rustc_trait_selection::infer::InferCtxtExt; -use rustc_trait_selection::traits::TraitEngineExt as _; use crate::borrow_set::TwoPhaseActivation; use crate::borrowck_errors; @@ -168,10 +167,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); } - self.add_moved_or_invoked_closure_note(location, used_place, &mut err); + let closure = self.add_moved_or_invoked_closure_note(location, used_place, &mut err); let mut is_loop_move = false; let mut in_pattern = false; + let mut seen_spans = FxHashSet::default(); for move_site in &move_site_vec { let move_out = self.move_data.moves[(*move_site).moi]; @@ -192,43 +192,28 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { is_loop_move = true; } - self.explain_captures( - &mut err, - span, - move_span, - move_spans, - *moved_place, - partially_str, - loop_message, - move_msg, - is_loop_move, - maybe_reinitialized_locations.is_empty(), - ); - - if let (UseSpans::PatUse(span), []) = - (move_spans, &maybe_reinitialized_locations[..]) - { - if maybe_reinitialized_locations.is_empty() { - err.span_suggestion_verbose( - span.shrink_to_lo(), - &format!( - "borrow this field in the pattern to avoid moving {}", - self.describe_place(moved_place.as_ref()) - .map(|n| format!("`{}`", n)) - .unwrap_or_else(|| "the value".to_string()) - ), - "ref ", - Applicability::MachineApplicable, - ); - in_pattern = true; + if !seen_spans.contains(&move_span) { + if !closure { + self.suggest_ref_or_clone(mpi, move_span, &mut err, &mut in_pattern); } + + self.explain_captures( + &mut err, + span, + move_span, + move_spans, + *moved_place, + partially_str, + loop_message, + move_msg, + is_loop_move, + maybe_reinitialized_locations.is_empty(), + ); } + seen_spans.insert(move_span); } - use_spans.var_span_label_path_only( - &mut err, - format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), - ); + use_spans.var_path_only_subdiag(&mut err, desired_action); if !is_loop_move { err.span_label( @@ -280,7 +265,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { DescribePlaceOpt { including_downcast: true, including_tuple_field: true }, ); let note_msg = match opt_name { - Some(ref name) => format!("`{}`", name), + Some(name) => format!("`{}`", name), None => "value".to_owned(), }; if self.suggest_borrow_fn_like(&mut err, ty, &move_site_vec, ¬e_msg) { @@ -321,6 +306,160 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } + fn suggest_ref_or_clone( + &mut self, + mpi: MovePathIndex, + move_span: Span, + err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, + in_pattern: &mut bool, + ) { + struct ExpressionFinder<'hir> { + expr_span: Span, + expr: Option<&'hir hir::Expr<'hir>>, + pat: Option<&'hir hir::Pat<'hir>>, + parent_pat: Option<&'hir hir::Pat<'hir>>, + } + impl<'hir> Visitor<'hir> for ExpressionFinder<'hir> { + fn visit_expr(&mut self, e: &'hir hir::Expr<'hir>) { + if e.span == self.expr_span { + self.expr = Some(e); + } + hir::intravisit::walk_expr(self, e); + } + fn visit_pat(&mut self, p: &'hir hir::Pat<'hir>) { + if p.span == self.expr_span { + self.pat = Some(p); + } + if let hir::PatKind::Binding(hir::BindingAnnotation::NONE, _, i, sub) = p.kind { + if i.span == self.expr_span || p.span == self.expr_span { + self.pat = Some(p); + } + // Check if we are in a situation of `ident @ ident` where we want to suggest + // `ref ident @ ref ident` or `ref ident @ Struct { ref ident }`. + if let Some(subpat) = sub && self.pat.is_none() { + self.visit_pat(subpat); + if self.pat.is_some() { + self.parent_pat = Some(p); + } + return; + } + } + hir::intravisit::walk_pat(self, p); + } + } + let hir = self.infcx.tcx.hir(); + if let Some(hir::Node::Item(hir::Item { + kind: hir::ItemKind::Fn(_, _, body_id), + .. + })) = hir.find(hir.local_def_id_to_hir_id(self.mir_def_id())) + && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) + { + let place = &self.move_data.move_paths[mpi].place; + let span = place.as_local() + .map(|local| self.body.local_decls[local].source_info.span); + let mut finder = ExpressionFinder { + expr_span: move_span, + expr: None, + pat: None, + parent_pat: None, + }; + finder.visit_expr(expr); + if let Some(span) = span && let Some(expr) = finder.expr { + for (_, expr) in hir.parent_iter(expr.hir_id) { + if let hir::Node::Expr(expr) = expr { + if expr.span.contains(span) { + // If the let binding occurs within the same loop, then that + // loop isn't relevant, like in the following, the outermost `loop` + // doesn't play into `x` being moved. + // ``` + // loop { + // let x = String::new(); + // loop { + // foo(x); + // } + // } + // ``` + break; + } + if let hir::ExprKind::Loop(.., loop_span) = expr.kind { + err.span_label(loop_span, "inside of this loop"); + } + } + } + let typeck = self.infcx.tcx.typeck(self.mir_def_id()); + let hir_id = hir.get_parent_node(expr.hir_id); + if let Some(parent) = hir.find(hir_id) { + let (def_id, args, offset) = if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::MethodCall(_, _, args, _) = parent_expr.kind + && let Some(def_id) = typeck.type_dependent_def_id(parent_expr.hir_id) + { + (def_id.as_local(), args, 1) + } else if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call, args) = parent_expr.kind + && let ty::FnDef(def_id, _) = typeck.node_type(call.hir_id).kind() + { + (def_id.as_local(), args, 0) + } else { + (None, &[][..], 0) + }; + if let Some(def_id) = def_id + && let Some(node) = hir.find(hir.local_def_id_to_hir_id(def_id)) + && let Some(fn_sig) = node.fn_sig() + && let Some(ident) = node.ident() + && let Some(pos) = args.iter().position(|arg| arg.hir_id == expr.hir_id) + && let Some(arg) = fn_sig.decl.inputs.get(pos + offset) + { + let mut span: MultiSpan = arg.span.into(); + span.push_span_label( + arg.span, + "this parameter takes ownership of the value".to_string(), + ); + let descr = match node.fn_kind() { + Some(hir::intravisit::FnKind::ItemFn(..)) | None => "function", + Some(hir::intravisit::FnKind::Method(..)) => "method", + Some(hir::intravisit::FnKind::Closure) => "closure", + }; + span.push_span_label( + ident.span, + format!("in this {descr}"), + ); + err.span_note( + span, + format!( + "consider changing this parameter type in {descr} `{ident}` to \ + borrow instead if owning the value isn't necessary", + ), + ); + } + let place = &self.move_data.move_paths[mpi].place; + let ty = place.ty(self.body, self.infcx.tcx).ty; + if let hir::Node::Expr(parent_expr) = parent + && let hir::ExprKind::Call(call_expr, _) = parent_expr.kind + && let hir::ExprKind::Path( + hir::QPath::LangItem(LangItem::IntoIterIntoIter, _, _) + ) = call_expr.kind + { + // Do not suggest `.clone()` in a `for` loop, we already suggest borrowing. + } else { + self.suggest_cloning(err, ty, move_span); + } + } + } + if let Some(pat) = finder.pat { + *in_pattern = true; + let mut sugg = vec![(pat.span.shrink_to_lo(), "ref ".to_string())]; + if let Some(pat) = finder.parent_pat { + sugg.insert(0, (pat.span.shrink_to_lo(), "ref ".to_string())); + } + err.multipart_suggestion_verbose( + "borrow this binding in the pattern to avoid moving the value", + sugg, + Applicability::MachineApplicable, + ); + } + } + } + fn report_use_of_uninitialized( &self, mpi: MovePathIndex, @@ -405,10 +544,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let used = desired_action.as_general_verb_in_past_tense(); let mut err = struct_span_err!(self, span, E0381, "{used} binding {desc}{isnt_initialized}"); - use_spans.var_span_label_path_only( - &mut err, - format!("{} occurs due to use{}", desired_action.as_noun(), use_spans.describe()), - ); + use_spans.var_path_only_subdiag(&mut err, desired_action); if let InitializationRequiringAction::PartialAssignment | InitializationRequiringAction::Assignment = desired_action @@ -496,12 +632,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // but the type has region variables, so erase those. tcx.infer_ctxt() .build() - .type_implements_trait( - default_trait, - tcx.erase_regions(ty), - ty::List::empty(), - param_env, - ) + .type_implements_trait(default_trait, [tcx.erase_regions(ty)], param_env) .must_apply_modulo_regions() }; @@ -535,15 +666,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let tcx = self.infcx.tcx; // Find out if the predicates show that the type is a Fn or FnMut - let find_fn_kind_from_did = - |predicates: ty::EarlyBinder<&[(ty::Predicate<'tcx>, Span)]>, substs| { - predicates.0.iter().find_map(|(pred, _)| { + let find_fn_kind_from_did = |predicates: ty::EarlyBinder< + &[(ty::Predicate<'tcx>, Span)], + >, + substs| { + predicates.0.iter().find_map(|(pred, _)| { let pred = if let Some(substs) = substs { predicates.rebind(*pred).subst(tcx, substs).kind().skip_binder() } else { pred.kind().skip_binder() }; - if let ty::PredicateKind::Trait(pred) = pred && pred.self_ty() == ty { + if let ty::PredicateKind::Clause(ty::Clause::Trait(pred)) = pred && pred.self_ty() == ty { if Some(pred.def_id()) == tcx.lang_items().fn_trait() { return Some(hir::Mutability::Not); } else if Some(pred.def_id()) == tcx.lang_items().fn_mut_trait() { @@ -552,7 +685,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } None }) - }; + }; // If the type is opaque/param/closure, and it is Fn or FnMut, let's suggest (mutably) // borrowing the type, since `&mut F: FnMut` iff `F: FnMut` and similarly for `Fn`. @@ -583,25 +716,41 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let moved_place = &self.move_data.move_paths[move_out.path].place; let move_spans = self.move_spans(moved_place.as_ref(), move_out.source); let move_span = move_spans.args_or_use(); - let suggestion = if borrow_level == hir::Mutability::Mut { - "&mut ".to_string() - } else { - "&".to_string() - }; + let suggestion = borrow_level.ref_prefix_str().to_owned(); (move_span.shrink_to_lo(), suggestion) }) .collect(); err.multipart_suggestion_verbose( - &format!( - "consider {}borrowing {value_name}", - if borrow_level == hir::Mutability::Mut { "mutably " } else { "" } - ), + format!("consider {}borrowing {value_name}", borrow_level.mutably_str()), sugg, Applicability::MaybeIncorrect, ); true } + fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { + let tcx = self.infcx.tcx; + // Try to find predicates on *generic params* that would allow copying `ty` + let infcx = tcx.infer_ctxt().build(); + + if let Some(clone_trait_def) = tcx.lang_items().clone_trait() + && infcx + .type_implements_trait( + clone_trait_def, + [tcx.erase_regions(ty)], + self.param_env, + ) + .must_apply_modulo_regions() + { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "consider cloning the value if the performance cost is acceptable", + ".clone()".to_string(), + Applicability::MachineApplicable, + ); + } + } + fn suggest_adding_copy_bounds(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { let tcx = self.infcx.tcx; let generics = tcx.generics_of(self.mir_def_id()); @@ -613,36 +762,34 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { else { return; }; // Try to find predicates on *generic params* that would allow copying `ty` let infcx = tcx.infer_ctxt().build(); - let mut fulfill_cx = <dyn rustc_infer::traits::TraitEngine<'_>>::new(infcx.tcx); - - let copy_did = infcx.tcx.lang_items().copy_trait().unwrap(); + let copy_did = infcx.tcx.require_lang_item(LangItem::Copy, Some(span)); let cause = ObligationCause::new( span, self.mir_hir_id(), rustc_infer::traits::ObligationCauseCode::MiscObligation, ); - fulfill_cx.register_bound( + let errors = rustc_trait_selection::traits::fully_solve_bound( &infcx, + cause, self.param_env, // Erase any region vids from the type, which may not be resolved infcx.tcx.erase_regions(ty), copy_did, - cause, ); - // Select all, including ambiguous predicates - let errors = fulfill_cx.select_all_or_error(&infcx); // Only emit suggestion if all required predicates are on generic let predicates: Result<Vec<_>, _> = errors .into_iter() .map(|err| match err.obligation.predicate.kind().skip_binder() { - PredicateKind::Trait(predicate) => match predicate.self_ty().kind() { - ty::Param(param_ty) => Ok(( - generics.type_param(param_ty, tcx), - predicate.trait_ref.print_only_trait_path().to_string(), - )), - _ => Err(()), - }, + PredicateKind::Clause(ty::Clause::Trait(predicate)) => { + match predicate.self_ty().kind() { + ty::Param(param_ty) => Ok(( + generics.type_param(param_ty, tcx), + predicate.trait_ref.print_only_trait_path().to_string(), + )), + _ => Err(()), + } + } _ => Err(()), }) .collect(); @@ -678,16 +825,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let move_spans = self.move_spans(place.as_ref(), location); let span = move_spans.args_or_use(); - let mut err = - self.cannot_move_when_borrowed(span, &self.describe_any_place(place.as_ref())); - err.span_label(borrow_span, format!("borrow of {} occurs here", borrow_msg)); - err.span_label(span, format!("move out of {} occurs here", value_msg)); - - borrow_spans.var_span_label_path_only( - &mut err, - format!("borrow occurs due to use{}", borrow_spans.describe()), + let mut err = self.cannot_move_when_borrowed( + span, + borrow_span, + &self.describe_any_place(place.as_ref()), + &borrow_msg, + &value_msg, ); + borrow_spans.var_path_only_subdiag(&mut err, crate::InitializationRequiringAction::Borrow); + move_spans.var_span_label( &mut err, format!("move occurs due to use{}", move_spans.describe()), @@ -729,16 +876,15 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { borrow_span, &self.describe_any_place(borrow.borrowed_place.as_ref()), ); - - borrow_spans.var_span_label( - &mut err, - { - let place = &borrow.borrowed_place; - let desc_place = self.describe_any_place(place.as_ref()); - format!("borrow occurs due to use of {}{}", desc_place, borrow_spans.describe()) - }, - "mutable", - ); + borrow_spans.var_subdiag(&mut err, Some(borrow.kind), |kind, var_span| { + use crate::session_diagnostics::CaptureVarCause::*; + let place = &borrow.borrowed_place; + let desc_place = self.describe_any_place(place.as_ref()); + match kind { + Some(_) => BorrowUsePlaceGenerator { place: desc_place, var_span }, + None => BorrowUsePlaceClosure { place: desc_place, var_span }, + } + }); self.explain_why_borrow_contains_point(location, borrow, None) .add_explanation_to_diagnostic( @@ -1271,7 +1417,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // then just use the normal error. The closure isn't escaping // and `move` will not help here. ( - Some(ref name), + Some(name), BorrowExplanation::MustBeValidFor { category: category @ (ConstraintCategory::Return(_) @@ -1292,7 +1438,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { &format!("`{}`", name), ), ( - ref name, + name, BorrowExplanation::MustBeValidFor { category: ConstraintCategory::Assignment, from_closure: false, @@ -1304,7 +1450,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { span, .. }, - ) => self.report_escaping_data(borrow_span, name, upvar_span, upvar_name, span), + ) => self.report_escaping_data(borrow_span, &name, upvar_span, upvar_name, span), (Some(name), explanation) => self.report_local_value_does_not_live_long_enough( location, &name, @@ -1556,7 +1702,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } let mut err = self.temporary_value_borrowed_for_too_long(proper_span); - err.span_label(proper_span, "creates a temporary which is freed while still in use"); + err.span_label(proper_span, "creates a temporary value which is freed while still in use"); err.span_label(drop_span, "temporary value is freed at the end of this statement"); match explanation { @@ -1719,7 +1865,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label(borrow_span, note); let tcx = self.infcx.tcx; - let ty_params = ty::List::empty(); let return_ty = self.regioncx.universal_regions().unnormalized_output_ty; let return_ty = tcx.erase_regions(return_ty); @@ -1728,7 +1873,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let Some(iter_trait) = tcx.get_diagnostic_item(sym::Iterator) && self .infcx - .type_implements_trait(iter_trait, return_ty, ty_params, self.param_env) + .type_implements_trait(iter_trait, [return_ty], self.param_env) .must_apply_modulo_regions() { err.span_suggestion_hidden( @@ -2307,7 +2452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // and it'll make sense. let location = borrow.reserve_location; debug!("annotate_argument_and_return_for_borrow: location={:?}", location); - if let Some(&Statement { kind: StatementKind::Assign(box (ref reservation, _)), .. }) = + if let Some(Statement { kind: StatementKind::Assign(box (reservation, _)), .. }) = &self.body[location.block].statements.get(location.statement_index) { debug!("annotate_argument_and_return_for_borrow: reservation={:?}", reservation); @@ -2335,8 +2480,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Check if our `target` was captured by a closure. if let Rvalue::Aggregate( box AggregateKind::Closure(def_id, substs), - ref operands, - ) = *rvalue + operands, + ) = rvalue { for operand in operands { let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else { @@ -2360,7 +2505,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // into a place then we should annotate the closure in // case it ends up being assigned into the return place. annotated_closure = - self.annotate_fn_sig(def_id, substs.as_closure().sig()); + self.annotate_fn_sig(*def_id, substs.as_closure().sig()); debug!( "annotate_argument_and_return_for_borrow: \ annotated_closure={:?} assigned_from_local={:?} \ @@ -2527,7 +2672,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if let hir::TyKind::Rptr(lifetime, _) = &fn_decl.inputs[index].kind { // With access to the lifetime, we can get // the span of it. - arguments.push((*argument, lifetime.span)); + arguments.push((*argument, lifetime.ident.span)); } else { bug!("ty type is a ref but hir type is not"); } @@ -2546,7 +2691,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut return_span = fn_decl.output.span(); if let hir::FnRetTy::Return(ty) = &fn_decl.output { if let hir::TyKind::Rptr(lifetime, _) = ty.kind { - return_span = lifetime.span; + return_span = lifetime.ident.span; } } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 582d683dd..304683618 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -469,8 +469,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else if self.was_captured_by_trait_object(borrow) { LaterUseKind::TraitCapture } else if location.statement_index == block.statements.len() { - if let TerminatorKind::Call { ref func, from_hir_call: true, .. } = - block.terminator().kind + if let TerminatorKind::Call { func, from_hir_call: true, .. } = + &block.terminator().kind { // Just point to the function, to reduce the chance of overlapping spans. let function_span = match func { @@ -515,19 +515,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // will only ever have one item at any given time, but by using a vector, we can pop from // it which simplifies the termination logic. let mut queue = vec![location]; - let mut target = if let Some(&Statement { - kind: StatementKind::Assign(box (ref place, _)), - .. - }) = stmt - { - if let Some(local) = place.as_local() { - local + let mut target = + if let Some(Statement { kind: StatementKind::Assign(box (place, _)), .. }) = stmt { + if let Some(local) = place.as_local() { + local + } else { + return false; + } } else { return false; - } - } else { - return false; - }; + }; debug!("was_captured_by_trait: target={:?} queue={:?}", target, queue); while let Some(current_location) = queue.pop() { diff --git a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs index b3edc35dc..498e98343 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_all_local_uses.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use std::collections::BTreeSet; use rustc_middle::mir::visit::{PlaceContext, Visitor}; diff --git a/compiler/rustc_borrowck/src/diagnostics/find_use.rs b/compiler/rustc_borrowck/src/diagnostics/find_use.rs index b5a3081e5..15f42e26c 100644 --- a/compiler/rustc_borrowck/src/diagnostics/find_use.rs +++ b/compiler/rustc_borrowck/src/diagnostics/find_use.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use std::collections::VecDeque; use std::rc::Rc; 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), diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 8ad40c0aa..3319a8068 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -1,6 +1,4 @@ -use rustc_errors::{ - Applicability, Diagnostic, DiagnosticBuilder, EmissionGuarantee, ErrorGuaranteed, -}; +use rustc_errors::{Applicability, Diagnostic}; use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; @@ -221,8 +219,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { PlaceRef { local, projection: - &[ - ref proj_base @ .., + [ + proj_base @ .., ProjectionElem::Deref, ProjectionElem::Field(field, _), ProjectionElem::Deref, @@ -233,7 +231,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let Some(span) = get_mut_span_in_struct_field( self.infcx.tcx, Place::ty_from(local, proj_base, self.body, self.infcx.tcx).ty, - field, + *field, ) { err.span_suggestion_verbose( span, @@ -391,13 +389,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // diagnostic: if the span starts with a mutable borrow of // a local variable, then just suggest the user remove it. PlaceRef { local: _, projection: [] } - if { - if let Ok(snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(span) { - snippet.starts_with("&mut ") - } else { - false - } - } => + if self + .infcx + .tcx + .sess + .source_map() + .span_to_snippet(span) + .map_or(false, |snippet| snippet.starts_with("&mut ")) => { err.span_label(span, format!("cannot {ACT}", ACT = act)); err.span_suggestion( @@ -629,25 +627,20 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { self.buffer_error(err); } - fn suggest_map_index_mut_alternatives( - &self, - ty: Ty<'_>, - err: &mut DiagnosticBuilder<'_, ErrorGuaranteed>, - span: Span, - ) { + fn suggest_map_index_mut_alternatives(&self, ty: Ty<'tcx>, err: &mut Diagnostic, span: Span) { let Some(adt) = ty.ty_adt_def() else { return }; let did = adt.did(); if self.infcx.tcx.is_diagnostic_item(sym::HashMap, did) || self.infcx.tcx.is_diagnostic_item(sym::BTreeMap, did) { - struct V<'a, 'b, 'tcx, G: EmissionGuarantee> { + struct V<'a, 'tcx> { assign_span: Span, - err: &'a mut DiagnosticBuilder<'b, G>, + err: &'a mut Diagnostic, ty: Ty<'tcx>, suggested: bool, } - impl<'a, 'b: 'a, 'hir, 'tcx, G: EmissionGuarantee> Visitor<'hir> for V<'a, 'b, 'tcx, G> { - fn visit_stmt(&mut self, stmt: &'hir hir::Stmt<'hir>) { + impl<'a, 'tcx> Visitor<'tcx> for V<'a, 'tcx> { + fn visit_stmt(&mut self, stmt: &'tcx hir::Stmt<'tcx>) { hir::intravisit::walk_stmt(self, stmt); let expr = match stmt.kind { hir::StmtKind::Semi(expr) | hir::StmtKind::Expr(expr) => expr, @@ -705,7 +698,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ), (rv.span.shrink_to_hi(), ")".to_string()), ], - ].into_iter(), + ], Applicability::MachineApplicable, ); self.suggested = true; @@ -1218,7 +1211,7 @@ fn get_mut_span_in_struct_field<'tcx>( && let hir::Node::Field(field) = node && let hir::TyKind::Rptr(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind { - return Some(lt.span.between(ty.span)); + return Some(lt.ident.span.between(ty.span)); } None diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 15230718d..9bc2e79e2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -2,7 +2,7 @@ #![deny(rustc::diagnostic_outside_of_impl)] //! Error reporting machinery for lifetime errors. -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -21,7 +21,7 @@ use rustc_middle::ty::subst::InternalSubsts; use rustc_middle::ty::Region; use rustc_middle::ty::TypeVisitor; use rustc_middle::ty::{self, RegionVid, Ty}; -use rustc_span::symbol::{kw, sym, Ident}; +use rustc_span::symbol::{kw, Ident}; use rustc_span::Span; use crate::borrowck_errors; @@ -181,7 +181,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // Try to convert the lower-bound region into something named we can print for the user. let lower_bound_region = self.to_error_region(type_test.lower_bound); - let type_test_span = type_test.locations.span(&self.body); + let type_test_span = type_test.span; if let Some(lower_bound_region) = lower_bound_region { let generic_ty = type_test.generic_kind.to_ty(self.infcx.tcx); @@ -276,7 +276,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn get_impl_ident_and_self_ty_from_trait( &self, def_id: DefId, - trait_objects: &FxHashSet<DefId>, + trait_objects: &FxIndexSet<DefId>, ) -> Option<(Ident, &'tcx hir::Ty<'tcx>)> { let tcx = self.infcx.tcx; match tcx.hir().get_if_local(def_id) { @@ -514,9 +514,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { span: *span, ty_err: match output_ty.kind() { ty::Closure(_, _) => FnMutReturnTypeErr::ReturnClosure { span: *span }, - ty::Adt(def, _) - if self.infcx.tcx.is_diagnostic_item(sym::gen_future, def.did()) => - { + ty::Generator(def, ..) if self.infcx.tcx.generator_is_async(*def) => { FnMutReturnTypeErr::ReturnAsyncBlock { span: *span } } _ => FnMutReturnTypeErr::ReturnRef { span: *span }, @@ -830,7 +828,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { }; debug!(?param); - let mut visitor = TraitObjectVisitor(FxHashSet::default()); + let mut visitor = TraitObjectVisitor(FxIndexSet::default()); visitor.visit_ty(param.param_ty); let Some((ident, self_ty)) = @@ -843,7 +841,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn suggest_constrain_dyn_trait_in_impl( &self, err: &mut Diagnostic, - found_dids: &FxHashSet<DefId>, + found_dids: &FxIndexSet<DefId>, ident: Ident, self_ty: &hir::Ty<'_>, ) -> bool { @@ -923,14 +921,18 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } } hir::ExprKind::Block(blk, _) => { - if let Some(ref expr) = blk.expr { + if let Some(expr) = blk.expr { // only when the block is a closure if let hir::ExprKind::Closure(hir::Closure { capture_clause: hir::CaptureBy::Ref, + body, .. }) = expr.kind { - closure_span = Some(expr.span.shrink_to_lo()); + let body = map.body(*body); + if !matches!(body.generator_kind, Some(hir::GeneratorKind::Async(..))) { + closure_span = Some(expr.span.shrink_to_lo()); + } } } } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index c044dbaba..171e62d91 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -254,7 +254,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .or_else(|| self.give_name_if_anonymous_region_appears_in_impl_signature(fr)) .or_else(|| self.give_name_if_anonymous_region_appears_in_arg_position_impl_trait(fr)); - if let Some(ref value) = value { + if let Some(value) = &value { self.region_names.try_borrow_mut().unwrap().insert(fr, value.clone()); } @@ -355,7 +355,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { }) } - ty::BoundRegionKind::BrAnon(_) => None, + ty::BoundRegionKind::BrAnon(..) => None, }, ty::ReLateBound(..) | ty::ReVar(..) | ty::RePlaceholder(..) | ty::ReErased => None, @@ -576,30 +576,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { let args = last_segment.args.as_ref()?; let lifetime = self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?; - match lifetime.name { - hir::LifetimeName::Param(_, hir::ParamName::Plain(_) | hir::ParamName::Error) - | hir::LifetimeName::Error - | hir::LifetimeName::Static => { - let lifetime_span = lifetime.span; - Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime_span)) - } - - hir::LifetimeName::Param(_, hir::ParamName::Fresh) - | hir::LifetimeName::ImplicitObjectLifetimeDefault - | hir::LifetimeName::Infer => { - // In this case, the user left off the lifetime; so - // they wrote something like: - // - // ``` - // x: Foo<T> - // ``` - // - // where the fully elaborated form is `Foo<'_, '1, - // T>`. We don't consider this a match; instead we let - // the "fully elaborated" type fallback above handle - // it. - None - } + if lifetime.is_anonymous() { + None + } else { + Some(RegionNameHighlight::MatchedAdtAndSegment(lifetime.ident.span)) } } @@ -959,8 +939,8 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { { predicates.iter().any(|pred| { match pred.kind().skip_binder() { - ty::PredicateKind::Trait(data) if data.self_ty() == ty => {} - ty::PredicateKind::Projection(data) if data.projection_ty.self_ty() == ty => {} + ty::PredicateKind::Clause(ty::Clause::Trait(data)) if data.self_ty() == ty => {} + ty::PredicateKind::Clause(ty::Clause::Projection(data)) if data.projection_ty.self_ty() == ty => {} _ => return false, } tcx.any_free_region_meets(pred, |r| { diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 9ba29f04b..b385f95b6 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -1,3 +1,6 @@ +#![deny(rustc::untranslatable_diagnostic)] +#![deny(rustc::diagnostic_outside_of_impl)] + use crate::Upvar; use crate::{nll::ToRegionVid, region_infer::RegionInferenceContext}; use rustc_index::vec::{Idx, IndexVec}; |