From d1b2d29528b7794b41e66fc2136e395a02f8529b Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Thu, 30 May 2024 05:59:35 +0200 Subject: Merging upstream version 1.73.0+dfsg1. Signed-off-by: Daniel Baumann --- compiler/rustc_borrowck/src/borrowck_errors.rs | 46 ++--- .../rustc_borrowck/src/constraint_generation.rs | 10 +- compiler/rustc_borrowck/src/consumers.rs | 2 +- compiler/rustc_borrowck/src/dataflow.rs | 21 ++- .../src/diagnostics/conflict_errors.rs | 210 +++++++++++---------- .../src/diagnostics/explain_borrow.rs | 8 +- compiler/rustc_borrowck/src/diagnostics/mod.rs | 38 ++-- .../rustc_borrowck/src/diagnostics/move_errors.rs | 14 +- .../src/diagnostics/mutability_errors.rs | 101 +++++----- .../src/diagnostics/region_errors.rs | 75 ++++---- .../rustc_borrowck/src/diagnostics/region_name.rs | 49 +++-- .../rustc_borrowck/src/diagnostics/var_name.rs | 4 +- compiler/rustc_borrowck/src/facts.rs | 2 +- compiler/rustc_borrowck/src/invalidation.rs | 3 +- compiler/rustc_borrowck/src/lib.rs | 35 ++-- compiler/rustc_borrowck/src/nll.rs | 6 +- compiler/rustc_borrowck/src/path_utils.rs | 14 +- compiler/rustc_borrowck/src/places_conflict.rs | 143 +++++++------- .../rustc_borrowck/src/region_infer/dump_mir.rs | 11 +- .../rustc_borrowck/src/region_infer/graphviz.rs | 4 +- compiler/rustc_borrowck/src/region_infer/mod.rs | 61 +++--- .../src/region_infer/opaque_types.rs | 98 +++++----- compiler/rustc_borrowck/src/region_infer/values.rs | 6 +- compiler/rustc_borrowck/src/renumber.rs | 8 +- compiler/rustc_borrowck/src/session_diagnostics.rs | 2 +- .../rustc_borrowck/src/type_check/canonical.rs | 6 +- .../src/type_check/constraint_conversion.rs | 10 +- .../src/type_check/liveness/polonius.rs | 6 +- .../src/type_check/liveness/trace.rs | 8 +- compiler/rustc_borrowck/src/type_check/mod.rs | 158 +++++++--------- .../rustc_borrowck/src/type_check/relate_tys.rs | 6 +- compiler/rustc_borrowck/src/universal_regions.rs | 161 ++++++++-------- 32 files changed, 653 insertions(+), 673 deletions(-) (limited to 'compiler/rustc_borrowck/src') diff --git a/compiler/rustc_borrowck/src/borrowck_errors.rs b/compiler/rustc_borrowck/src/borrowck_errors.rs index a4e0e773a..a2c7e767b 100644 --- a/compiler/rustc_borrowck/src/borrowck_errors.rs +++ b/compiler/rustc_borrowck/src/borrowck_errors.rs @@ -37,8 +37,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc, ); - err.span_label(borrow_span, format!("{} is borrowed here", borrow_desc)); - err.span_label(span, format!("use of borrowed {}", borrow_desc)); + err.span_label(borrow_span, format!("{borrow_desc} is borrowed here")); + err.span_label(span, format!("use of borrowed {borrow_desc}")); err } @@ -51,8 +51,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { old_opt_via: &str, old_load_end_span: Option, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let via = - |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; + let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_err!( self, new_loan_span, @@ -143,9 +142,9 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { ); err.span_label( new_loan_span, - format!("{} construction occurs here{}", container_name, opt_via), + format!("{container_name} construction occurs here{opt_via}"), ); - err.span_label(old_loan_span, format!("borrow occurs here{}", old_opt_via)); + err.span_label(old_loan_span, format!("borrow occurs here{old_opt_via}")); if let Some(previous_end_span) = previous_end_span { err.span_label(previous_end_span, "borrow ends here"); } @@ -173,13 +172,10 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { opt_via, kind_new, ); - err.span_label( - new_loan_span, - format!("{}borrow occurs here{}", second_borrow_desc, opt_via), - ); + err.span_label(new_loan_span, format!("{second_borrow_desc}borrow occurs here{opt_via}")); err.span_label( old_loan_span, - format!("{} construction occurs here{}", container_name, old_opt_via), + format!("{container_name} construction occurs here{old_opt_via}"), ); if let Some(previous_end_span) = previous_end_span { err.span_label(previous_end_span, "borrow from closure ends here"); @@ -199,8 +195,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { msg_old: &str, old_load_end_span: Option, ) -> DiagnosticBuilder<'cx, ErrorGuaranteed> { - let via = - |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {})", msg) }; + let via = |msg: &str| if msg.is_empty() { "".to_string() } else { format!(" (via {msg})") }; let mut err = struct_span_err!( self, span, @@ -216,22 +211,21 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { if msg_new == "" { // If `msg_new` is empty, then this isn't a borrow of a union field. - err.span_label(span, format!("{} borrow occurs here", kind_new)); - err.span_label(old_span, format!("{} borrow occurs here", kind_old)); + err.span_label(span, format!("{kind_new} borrow occurs here")); + err.span_label(old_span, format!("{kind_old} borrow occurs here")); } else { // If `msg_new` isn't empty, then this a borrow of a union field. err.span_label( span, format!( - "{} borrow of {} -- which overlaps with {} -- occurs here", - kind_new, msg_new, msg_old, + "{kind_new} borrow of {msg_new} -- which overlaps with {msg_old} -- occurs here", ), ); err.span_label(old_span, format!("{} borrow occurs here{}", kind_old, via(msg_old))); } if let Some(old_load_end_span) = old_load_end_span { - err.span_label(old_load_end_span, format!("{} borrow ends here", kind_old)); + err.span_label(old_load_end_span, format!("{kind_old} borrow ends here")); } err } @@ -250,8 +244,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { desc, ); - err.span_label(borrow_span, format!("{} is borrowed here", desc)); - err.span_label(span, format!("{} is assigned to here but it was already borrowed", desc)); + err.span_label(borrow_span, format!("{desc} is borrowed here")); + err.span_label(span, format!("{desc} is assigned to here but it was already borrowed")); err } @@ -330,7 +324,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { optional_adverb_for_moved: &str, moved_path: Option, ) -> DiagnosticBuilder<'tcx, ErrorGuaranteed> { - let moved_path = moved_path.map(|mp| format!(": `{}`", mp)).unwrap_or_default(); + let moved_path = moved_path.map(|mp| format!(": `{mp}`")).unwrap_or_default(); struct_span_err!( self, @@ -369,8 +363,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { immutable_place, immutable_section, ); - err.span_label(mutate_span, format!("cannot {}", action)); - err.span_label(immutable_span, format!("value is immutable in {}", immutable_section)); + err.span_label(mutate_span, format!("cannot {action}")); + err.span_label(immutable_span, format!("value is immutable in {immutable_section}")); err } @@ -428,7 +422,7 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { err.span_label( span, - format!("{}s a {} data owned by the current function", return_kind, reference_desc), + format!("{return_kind}s a {reference_desc} data owned by the current function"), ); err @@ -449,8 +443,8 @@ impl<'cx, 'tcx> crate::MirBorrowckCtxt<'cx, 'tcx> { "{closure_kind} may outlive the current {scope}, but it borrows {borrowed_path}, \ which is owned by the current {scope}", ); - err.span_label(capture_span, format!("{} is borrowed here", borrowed_path)) - .span_label(closure_span, format!("may outlive borrowed value {}", borrowed_path)); + err.span_label(capture_span, format!("{borrowed_path} is borrowed here")) + .span_label(closure_span, format!("may outlive borrowed value {borrowed_path}")); err } diff --git a/compiler/rustc_borrowck/src/constraint_generation.rs b/compiler/rustc_borrowck/src/constraint_generation.rs index 743d117e0..1f642099f 100644 --- a/compiler/rustc_borrowck/src/constraint_generation.rs +++ b/compiler/rustc_borrowck/src/constraint_generation.rs @@ -7,8 +7,8 @@ use rustc_middle::mir::{ Body, Local, Location, Place, PlaceRef, ProjectionElem, Rvalue, SourceInfo, Statement, StatementKind, Terminator, TerminatorKind, UserTypeProjection, }; -use rustc_middle::ty::subst::SubstsRef; use rustc_middle::ty::visit::TypeVisitable; +use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt}; use crate::{ @@ -49,11 +49,11 @@ struct ConstraintGeneration<'cg, 'tcx> { } impl<'cg, 'tcx> Visitor<'tcx> for ConstraintGeneration<'cg, 'tcx> { - /// We sometimes have `substs` within an rvalue, or within a + /// We sometimes have `args` within an rvalue, or within a /// call. Make them live at the location where they appear. - fn visit_substs(&mut self, substs: &SubstsRef<'tcx>, location: Location) { - self.add_regular_live_constraint(*substs, location); - self.super_substs(substs); + fn visit_args(&mut self, args: &GenericArgsRef<'tcx>, location: Location) { + self.add_regular_live_constraint(*args, location); + self.super_args(args); } /// We sometimes have `region` within an rvalue, or within a diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index d25714537..becfa535a 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -30,7 +30,7 @@ pub use super::{ /// will be retrieved. #[derive(Debug, Copy, Clone)] pub enum ConsumerOptions { - /// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet) + /// Retrieve the [`Body`] along with the [`BorrowSet`] /// and [`RegionInferenceContext`]. If you would like the body only, use /// [`TyCtxt::mir_promoted`]. /// diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs index 1064b44d2..4ac633c26 100644 --- a/compiler/rustc_borrowck/src/dataflow.rs +++ b/compiler/rustc_borrowck/src/dataflow.rs @@ -2,12 +2,14 @@ #![deny(rustc::diagnostic_outside_of_impl)] use rustc_data_structures::fx::FxIndexMap; use rustc_index::bit_set::BitSet; -use rustc_middle::mir::{self, BasicBlock, Body, Location, Place}; +use rustc_middle::mir::{ + self, BasicBlock, Body, CallReturnPlaces, Location, Place, TerminatorEdges, +}; use rustc_middle::ty::RegionVid; use rustc_middle::ty::TyCtxt; use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces}; use rustc_mir_dataflow::ResultsVisitable; -use rustc_mir_dataflow::{self, fmt::DebugWithContext, CallReturnPlaces, GenKill}; +use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill}; use rustc_mir_dataflow::{Analysis, Direction, Results}; use std::fmt; @@ -334,6 +336,10 @@ impl<'tcx> rustc_mir_dataflow::AnalysisDomain<'tcx> for Borrows<'_, 'tcx> { impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { type Idx = BorrowIndex; + fn domain_size(&self, _: &mir::Body<'tcx>) -> usize { + self.borrow_set.len() + } + fn before_statement_effect( &mut self, trans: &mut impl GenKill, @@ -360,7 +366,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { return; } let index = self.borrow_set.get_index_of(&location).unwrap_or_else(|| { - panic!("could not find BorrowIndex for location {:?}", location); + panic!("could not find BorrowIndex for location {location:?}"); }); trans.gen(index); @@ -400,12 +406,12 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { self.kill_loans_out_of_scope_at_location(trans, location); } - fn terminator_effect( + fn terminator_effect<'mir>( &mut self, - trans: &mut impl GenKill, - terminator: &mir::Terminator<'tcx>, + trans: &mut Self::Domain, + terminator: &'mir mir::Terminator<'tcx>, _location: Location, - ) { + ) -> TerminatorEdges<'mir, 'tcx> { if let mir::TerminatorKind::InlineAsm { operands, .. } = &terminator.kind { for op in operands { if let mir::InlineAsmOperand::Out { place: Some(place), .. } @@ -415,6 +421,7 @@ impl<'tcx> rustc_mir_dataflow::GenKillAnalysis<'tcx> for Borrows<'_, 'tcx> { } } } + terminator.edges() } fn call_return_effect( diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index c8c8b72b3..fe4a45b38 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -363,21 +363,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } let hir = self.infcx.tcx.hir(); - if let Some(hir::Node::Item(hir::Item { - kind: hir::ItemKind::Fn(_, _, body_id), - .. - })) = hir.find(self.mir_hir_id()) - && let Some(hir::Node::Expr(expr)) = hir.find(body_id.hir_id) - { + if let Some(body_id) = hir.maybe_body_owned_by(self.mir_def_id()) { + let expr = hir.body(body_id).value; 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, - }; + 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) { @@ -461,7 +452,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } = move_spans { // We already suggest cloning for these cases in `explain_captures`. } else { - self.suggest_cloning(err, ty, move_span); + self.suggest_cloning(err, ty, expr, move_span); } } } @@ -662,7 +653,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_suggestion_verbose( sugg_span.shrink_to_hi(), "consider assigning a value", - format!(" = {}", assign_value), + format!(" = {assign_value}"), Applicability::MaybeIncorrect, ); } @@ -702,11 +693,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .iter() .copied() .find_map(find_fn_kind_from_did), - ty::Alias(ty::Opaque, ty::AliasTy { def_id, substs, .. }) => tcx + ty::Alias(ty::Opaque, ty::AliasTy { def_id, args, .. }) => tcx .explicit_item_bounds(def_id) - .subst_iter_copied(tcx, substs) + .iter_instantiated_copied(tcx, args) .find_map(|(clause, span)| find_fn_kind_from_did((clause, span))), - ty::Closure(_, substs) => match substs.as_closure().kind() { + ty::Closure(_, args) => match args.as_closure().kind() { ty::ClosureKind::Fn => Some(hir::Mutability::Not), ty::ClosureKind::FnMut => Some(hir::Mutability::Mut), _ => None, @@ -714,7 +705,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { _ => None, }; - let Some(borrow_level) = borrow_level else { return false; }; + let Some(borrow_level) = borrow_level else { + return false; + }; let sugg = move_sites .iter() .map(|move_site| { @@ -734,9 +727,21 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { true } - fn suggest_cloning(&self, err: &mut Diagnostic, ty: Ty<'tcx>, span: Span) { + fn suggest_cloning( + &self, + err: &mut Diagnostic, + ty: Ty<'tcx>, + expr: &hir::Expr<'_>, + span: Span, + ) { let tcx = self.infcx.tcx; // Try to find predicates on *generic params* that would allow copying `ty` + let suggestion = + if let Some(symbol) = tcx.hir().maybe_get_struct_pattern_shorthand_field(expr) { + format!(": {symbol}.clone()") + } else { + ".clone()".to_owned() + }; if let Some(clone_trait_def) = tcx.lang_items().clone_trait() && self.infcx .type_implements_trait( @@ -746,10 +751,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ) .must_apply_modulo_regions() { + let msg = if let ty::Adt(def, _) = ty.kind() + && [ + tcx.get_diagnostic_item(sym::Arc), + tcx.get_diagnostic_item(sym::Rc), + ].contains(&Some(def.did())) + { + "clone the value to increment its reference count" + } else { + "consider cloning the value if the performance cost is acceptable" + }; err.span_suggestion_verbose( span.shrink_to_hi(), - "consider cloning the value if the performance cost is acceptable", - ".clone()", + msg, + suggestion, Applicability::MachineApplicable, ); } @@ -763,7 +778,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { .typeck_root_def_id(self.mir_def_id().to_def_id()) .as_local() .and_then(|def_id| tcx.hir().get_generics(def_id)) - else { return; }; + else { + return; + }; // Try to find predicates on *generic params* that would allow copying `ty` let ocx = ObligationCtxt::new(&self.infcx); let copy_did = tcx.require_lang_item(LangItem::Copy, Some(span)); @@ -1155,8 +1172,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if union_type_name != "" { err.note(format!( - "{} is a field of the union `{}`, so it overlaps the field {}", - msg_place, union_type_name, msg_borrow, + "{msg_place} is a field of the union `{union_type_name}`, so it overlaps the field {msg_borrow}", )); } @@ -1220,18 +1236,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { return; }; let inner_param_uses = find_all_local_uses::find(self.body, inner_param.local); - let Some((inner_call_loc, inner_call_term)) = inner_param_uses.into_iter().find_map(|loc| { - let Either::Right(term) = self.body.stmt_at(loc) else { - debug!("{:?} is a statement, so it can't be a call", loc); - return None; - }; - let TerminatorKind::Call { args, .. } = &term.kind else { - debug!("not a call: {:?}", term); - return None; - }; - debug!("checking call args for uses of inner_param: {:?}", args); - args.contains(&Operand::Move(inner_param)).then_some((loc, term)) - }) else { + let Some((inner_call_loc, inner_call_term)) = + inner_param_uses.into_iter().find_map(|loc| { + let Either::Right(term) = self.body.stmt_at(loc) else { + debug!("{:?} is a statement, so it can't be a call", loc); + return None; + }; + let TerminatorKind::Call { args, .. } = &term.kind else { + debug!("not a call: {:?}", term); + return None; + }; + debug!("checking call args for uses of inner_param: {:?}", args); + args.contains(&Operand::Move(inner_param)).then_some((loc, term)) + }) + else { debug!("no uses of inner_param found as a by-move call arg"); return; }; @@ -1344,8 +1362,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let Some(trait_did) = tcx.trait_of_item(def_id) && tcx.is_diagnostic_item(sym::Iterator, trait_did) { err.note(format!( - "a for loop advances the iterator for you, the result is stored in `{}`.", - loop_bind + "a for loop advances the iterator for you, the result is stored in `{loop_bind}`." )); err.help("if you want to call `next` on a iterator within the loop, consider using `while let`."); } @@ -1442,21 +1459,24 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } // Get closure's arguments - let ty::Closure(_, substs) = typeck_results.expr_ty(closure_expr).kind() else { /* hir::Closure can be a generator too */ return }; - let sig = substs.as_closure().sig(); + let ty::Closure(_, args) = typeck_results.expr_ty(closure_expr).kind() else { + /* hir::Closure can be a generator too */ + return; + }; + let sig = args.as_closure().sig(); let tupled_params = tcx.erase_late_bound_regions(sig.inputs().iter().next().unwrap().map_bound(|&b| b)); let ty::Tuple(params) = tupled_params.kind() else { return }; // Find the first argument with a matching type, get its name - let Some((_, this_name)) = params - .iter() - .zip(hir.body_param_names(closure.body)) - .find(|(param_ty, name)|{ + let Some((_, this_name)) = + params.iter().zip(hir.body_param_names(closure.body)).find(|(param_ty, name)| { // FIXME: also support deref for stuff like `Rc` arguments param_ty.peel_refs() == local_ty && name != &Ident::empty() }) - else { return }; + else { + return; + }; let spans; if let Some((_path_expr, qpath)) = finder.error_path @@ -1813,7 +1833,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }, ConstraintCategory::CallArgument(None), var_or_use_span, - &format!("`{}`", name), + &format!("`{name}`"), "block", ), ( @@ -1835,7 +1855,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { region_name, category, span, - &format!("`{}`", name), + &format!("`{name}`"), "function", ), ( @@ -1909,14 +1929,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } - let mut err = self.path_does_not_live_long_enough(borrow_span, &format!("`{}`", name)); + let mut err = self.path_does_not_live_long_enough(borrow_span, &format!("`{name}`")); if let Some(annotation) = self.annotate_argument_and_return_for_borrow(borrow) { let region_name = annotation.emit(self, &mut err); err.span_label( borrow_span, - format!("`{}` would have to be valid for `{}`...", name, region_name), + format!("`{name}` would have to be valid for `{region_name}`..."), ); err.span_label( @@ -1927,7 +1947,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.infcx .tcx .opt_item_name(self.mir_def_id().to_def_id()) - .map(|name| format!("function `{}`", name)) + .map(|name| format!("function `{name}`")) .unwrap_or_else(|| { match &self.infcx.tcx.def_kind(self.mir_def_id()) { DefKind::Closure => "enclosing closure", @@ -1962,7 +1982,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } } else { err.span_label(borrow_span, "borrowed value does not live long enough"); - err.span_label(drop_span, format!("`{}` dropped here while still borrowed", name)); + err.span_label(drop_span, format!("`{name}` dropped here while still borrowed")); borrow_spans.args_subdiag(&mut err, |args_span| { crate::session_diagnostics::CaptureArgLabel::Capture { @@ -2006,22 +2026,17 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let mut err = self.cannot_borrow_across_destructor(borrow_span); let what_was_dropped = match self.describe_place(place.as_ref()) { - Some(name) => format!("`{}`", name), + Some(name) => format!("`{name}`"), None => String::from("temporary value"), }; let label = match self.describe_place(borrow.borrowed_place.as_ref()) { Some(borrowed) => format!( - "here, drop of {D} needs exclusive access to `{B}`, \ - because the type `{T}` implements the `Drop` trait", - D = what_was_dropped, - T = dropped_ty, - B = borrowed + "here, drop of {what_was_dropped} needs exclusive access to `{borrowed}`, \ + because the type `{dropped_ty}` implements the `Drop` trait" ), None => format!( - "here is drop of {D}; whose type `{T}` implements the `Drop` trait", - D = what_was_dropped, - T = dropped_ty + "here is drop of {what_was_dropped}; whose type `{dropped_ty}` implements the `Drop` trait" ), }; err.span_label(drop_span, label); @@ -2128,13 +2143,14 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.current -= 1; } fn visit_expr(&mut self, expr: &hir::Expr<'tcx>) { - if self.span == expr.span { + if self.span == expr.span.source_callsite() { self.found = self.current; } walk_expr(self, expr); } } let source_info = self.body.source_info(location); + let proper_span = proper_span.source_callsite(); if let Some(scope) = self.body.source_scopes.get(source_info.scope) && let ClearCrossCrate::Set(scope_data) = &scope.local_data && let Some(node) = self.infcx.tcx.hir().find(scope_data.lint_root) @@ -2233,10 +2249,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } else { "local data " }; - ( - format!("{}`{}`", local_kind, place_desc), - format!("`{}` is borrowed here", place_desc), - ) + (format!("{local_kind}`{place_desc}`"), format!("`{place_desc}` is borrowed here")) } else { let root_place = self.prefixes(borrow.borrowed_place.as_ref(), PrefixSet::All).last().unwrap(); @@ -2338,9 +2351,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_suggestion_verbose( sugg_span, format!( - "to force the {} to take ownership of {} (and any \ - other referenced variables), use the `move` keyword", - kind, captured_var + "to force the {kind} to take ownership of {captured_var} (and any \ + other referenced variables), use the `move` keyword" ), suggestion, Applicability::MachineApplicable, @@ -2348,7 +2360,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { match category { ConstraintCategory::Return(_) | ConstraintCategory::OpaqueType => { - let msg = format!("{} is returned here", kind); + let msg = format!("{kind} is returned here"); err.span_note(constraint_span, msg); } ConstraintCategory::CallArgument(_) => { @@ -2390,21 +2402,18 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_label( upvar_span, - format!("`{}` declared here, outside of the {} body", upvar_name, escapes_from), + format!("`{upvar_name}` declared here, outside of the {escapes_from} body"), ); - err.span_label(borrow_span, format!("borrow is only valid in the {} body", escapes_from)); + err.span_label(borrow_span, format!("borrow is only valid in the {escapes_from} body")); if let Some(name) = name { err.span_label( escape_span, - format!("reference to `{}` escapes the {} body here", name, escapes_from), + format!("reference to `{name}` escapes the {escapes_from} body here"), ); } else { - err.span_label( - escape_span, - format!("reference escapes the {} body here", escapes_from), - ); + err.span_label(escape_span, format!("reference escapes the {escapes_from} body here")); } err @@ -2667,7 +2676,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { kind: TerminatorKind::Call { call_source: CallSource::OverloadedOperator, .. }, .. }), - Some((method_did, method_substs)), + Some((method_did, method_args)), ) = ( &self.body[loan.reserve_location.block].terminator, rustc_middle::util::find_self_call( @@ -2680,15 +2689,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if tcx.is_diagnostic_item(sym::deref_method, method_did) { let deref_target = tcx.get_diagnostic_item(sym::deref_target).and_then(|deref_target| { - Instance::resolve(tcx, self.param_env, deref_target, method_substs) + Instance::resolve(tcx, self.param_env, deref_target, method_args) .transpose() }); if let Some(Ok(instance)) = deref_target { let deref_target_ty = instance.ty(tcx, self.param_env); - err.note(format!( - "borrow occurs due to deref coercion to `{}`", - deref_target_ty - )); + err.note(format!("borrow occurs due to deref coercion to `{deref_target_ty}`")); err.span_note(tcx.def_span(instance.def_id()), "deref defined here"); } } @@ -2744,7 +2750,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { "cannot assign twice to immutable variable" }; if span != assigned_span && !from_arg { - err.span_label(assigned_span, format!("first assignment to {}", place_description)); + err.span_label(assigned_span, format!("first assignment to {place_description}")); } if let Some(decl) = local_decl && let Some(name) = local_name @@ -2753,7 +2759,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { err.span_suggestion( decl.source_info.span, "consider making this binding mutable", - format!("mut {}", name), + format!("mut {name}"), Applicability::MachineApplicable, ); } @@ -2847,11 +2853,11 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { if is_closure { None } else { - let ty = self.infcx.tcx.type_of(self.mir_def_id()).subst_identity(); + let ty = self.infcx.tcx.type_of(self.mir_def_id()).instantiate_identity(); match ty.kind() { ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig( self.mir_def_id(), - self.infcx.tcx.fn_sig(self.mir_def_id()).subst_identity(), + self.infcx.tcx.fn_sig(self.mir_def_id()).instantiate_identity(), ), _ => None, } @@ -2893,13 +2899,15 @@ 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), + box AggregateKind::Closure(def_id, args), operands, ) = rvalue { let def_id = def_id.expect_local(); for operand in operands { - let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else { + let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = + operand + else { continue; }; debug!( @@ -2908,7 +2916,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Find the local from the operand. - let Some(assigned_from_local) = assigned_from.local_or_deref_local() else { + let Some(assigned_from_local) = + assigned_from.local_or_deref_local() + else { continue; }; @@ -2920,7 +2930,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, args.as_closure().sig()); debug!( "annotate_argument_and_return_for_borrow: \ annotated_closure={:?} assigned_from_local={:?} \ @@ -2961,7 +2971,9 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { ); // Find the local from the rvalue. - let Some(assigned_from_local) = assigned_from.local_or_deref_local() else { continue }; + let Some(assigned_from_local) = assigned_from.local_or_deref_local() else { + continue; + }; debug!( "annotate_argument_and_return_for_borrow: \ assigned_from_local={:?}", @@ -3009,7 +3021,8 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { assigned_to, args ); for operand in args { - let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand else { + let (Operand::Copy(assigned_from) | Operand::Move(assigned_from)) = operand + else { continue; }; debug!( @@ -3207,7 +3220,7 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { return_span, } => { let argument_ty_name = cx.get_name_for_ty(argument_ty, 0); - diag.span_label(argument_span, format!("has type `{}`", argument_ty_name)); + diag.span_label(argument_span, format!("has type `{argument_ty_name}`")); let return_ty_name = cx.get_name_for_ty(return_ty, 0); let types_equal = return_ty_name == argument_ty_name; @@ -3234,15 +3247,14 @@ impl<'tcx> AnnotatedBorrowFnSignature<'tcx> { // Region of return type and arguments checked to be the same earlier. let region_name = cx.get_region_name_for_ty(*return_ty, 0); for (_, argument_span) in arguments { - diag.span_label(*argument_span, format!("has lifetime `{}`", region_name)); + diag.span_label(*argument_span, format!("has lifetime `{region_name}`")); } - diag.span_label(*return_span, format!("also has lifetime `{}`", region_name,)); + diag.span_label(*return_span, format!("also has lifetime `{region_name}`",)); diag.help(format!( - "use data from the highlighted arguments which match the `{}` lifetime of \ + "use data from the highlighted arguments which match the `{region_name}` lifetime of \ the return type", - region_name, )); region_name diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 225c38efb..c66a24473 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -79,7 +79,7 @@ impl<'tcx> BorrowExplanation<'tcx> { | hir::ExprKind::Unary(hir::UnOp::Deref, inner) | hir::ExprKind::Field(inner, _) | hir::ExprKind::MethodCall(_, inner, _, _) - | hir::ExprKind::Index(inner, _) = &expr.kind + | hir::ExprKind::Index(inner, _, _) = &expr.kind { expr = inner; } @@ -168,17 +168,17 @@ impl<'tcx> BorrowExplanation<'tcx> { let local_decl = &body.local_decls[dropped_local]; let mut ty = local_decl.ty; if local_decl.source_info.span.desugaring_kind() == Some(DesugaringKind::ForLoop) { - if let ty::Adt(adt, substs) = local_decl.ty.kind() { + if let ty::Adt(adt, args) = local_decl.ty.kind() { if tcx.is_diagnostic_item(sym::Option, adt.did()) { // in for loop desugaring, only look at the `Some(..)` inner type - ty = substs.type_at(0); + ty = args.type_at(0); } } } let (dtor_desc, type_desc) = match ty.kind() { // If type is an ADT that implements Drop, then // simplify output by reporting just the ADT name. - ty::Adt(adt, _substs) if adt.has_dtor(tcx) && !adt.is_box() => { + ty::Adt(adt, _args) if adt.has_dtor(tcx) && !adt.is_box() => { ("`Drop` code", format!("type `{}`", tcx.def_path_str(adt.did()))) } diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index d292611e6..099e07e88 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -732,18 +732,18 @@ impl<'tcx> BorrowedContentSource<'tcx> { fn from_call(func: Ty<'tcx>, tcx: TyCtxt<'tcx>) -> Option { match *func.kind() { - ty::FnDef(def_id, substs) => { + ty::FnDef(def_id, args) => { let trait_id = tcx.trait_of_item(def_id)?; let lang_items = tcx.lang_items(); if Some(trait_id) == lang_items.deref_trait() || Some(trait_id) == lang_items.deref_mut_trait() { - Some(BorrowedContentSource::OverloadedDeref(substs.type_at(0))) + Some(BorrowedContentSource::OverloadedDeref(args.type_at(0))) } else if Some(trait_id) == lang_items.index_trait() || Some(trait_id) == lang_items.index_mut_trait() { - Some(BorrowedContentSource::OverloadedIndex(substs.type_at(0))) + Some(BorrowedContentSource::OverloadedIndex(args.type_at(0))) } else { None } @@ -847,14 +847,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { kind: TerminatorKind::Call { fn_span, call_source, .. }, .. }) = &self.body[location.block].terminator { - let Some((method_did, method_substs)) = - rustc_middle::util::find_self_call( - self.infcx.tcx, - &self.body, - target_temp, - location.block, - ) - else { + let Some((method_did, method_args)) = rustc_middle::util::find_self_call( + self.infcx.tcx, + &self.body, + target_temp, + location.block, + ) else { return normal_ret; }; @@ -862,7 +860,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.infcx.tcx, self.param_env, method_did, - method_substs, + method_args, *fn_span, call_source.from_hir_call(), Some(self.infcx.tcx.fn_arg_names(method_did)[0]), @@ -1041,7 +1039,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { }); } } - CallKind::Normal { self_arg, desugaring, method_did, method_substs } => { + CallKind::Normal { self_arg, desugaring, method_did, method_args } => { let self_arg = self_arg.unwrap(); let tcx = self.infcx.tcx; if let Some((CallDesugaringKind::ForLoopIntoIter, _)) = desugaring { @@ -1108,20 +1106,20 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { // Erase and shadow everything that could be passed to the new infcx. let ty = moved_place.ty(self.body, tcx).ty; - if let ty::Adt(def, substs) = ty.kind() + if let ty::Adt(def, args) = ty.kind() && Some(def.did()) == tcx.lang_items().pin_type() - && let ty::Ref(_, _, hir::Mutability::Mut) = substs.type_at(0).kind() + && let ty::Ref(_, _, hir::Mutability::Mut) = args.type_at(0).kind() && let self_ty = self.infcx.instantiate_binder_with_fresh_vars( fn_call_span, LateBoundRegionConversionTime::FnCall, - tcx.fn_sig(method_did).subst(tcx, method_substs).input(0), + tcx.fn_sig(method_did).instantiate(tcx, method_args).input(0), ) && self.infcx.can_eq(self.param_env, ty, self_ty) { err.eager_subdiagnostic( &self.infcx.tcx.sess.parse_sess.span_diagnostic, CaptureReasonSuggest::FreshReborrow { - span: fn_call_span.shrink_to_lo(), + span: move_span.shrink_to_hi(), }); } if let Some(clone_trait) = tcx.lang_items().clone_trait() @@ -1135,10 +1133,10 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { && self.infcx.predicate_must_hold_modulo_regions(&o) { err.span_suggestion_verbose( - fn_call_span.shrink_to_lo(), + move_span.shrink_to_hi(), "you can `clone` the value and consume it, but this might not be \ your desired behavior", - "clone().".to_string(), + ".clone()".to_string(), Applicability::MaybeIncorrect, ); } @@ -1163,7 +1161,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let parent_self_ty = matches!(tcx.def_kind(parent_did), rustc_hir::def::DefKind::Impl { .. }) .then_some(parent_did) - .and_then(|did| match tcx.type_of(did).subst_identity().kind() { + .and_then(|did| match tcx.type_of(did).instantiate_identity().kind() { ty::Adt(def, ..) => Some(def.did()), _ => None, }); diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index 8b77477a3..e05c04e11 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -184,7 +184,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } // Error with the pattern LookupResult::Exact(_) => { - let LookupResult::Parent(Some(mpi)) = self.move_data.rev_lookup.find(move_from.as_ref()) else { + let LookupResult::Parent(Some(mpi)) = + self.move_data.rev_lookup.find(move_from.as_ref()) + else { // move_from should be a projection from match_place. unreachable!("Probably not unreachable..."); }; @@ -322,10 +324,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ty::Array(..) | ty::Slice(..) => { self.cannot_move_out_of_interior_noncopy(span, ty, None) } - ty::Closure(def_id, closure_substs) + ty::Closure(def_id, closure_args) if def_id.as_local() == Some(self.mir_def_id()) && upvar_field.is_some() => { - let closure_kind_ty = closure_substs.as_closure().kind_ty(); + let closure_kind_ty = closure_args.as_closure().kind_ty(); let closure_kind = match closure_kind_ty.to_opt_closure_kind() { Some(kind @ (ty::ClosureKind::Fn | ty::ClosureKind::FnMut)) => kind, Some(ty::ClosureKind::FnOnce) => { @@ -494,8 +496,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { if let LocalInfo::User(BindingForm::Var(VarBindingForm { pat_span, .. })) = *bind_to.local_info() { - let Ok(pat_snippet) = - self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) else { continue; }; + let Ok(pat_snippet) = self.infcx.tcx.sess.source_map().span_to_snippet(pat_span) + else { + continue; + }; let Some(stripped) = pat_snippet.strip_prefix('&') else { suggestions.push(( bind_to.source_info.span.shrink_to_lo(), diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 1f2fefadf..d62541daf 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -2,7 +2,6 @@ use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed use rustc_hir as hir; use rustc_hir::intravisit::Visitor; use rustc_hir::Node; -use rustc_middle::hir::map::Map; use rustc_middle::mir::{Mutability, Place, PlaceRef, ProjectionElem}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{ @@ -568,7 +567,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } }; if let hir::ExprKind::Assign(place, rv, _sp) = expr.kind - && let hir::ExprKind::Index(val, index) = place.kind + && let hir::ExprKind::Index(val, index, _) = place.kind && (expr.span == self.assign_span || place.span == self.assign_span) { // val[index] = rv; @@ -621,7 +620,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { ); self.suggested = true; } else if let hir::ExprKind::MethodCall(_path, receiver, _, sp) = expr.kind - && let hir::ExprKind::Index(val, index) = receiver.kind + && let hir::ExprKind::Index(val, index, _) = receiver.kind && expr.span == self.assign_span { // val[index].path(args..); @@ -646,10 +645,8 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } let hir_map = self.infcx.tcx.hir(); let def_id = self.body.source.def_id(); - let hir_id = hir_map.local_def_id_to_hir_id(def_id.as_local().unwrap()); - let node = hir_map.find(hir_id); - let Some(hir::Node::Item(item)) = node else { return; }; - let hir::ItemKind::Fn(.., body_id) = item.kind else { return; }; + let Some(local_def_id) = def_id.as_local() else { return }; + let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) else { return }; let body = self.infcx.tcx.hir().body(body_id); let mut v = V { assign_span: span, err, ty, suggested: false }; @@ -786,23 +783,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { // In the future, attempt in all path but initially for RHS of for_loop fn suggest_similar_mut_method_for_for_loop(&self, err: &mut Diagnostic) { use hir::{ - BodyId, Expr, + Expr, ExprKind::{Block, Call, DropTemps, Match, MethodCall}, - HirId, ImplItem, ImplItemKind, Item, ItemKind, }; - fn maybe_body_id_of_fn(hir_map: Map<'_>, id: HirId) -> Option { - match hir_map.find(id) { - Some(Node::Item(Item { kind: ItemKind::Fn(_, _, body_id), .. })) - | Some(Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })) => { - Some(*body_id) - } - _ => None, - } - } let hir_map = self.infcx.tcx.hir(); - let mir_body_hir_id = self.mir_hir_id(); - if let Some(fn_body_id) = maybe_body_id_of_fn(hir_map, mir_body_hir_id) { + if let Some(body_id) = hir_map.maybe_body_owned_by(self.mir_def_id()) { if let Block( hir::Block { expr: @@ -836,7 +822,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .. }, _, - ) = hir_map.body(fn_body_id).value.kind + ) = hir_map.body(body_id).value.kind { let opt_suggestions = self .infcx @@ -1098,46 +1084,45 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } let hir_map = self.infcx.tcx.hir(); let def_id = self.body.source.def_id(); - let hir_id = hir_map.local_def_id_to_hir_id(def_id.expect_local()); - let node = hir_map.find(hir_id); - let hir_id = if let Some(hir::Node::Item(item)) = node - && let hir::ItemKind::Fn(.., body_id) = item.kind - { - let body = hir_map.body(body_id); - let mut v = BindingFinder { - span: err_label_span, - hir_id: None, + let hir_id = if let Some(local_def_id) = def_id.as_local() && + let Some(body_id) = hir_map.maybe_body_owned_by(local_def_id) + { + let body = hir_map.body(body_id); + let mut v = BindingFinder { + span: err_label_span, + hir_id: None, + }; + v.visit_body(body); + v.hir_id + } else { + None }; - v.visit_body(body); - v.hir_id - } else { - None - }; + if let Some(hir_id) = hir_id && let Some(hir::Node::Local(local)) = hir_map.find(hir_id) - { - let (changing, span, sugg) = match local.ty { - Some(ty) => ("changing", ty.span, message), - None => ( - "specifying", - local.pat.span.shrink_to_hi(), - format!(": {message}"), - ), - }; - err.span_suggestion_verbose( - span, - format!("consider {changing} this binding's type"), - sugg, - Applicability::HasPlaceholders, - ); - } else { - err.span_label( - err_label_span, - format!( - "consider changing this binding's type to be: `{message}`" - ), - ); - } + { + let (changing, span, sugg) = match local.ty { + Some(ty) => ("changing", ty.span, message), + None => ( + "specifying", + local.pat.span.shrink_to_hi(), + format!(": {message}"), + ), + }; + err.span_suggestion_verbose( + span, + format!("consider {changing} this binding's type"), + sugg, + Applicability::HasPlaceholders, + ); + } else { + err.span_label( + err_label_span, + format!( + "consider changing this binding's type to be: `{message}`" + ), + ); + } } None => {} } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 617c85174..2ea399789 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -22,7 +22,7 @@ use rustc_infer::infer::{ }; use rustc_middle::hir::place::PlaceBase; use rustc_middle::mir::{ConstraintCategory, ReturnConstraint}; -use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::GenericArgs; use rustc_middle::ty::TypeVisitor; use rustc_middle::ty::{self, RegionVid, Ty}; use rustc_middle::ty::{Region, TyCtxt}; @@ -183,9 +183,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { fn is_closure_fn_mut(&self, fr: RegionVid) -> bool { if let Some(ty::ReFree(free_region)) = self.to_error_region(fr).as_deref() && let ty::BoundRegionKind::BrEnv = free_region.bound_region - && let DefiningTy::Closure(_, substs) = self.regioncx.universal_regions().defining_ty + && let DefiningTy::Closure(_, args) = self.regioncx.universal_regions().defining_ty { - return substs.as_closure().kind() == ty::ClosureKind::FnMut; + return args.as_closure().kind() == ty::ClosureKind::FnMut; } false @@ -224,12 +224,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut hrtb_bounds = vec![]; gat_id_and_generics.iter().flatten().for_each(|(gat_hir_id, generics)| { for pred in generics.predicates { - let BoundPredicate( - WhereBoundPredicate { - bound_generic_params, - bounds, - .. - }) = pred else { continue; }; + let BoundPredicate(WhereBoundPredicate { bound_generic_params, bounds, .. }) = pred + else { + continue; + }; if bound_generic_params .iter() .rfind(|bgp| hir.local_def_id_to_hir_id(bgp.def_id) == *gat_hir_id) @@ -504,12 +502,12 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { .to_string(), ) } - ty::Adt(adt, substs) => { - let generic_arg = substs[param_index as usize]; - let identity_substs = - InternalSubsts::identity_for_item(self.infcx.tcx, adt.did()); - let base_ty = Ty::new_adt(self.infcx.tcx, *adt, identity_substs); - let base_generic_arg = identity_substs[param_index as usize]; + ty::Adt(adt, args) => { + let generic_arg = args[param_index as usize]; + let identity_args = + GenericArgs::identity_for_item(self.infcx.tcx, adt.did()); + let base_ty = Ty::new_adt(self.infcx.tcx, *adt, identity_args); + let base_generic_arg = identity_args[param_index as usize]; let adt_desc = adt.descr(); let desc = format!( @@ -522,12 +520,11 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { } ty::FnDef(def_id, _) => { let name = self.infcx.tcx.item_name(*def_id); - let identity_substs = - InternalSubsts::identity_for_item(self.infcx.tcx, *def_id); + let identity_args = GenericArgs::identity_for_item(self.infcx.tcx, *def_id); let desc = format!("a function pointer to `{name}`"); let note = format!( "the function `{name}` is invariant over the parameter `{}`", - identity_substs[param_index as usize] + identity_args[param_index as usize] ); (desc, note) } @@ -575,7 +572,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut output_ty = self.regioncx.universal_regions().unnormalized_output_ty; if let ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) = *output_ty.kind() { - output_ty = self.infcx.tcx.type_of(def_id).subst_identity() + output_ty = self.infcx.tcx.type_of(def_id).instantiate_identity() }; debug!("report_fnmut_error: output_ty={:?}", output_ty); @@ -813,7 +810,9 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { return; } let suitable_region = self.infcx.tcx.is_suitable_region(f); - let Some(suitable_region) = suitable_region else { return; }; + let Some(suitable_region) = suitable_region else { + return; + }; let fn_returns = self.infcx.tcx.return_type_impl_or_dyn_traits(suitable_region.def_id); @@ -848,7 +847,10 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let Some((alias_tys, alias_span, lt_addition_span)) = self .infcx .tcx - .return_type_impl_or_dyn_traits_with_type_alias(suitable_region.def_id) else { return; }; + .return_type_impl_or_dyn_traits_with_type_alias(suitable_region.def_id) + else { + return; + }; // in case the return type of the method is a type alias let mut spans_suggs: Vec<_> = Vec::new(); @@ -896,14 +898,14 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let tcx = self.infcx.tcx; let instance = if let ConstraintCategory::CallArgument(Some(func_ty)) = category { - let (fn_did, substs) = match func_ty.kind() { - ty::FnDef(fn_did, substs) => (fn_did, substs), + let (fn_did, args) = match func_ty.kind() { + ty::FnDef(fn_did, args) => (fn_did, args), _ => return, }; - debug!(?fn_did, ?substs); + debug!(?fn_did, ?args); // Only suggest this on function calls, not closures - let ty = tcx.type_of(fn_did).subst_identity(); + let ty = tcx.type_of(fn_did).instantiate_identity(); debug!("ty: {:?}, ty.kind: {:?}", ty, ty.kind()); if let ty::Closure(_, _) = ty.kind() { return; @@ -913,7 +915,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { tcx, self.param_env, *fn_did, - self.infcx.resolve_vars_if_possible(substs), + self.infcx.resolve_vars_if_possible(args), ) { instance } else { @@ -932,8 +934,13 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { let mut visitor = TraitObjectVisitor(FxIndexSet::default()); visitor.visit_ty(param.param_ty); - let Some((ident, self_ty)) = - NiceRegionError::get_impl_ident_and_self_ty_from_trait(tcx, instance.def_id(), &visitor.0) else { return; }; + let Some((ident, self_ty)) = NiceRegionError::get_impl_ident_and_self_ty_from_trait( + tcx, + instance.def_id(), + &visitor.0, + ) else { + return; + }; self.suggest_constrain_dyn_trait_in_impl(diag, &visitor.0, ident, self_ty); } @@ -981,23 +988,25 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> { sup: RegionVid, ) { let (Some(sub), Some(sup)) = (self.to_error_region(sub), self.to_error_region(sup)) else { - return + return; }; let Some((ty_sub, _)) = self .infcx .tcx .is_suitable_region(sub) - .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.boundregion)) else { - return + .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sub, &anon_reg.boundregion)) + else { + return; }; let Some((ty_sup, _)) = self .infcx .tcx .is_suitable_region(sup) - .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.boundregion)) else { - return + .and_then(|anon_reg| find_anon_type(self.infcx.tcx, sup, &anon_reg.boundregion)) + else { + return; }; suggest_adding_lifetime_params(self.infcx.tcx, sub, ty_sup, ty_sub, diag); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 074f37bed..337af89b2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -5,8 +5,8 @@ use rustc_errors::Diagnostic; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_middle::ty::print::RegionHighlightMode; -use rustc_middle::ty::subst::{GenericArgKind, SubstsRef}; use rustc_middle::ty::{self, RegionVid, Ty}; +use rustc_middle::ty::{GenericArgKind, GenericArgsRef}; use rustc_span::symbol::{kw, sym, Ident, Symbol}; use rustc_span::{Span, DUMMY_SP}; @@ -321,18 +321,18 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { ty::BoundRegionKind::BrEnv => { let def_ty = self.regioncx.universal_regions().defining_ty; - let DefiningTy::Closure(_, substs) = def_ty else { + let DefiningTy::Closure(_, args) = def_ty else { // Can't have BrEnv in functions, constants or generators. bug!("BrEnv outside of closure."); }; - let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) - = tcx.hir().expect_expr(self.mir_hir_id()).kind + let hir::ExprKind::Closure(&hir::Closure { fn_decl_span, .. }) = + tcx.hir().expect_expr(self.mir_hir_id()).kind else { bug!("Closure is not defined by a closure expr"); }; let region_name = self.synthesize_region_name(); - let closure_kind_ty = substs.as_closure().kind_ty(); + let closure_kind_ty = args.as_closure().kind_ty(); let note = match closure_kind_ty.to_opt_closure_kind() { Some(ty::ClosureKind::Fn) => { "closure implements `Fn`, so references to captured variables \ @@ -510,20 +510,17 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } // Match up something like `Foo<'1>` - ( - ty::Adt(_adt_def, substs), - hir::TyKind::Path(hir::QPath::Resolved(None, path)), - ) => { + (ty::Adt(_adt_def, args), hir::TyKind::Path(hir::QPath::Resolved(None, path))) => { match path.res { // Type parameters of the type alias have no reason to // be the same as those of the ADT. // FIXME: We should be able to do something similar to // match_adt_and_segment in this case. - Res::Def(DefKind::TyAlias, _) => (), + Res::Def(DefKind::TyAlias { .. }, _) => (), _ => { if let Some(last_segment) = path.segments.last() { if let Some(highlight) = self.match_adt_and_segment( - substs, + args, needle_fr, last_segment, search_stack, @@ -560,22 +557,22 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { None } - /// We've found an enum/struct/union type with the substitutions - /// `substs` and -- in the HIR -- a path type with the final + /// We've found an enum/struct/union type with the generic args + /// `args` and -- in the HIR -- a path type with the final /// segment `last_segment`. Try to find a `'_` to highlight in /// the generic args (or, if not, to produce new zipped pairs of /// types+hir to search through). fn match_adt_and_segment<'hir>( &self, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, needle_fr: RegionVid, last_segment: &'hir hir::PathSegment<'hir>, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>, ) -> Option { // Did the user give explicit arguments? (e.g., `Foo<..>`) - let args = last_segment.args.as_ref()?; + let explicit_args = last_segment.args.as_ref()?; let lifetime = - self.try_match_adt_and_generic_args(substs, needle_fr, args, search_stack)?; + self.try_match_adt_and_generic_args(args, needle_fr, explicit_args, search_stack)?; if lifetime.is_anonymous() { None } else { @@ -583,19 +580,19 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { } } - /// We've found an enum/struct/union type with the substitutions - /// `substs` and -- in the HIR -- a path with the generic - /// arguments `args`. If `needle_fr` appears in the args, return + /// We've found an enum/struct/union type with the generic args + /// `args` and -- in the HIR -- a path with the generic + /// arguments `hir_args`. If `needle_fr` appears in the args, return /// the `hir::Lifetime` that corresponds to it. If not, push onto /// `search_stack` the types+hir to search through. fn try_match_adt_and_generic_args<'hir>( &self, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, needle_fr: RegionVid, - args: &'hir hir::GenericArgs<'hir>, + hir_args: &'hir hir::GenericArgs<'hir>, search_stack: &mut Vec<(Ty<'tcx>, &'hir hir::Ty<'hir>)>, ) -> Option<&'hir hir::Lifetime> { - for (kind, hir_arg) in iter::zip(substs, args.args) { + for (kind, hir_arg) in iter::zip(args, hir_args.args) { match (kind.unpack(), hir_arg) { (GenericArgKind::Lifetime(r), hir::GenericArg::Lifetime(lt)) => { if r.as_var() == needle_fr { @@ -849,9 +846,10 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { return None; }; - let found = tcx.any_free_region_meets(&tcx.type_of(region_parent).subst_identity(), |r| { - *r == ty::ReEarlyBound(region) - }); + let found = tcx + .any_free_region_meets(&tcx.type_of(region_parent).instantiate_identity(), |r| { + *r == ty::ReEarlyBound(region) + }); Some(RegionName { name: self.synthesize_region_name(), @@ -888,6 +886,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> { .universal_regions() .defining_ty .upvar_tys() + .iter() .position(|ty| self.any_param_predicate_mentions(&predicates, ty, region)) { let (upvar_name, upvar_span) = self.regioncx.get_upvar_name_and_span_for_region( diff --git a/compiler/rustc_borrowck/src/diagnostics/var_name.rs b/compiler/rustc_borrowck/src/diagnostics/var_name.rs index 98418e237..8832d345d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/var_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/var_name.rs @@ -43,7 +43,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { fr: RegionVid, ) -> Option { let upvar_index = - self.universal_regions().defining_ty.upvar_tys().position(|upvar_ty| { + self.universal_regions().defining_ty.upvar_tys().iter().position(|upvar_ty| { debug!("get_upvar_index_for_region: upvar_ty={upvar_ty:?}"); tcx.any_free_region_meets(&upvar_ty, |r| { let r = r.as_var(); @@ -52,7 +52,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { }) })?; - let upvar_ty = self.universal_regions().defining_ty.upvar_tys().nth(upvar_index); + let upvar_ty = self.universal_regions().defining_ty.upvar_tys().get(upvar_index); debug!( "get_upvar_index_for_region: found {fr:?} in upvar {upvar_index} which has type {upvar_ty:?}", diff --git a/compiler/rustc_borrowck/src/facts.rs b/compiler/rustc_borrowck/src/facts.rs index 87fad9a35..9916ebca3 100644 --- a/compiler/rustc_borrowck/src/facts.rs +++ b/compiler/rustc_borrowck/src/facts.rs @@ -202,7 +202,7 @@ trait FactCell { impl FactCell for A { default fn to_string(&self, _location_table: &LocationTable) -> String { - format!("{:?}", self) + format!("{self:?}") } } diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs index 0152d89eb..df5e383ad 100644 --- a/compiler/rustc_borrowck/src/invalidation.rs +++ b/compiler/rustc_borrowck/src/invalidation.rs @@ -353,7 +353,6 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { let tcx = self.tcx; let body = self.body; let borrow_set = self.borrow_set; - let indices = self.borrow_set.indices(); each_borrow_involving_path( self, tcx, @@ -361,7 +360,7 @@ impl<'cx, 'tcx> InvalidationGenerator<'cx, 'tcx> { location, (sd, place), borrow_set, - indices, + |_| true, |this, borrow_index, borrow| { match (rw, borrow.kind) { // Obviously an activation is compatible with its own diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 97d15cb53..efe525c22 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -11,6 +11,7 @@ #![feature(trusted_step)] #![feature(try_blocks)] #![recursion_limit = "256"] +#![cfg_attr(not(bootstrap), allow(internal_features))] #[macro_use] extern crate rustc_middle; @@ -23,7 +24,7 @@ use rustc_errors::{Diagnostic, DiagnosticBuilder, DiagnosticMessage, Subdiagnost use rustc_fluent_macro::fluent_messages; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; -use rustc_index::bit_set::ChunkedBitSet; +use rustc_index::bit_set::{BitSet, ChunkedBitSet}; use rustc_index::{IndexSlice, IndexVec}; use rustc_infer::infer::{ InferCtxt, NllRegionVariableOrigin, RegionVariableOrigin, TyCtxtInferExt, @@ -42,7 +43,6 @@ use rustc_session::lint::builtin::UNUSED_MUT; use rustc_span::{Span, Symbol}; use rustc_target::abi::FieldIdx; -use either::Either; use smallvec::SmallVec; use std::cell::RefCell; use std::collections::BTreeMap; @@ -301,7 +301,7 @@ fn do_mir_borrowck<'tcx>( let movable_generator = // The first argument is the generator type passed by value if let Some(local) = body.local_decls.raw.get(1) - // Get the interior types and substs which typeck computed + // Get the interior types and args which typeck computed && let ty::Generator(_, _, hir::Movability::Static) = local.ty.kind() { false @@ -1035,12 +1035,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { let borrow_set = self.borrow_set.clone(); // Use polonius output if it has been enabled. - let polonius_output = self.polonius_output.clone(); - let borrows_in_scope = if let Some(polonius) = &polonius_output { + let mut polonius_output; + let borrows_in_scope = if let Some(polonius) = &self.polonius_output { let location = self.location_table.start_index(location); - Either::Left(polonius.errors_at(location).iter().copied()) + polonius_output = BitSet::new_empty(borrow_set.len()); + for &idx in polonius.errors_at(location) { + polonius_output.insert(idx); + } + &polonius_output } else { - Either::Right(flow_state.borrows.iter()) + &flow_state.borrows }; each_borrow_involving_path( @@ -1050,7 +1054,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { location, (sd, place_span.0), &borrow_set, - borrows_in_scope, + |borrow_index| borrows_in_scope.contains(borrow_index), |this, borrow_index, borrow| match (rw, borrow.kind) { // Obviously an activation is compatible with its own // reservation (or even prior activating uses of same @@ -1817,8 +1821,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { } ProjectionElem::Subslice { .. } => { - panic!("we don't allow assignments to subslices, location: {:?}", - location); + panic!("we don't allow assignments to subslices, location: {location:?}"); } ProjectionElem::Field(..) => { @@ -2017,8 +2020,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> { self.infcx.tcx.sess.delay_span_bug( span, format!( - "Accessing `{:?}` with the kind `{:?}` shouldn't be possible", - place, kind, + "Accessing `{place:?}` with the kind `{kind:?}` shouldn't be possible", ), ); } @@ -2306,11 +2308,10 @@ mod error { pub fn buffer_error(&mut self, t: DiagnosticBuilder<'_, ErrorGuaranteed>) { if let None = self.tainted_by_errors { - self.tainted_by_errors = Some( - self.tcx - .sess - .delay_span_bug(t.span.clone(), "diagnostic buffered but not emitted"), - ) + self.tainted_by_errors = Some(self.tcx.sess.delay_span_bug( + t.span.clone_ignoring_labels(), + "diagnostic buffered but not emitted", + )) } t.buffer(&mut self.buffered); } diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index b5014a3f4..679a19710 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -347,7 +347,7 @@ pub(super) fn dump_mir_results<'tcx>( for_each_region_constraint( infcx.tcx, closure_region_requirements, - &mut |msg| writeln!(out, "| {}", msg), + &mut |msg| writeln!(out, "| {msg}"), )?; writeln!(out, "|")?; } @@ -426,7 +426,7 @@ pub(super) fn dump_annotation<'tcx>( }; if !opaque_type_values.is_empty() { - err.note(format!("Inferred opaque type values:\n{:#?}", opaque_type_values)); + err.note(format!("Inferred opaque type values:\n{opaque_type_values:#?}")); } errors.buffer_non_error_diag(err); @@ -439,7 +439,7 @@ fn for_each_region_constraint<'tcx>( ) -> io::Result<()> { for req in &closure_region_requirements.outlives_requirements { let subject = match req.subject { - ClosureOutlivesSubject::Region(subject) => format!("{:?}", subject), + ClosureOutlivesSubject::Region(subject) => format!("{subject:?}"), ClosureOutlivesSubject::Ty(ty) => { format!("{:?}", ty.instantiate(tcx, |vid| ty::Region::new_var(tcx, vid))) } diff --git a/compiler/rustc_borrowck/src/path_utils.rs b/compiler/rustc_borrowck/src/path_utils.rs index ea9f8683c..ed93a5609 100644 --- a/compiler/rustc_borrowck/src/path_utils.rs +++ b/compiler/rustc_borrowck/src/path_utils.rs @@ -33,20 +33,24 @@ pub(super) fn each_borrow_involving_path<'tcx, F, I, S>( _location: Location, access_place: (AccessDepth, Place<'tcx>), borrow_set: &BorrowSet<'tcx>, - candidates: I, + is_candidate: I, mut op: F, ) where F: FnMut(&mut S, BorrowIndex, &BorrowData<'tcx>) -> Control, - I: Iterator, + I: Fn(BorrowIndex) -> bool, { let (access, place) = access_place; - // FIXME: analogous code in check_loans first maps `place` to - // its base_path. + // The number of candidates can be large, but borrows for different locals cannot conflict with + // each other, so we restrict the working set a priori. + let Some(borrows_for_place_base) = borrow_set.local_map.get(&place.local) else { return }; // check for loan restricting path P being used. Accounts for // borrows of P, P.a.b, etc. - for i in candidates { + for &i in borrows_for_place_base { + if !is_candidate(i) { + continue; + } let borrowed = &borrow_set[i]; if places_conflict::borrow_conflicts_with_place( diff --git a/compiler/rustc_borrowck/src/places_conflict.rs b/compiler/rustc_borrowck/src/places_conflict.rs index 1217dcb9c..c02f6f3b6 100644 --- a/compiler/rustc_borrowck/src/places_conflict.rs +++ b/compiler/rustc_borrowck/src/places_conflict.rs @@ -1,3 +1,55 @@ +//! The borrowck rules for proving disjointness are applied from the "root" of the +//! borrow forwards, iterating over "similar" projections in lockstep until +//! we can prove overlap one way or another. Essentially, we treat `Overlap` as +//! a monoid and report a conflict if the product ends up not being `Disjoint`. +//! +//! At each step, if we didn't run out of borrow or place, we know that our elements +//! have the same type, and that they only overlap if they are the identical. +//! +//! For example, if we are comparing these: +//! ```text +//! BORROW: (*x1[2].y).z.a +//! ACCESS: (*x1[i].y).w.b +//! ``` +//! +//! Then our steps are: +//! ```text +//! x1 | x1 -- places are the same +//! x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) +//! x1[2].y | x1[i].y -- equal or disjoint +//! *x1[2].y | *x1[i].y -- equal or disjoint +//! (*x1[2].y).z | (*x1[i].y).w -- we are disjoint and don't need to check more! +//! ``` +//! +//! Because `zip` does potentially bad things to the iterator inside, this loop +//! also handles the case where the access might be a *prefix* of the borrow, e.g. +//! +//! ```text +//! BORROW: (*x1[2].y).z.a +//! ACCESS: x1[i].y +//! ``` +//! +//! Then our steps are: +//! ```text +//! x1 | x1 -- places are the same +//! x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) +//! x1[2].y | x1[i].y -- equal or disjoint +//! ``` +//! +//! -- here we run out of access - the borrow can access a part of it. If this +//! is a full deep access, then we *know* the borrow conflicts with it. However, +//! if the access is shallow, then we can proceed: +//! +//! ```text +//! x1[2].y | (*x1[i].y) -- a deref! the access can't get past this, so we +//! are disjoint +//! ``` +//! +//! Our invariant is, that at each step of the iteration: +//! - If we didn't run out of access to match, our borrow and access are comparable +//! and either equal or disjoint. +//! - If we did run out of access, the borrow can access a part of it. + #![deny(rustc::untranslatable_diagnostic)] #![deny(rustc::diagnostic_outside_of_impl)] use crate::ArtificialField; @@ -5,7 +57,7 @@ use crate::Overlap; use crate::{AccessDepth, Deep, Shallow}; use rustc_hir as hir; use rustc_middle::mir::{ - Body, BorrowKind, Local, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem, + Body, BorrowKind, MutBorrowKind, Place, PlaceElem, PlaceRef, ProjectionElem, }; use rustc_middle::ty::{self, TyCtxt}; use std::cmp::max; @@ -48,7 +100,7 @@ pub fn places_conflict<'tcx>( /// access depth. The `bias` parameter is used to determine how the unknowable (comparing runtime /// array indices, for example) should be interpreted - this depends on what the caller wants in /// order to make the conservative choice and preserve soundness. -#[instrument(level = "debug", skip(tcx, body))] +#[inline] pub(super) fn borrow_conflicts_with_place<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -58,15 +110,24 @@ pub(super) fn borrow_conflicts_with_place<'tcx>( access: AccessDepth, bias: PlaceConflictBias, ) -> bool { + let borrow_local = borrow_place.local; + let access_local = access_place.local; + + if borrow_local != access_local { + // We have proven the borrow disjoint - further projections will remain disjoint. + return false; + } + // This Local/Local case is handled by the more general code below, but // it's so common that it's a speed win to check for it first. - if let Some(l1) = borrow_place.as_local() && let Some(l2) = access_place.as_local() { - return l1 == l2; + if borrow_place.projection.is_empty() && access_place.projection.is_empty() { + return true; } place_components_conflict(tcx, body, borrow_place, borrow_kind, access_place, access, bias) } +#[instrument(level = "debug", skip(tcx, body))] fn place_components_conflict<'tcx>( tcx: TyCtxt<'tcx>, body: &Body<'tcx>, @@ -76,65 +137,10 @@ fn place_components_conflict<'tcx>( access: AccessDepth, bias: PlaceConflictBias, ) -> bool { - // The borrowck rules for proving disjointness are applied from the "root" of the - // borrow forwards, iterating over "similar" projections in lockstep until - // we can prove overlap one way or another. Essentially, we treat `Overlap` as - // a monoid and report a conflict if the product ends up not being `Disjoint`. - // - // At each step, if we didn't run out of borrow or place, we know that our elements - // have the same type, and that they only overlap if they are the identical. - // - // For example, if we are comparing these: - // BORROW: (*x1[2].y).z.a - // ACCESS: (*x1[i].y).w.b - // - // Then our steps are: - // x1 | x1 -- places are the same - // x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) - // x1[2].y | x1[i].y -- equal or disjoint - // *x1[2].y | *x1[i].y -- equal or disjoint - // (*x1[2].y).z | (*x1[i].y).w -- we are disjoint and don't need to check more! - // - // Because `zip` does potentially bad things to the iterator inside, this loop - // also handles the case where the access might be a *prefix* of the borrow, e.g. - // - // BORROW: (*x1[2].y).z.a - // ACCESS: x1[i].y - // - // Then our steps are: - // x1 | x1 -- places are the same - // x1[2] | x1[i] -- equal or disjoint (disjoint if indexes differ) - // x1[2].y | x1[i].y -- equal or disjoint - // - // -- here we run out of access - the borrow can access a part of it. If this - // is a full deep access, then we *know* the borrow conflicts with it. However, - // if the access is shallow, then we can proceed: - // - // x1[2].y | (*x1[i].y) -- a deref! the access can't get past this, so we - // are disjoint - // - // Our invariant is, that at each step of the iteration: - // - If we didn't run out of access to match, our borrow and access are comparable - // and either equal or disjoint. - // - If we did run out of access, the borrow can access a part of it. - let borrow_local = borrow_place.local; let access_local = access_place.local; - - match place_base_conflict(borrow_local, access_local) { - Overlap::Arbitrary => { - bug!("Two base can't return Arbitrary"); - } - Overlap::EqualOrDisjoint => { - // This is the recursive case - proceed to the next element. - } - Overlap::Disjoint => { - // We have proven the borrow disjoint - further - // projections will remain disjoint. - debug!("borrow_conflicts_with_place: disjoint"); - return false; - } - } + // borrow_conflicts_with_place should have checked that. + assert_eq!(borrow_local, access_local); // loop invariant: borrow_c is always either equal to access_c or disjoint from it. for ((borrow_place, borrow_c), &access_c) in @@ -277,21 +283,6 @@ fn place_components_conflict<'tcx>( } } -// Given that the bases of `elem1` and `elem2` are always either equal -// or disjoint (and have the same type!), return the overlap situation -// between `elem1` and `elem2`. -fn place_base_conflict(l1: Local, l2: Local) -> Overlap { - if l1 == l2 { - // the same local - base case, equal - debug!("place_element_conflict: DISJOINT-OR-EQ-LOCAL"); - Overlap::EqualOrDisjoint - } else { - // different locals - base case, disjoint - debug!("place_element_conflict: DISJOINT-LOCAL"); - Overlap::Disjoint - } -} - // Given that the bases of `elem1` and `elem2` are always either equal // or disjoint (and have the same type!), return the overlap situation // between `elem1` and `elem2`. diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index 6524b594e..4d620ac9d 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -52,7 +52,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { writeln!(out, "|")?; writeln!(out, "| Inference Constraints")?; - self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {}", msg))?; + self.for_each_constraint(tcx, &mut |msg| writeln!(out, "| {msg}"))?; Ok(()) } @@ -69,7 +69,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { for region in self.definitions.indices() { let value = self.liveness_constraints.region_value_str(region); if value != "{}" { - with_msg(&format!("{:?} live at {}", region, value))?; + with_msg(&format!("{region:?} live at {value}"))?; } } @@ -81,12 +81,9 @@ impl<'tcx> RegionInferenceContext<'tcx> { Locations::All(span) => { ("All", tcx.sess.source_map().span_to_embeddable_string(*span)) } - Locations::Single(loc) => ("Single", format!("{:?}", loc)), + Locations::Single(loc) => ("Single", format!("{loc:?}")), }; - with_msg(&format!( - "{:?}: {:?} due to {:?} at {}({}) ({:?}", - sup, sub, category, name, arg, span - ))?; + with_msg(&format!("{sup:?}: {sub:?} due to {category:?} at {name}({arg}) ({span:?}"))?; } Ok(()) diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index 2e15586e0..a0cf22e93 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -49,7 +49,7 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for RawConstraints<'a, 'tcx> { Some(dot::LabelText::LabelStr(Cow::Borrowed("box"))) } fn node_label(&'this self, n: &RegionVid) -> dot::LabelText<'this> { - dot::LabelText::LabelStr(format!("{:?}", n).into()) + dot::LabelText::LabelStr(format!("{n:?}").into()) } fn edge_label(&'this self, e: &OutlivesConstraint<'tcx>) -> dot::LabelText<'this> { dot::LabelText::LabelStr(format!("{:?}", e.locations).into()) @@ -100,7 +100,7 @@ impl<'a, 'this, 'tcx> dot::Labeller<'this> for SccConstraints<'a, 'tcx> { } fn node_label(&'this self, n: &ConstraintSccIndex) -> dot::LabelText<'this> { let nodes = &self.nodes_per_scc[*n]; - dot::LabelText::LabelStr(format!("{:?} = {:?}", n, nodes).into()) + dot::LabelText::LabelStr(format!("{n:?} = {nodes:?}").into()) } } diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index e45d3a2c8..b8cd94e54 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -259,7 +259,7 @@ fn sccs_info<'cx, 'tcx>( let mut reg_vars_to_origins_str = "region variables to origins:\n".to_string(); for (reg_var, origin) in var_to_origin_sorted.into_iter() { - reg_vars_to_origins_str.push_str(&format!("{:?}: {:?}\n", reg_var, origin)); + reg_vars_to_origins_str.push_str(&format!("{reg_var:?}: {origin:?}\n")); } debug!("{}", reg_vars_to_origins_str); @@ -784,13 +784,20 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// is considered a *lower bound*. If possible, we will modify /// the constraint to set it equal to one of the option regions. /// If we make any changes, returns true, else false. + /// + /// This function only adds the member constraints to the region graph, + /// it does not check them. They are later checked in + /// `check_member_constraints` after the region graph has been computed. #[instrument(skip(self, member_constraint_index), level = "debug")] fn apply_member_constraint( &mut self, scc: ConstraintSccIndex, member_constraint_index: NllMemberConstraintIndex, choice_regions: &[ty::RegionVid], - ) -> bool { + ) { + // Lazily compute the reverse graph, we'll need it later. + self.compute_reverse_scc_graph(); + // Create a mutable vector of the options. We'll try to winnow // them down. let mut choice_regions: Vec = choice_regions.to_vec(); @@ -805,10 +812,11 @@ impl<'tcx> RegionInferenceContext<'tcx> { *c_r = self.scc_representatives[scc]; } - // The 'member region' in a member constraint is part of the - // hidden type, which must be in the root universe. Therefore, - // it cannot have any placeholders in its value. - assert!(self.scc_universes[scc] == ty::UniverseIndex::ROOT); + // If the member region lives in a higher universe, we currently choose + // the most conservative option by leaving it unchanged. + if self.scc_universes[scc] != ty::UniverseIndex::ROOT { + return; + } debug_assert!( self.scc_values.placeholders_contained_in(scc).next().is_none(), "scc {:?} in a member constraint has placeholder value: {:?}", @@ -832,7 +840,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { // free region that must outlive the member region `R0` (`UB: // R0`). Therefore, we need only keep an option `O` if `UB: O` // for all UB. - self.compute_reverse_scc_graph(); let universal_region_relations = &self.universal_region_relations; for ub in self.rev_scc_graph.as_ref().unwrap().upper_bounds(scc) { debug!(?ub); @@ -867,7 +874,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } }) else { debug!("no unique minimum choice"); - return false; + return; }; let min_choice_scc = self.constraint_sccs.scc(min_choice); @@ -878,10 +885,6 @@ impl<'tcx> RegionInferenceContext<'tcx> { min_choice, member_constraint_index, }); - - true - } else { - false } } @@ -1115,7 +1118,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ) -> Option> { let tcx = infcx.tcx; - // Opaque types' substs may include useless lifetimes. + // Opaque types' args may include useless lifetimes. // We will replace them with ReStatic. struct OpaqueFolder<'tcx> { tcx: TyCtxt<'tcx>, @@ -1127,19 +1130,18 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> { use ty::TypeSuperFoldable as _; let tcx = self.tcx; - let &ty::Alias(ty::Opaque, ty::AliasTy { substs, def_id, .. }) = t.kind() else { + let &ty::Alias(ty::Opaque, ty::AliasTy { args, def_id, .. }) = t.kind() else { return t.super_fold_with(self); }; - let substs = - std::iter::zip(substs, tcx.variances_of(def_id)).map(|(arg, v)| { - match (arg.unpack(), v) { - (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => { - tcx.lifetimes.re_static.into() - } - _ => arg.fold_with(self), + let args = std::iter::zip(args, tcx.variances_of(def_id)).map(|(arg, v)| { + match (arg.unpack(), v) { + (ty::GenericArgKind::Lifetime(_), ty::Bivariant) => { + tcx.lifetimes.re_static.into() } - }); - Ty::new_opaque(tcx, def_id, tcx.mk_substs_from_iter(substs)) + _ => arg.fold_with(self), + } + }); + Ty::new_opaque(tcx, def_id, tcx.mk_args_from_iter(args)) } } @@ -2058,10 +2060,17 @@ impl<'tcx> RegionInferenceContext<'tcx> { let mut extra_info = vec![]; for constraint in path.iter() { let outlived = constraint.sub; - let Some(origin) = self.var_infos.get(outlived) else { continue; }; - let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin else { continue; }; + let Some(origin) = self.var_infos.get(outlived) else { + continue; + }; + let RegionVariableOrigin::Nll(NllRegionVariableOrigin::Placeholder(p)) = origin.origin + else { + continue; + }; debug!(?constraint, ?p); - let ConstraintCategory::Predicate(span) = constraint.category else { continue; }; + let ConstraintCategory::Predicate(span) = constraint.category else { + continue; + }; extra_info.push(ExtraConstraintInfo::PlaceholderFromPredicate(span)); // We only want to point to one break; diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs index 1a227f2d1..4da7b6025 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types.rs @@ -6,9 +6,9 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::traits::{Obligation, ObligationCause}; use rustc_middle::traits::DefiningAnchor; -use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty, TyCtxt, TypeFoldable}; +use rustc_middle::ty::{GenericArgKind, GenericArgs}; use rustc_span::Span; use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _; use rustc_trait_selection::traits::ObligationCtxt; @@ -38,15 +38,15 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// back to concrete lifetimes: `'static`, `ReEarlyBound` or `ReFree`. /// /// First we map all the lifetimes in the concrete type to an equal - /// universal region that occurs in the concrete type's substs, in this case - /// this would result in `&'1 i32`. We only consider regions in the substs + /// universal region that occurs in the concrete type's args, in this case + /// this would result in `&'1 i32`. We only consider regions in the args /// in case there is an equal region that does not. For example, this should /// be allowed: /// `fn f<'a: 'b, 'b: 'a>(x: *mut &'b i32) -> impl Sized + 'a { x }` /// /// Then we map the regions in both the type and the subst to their /// `external_name` giving `concrete_type = &'a i32`, - /// `substs = ['static, 'a]`. This will then allow + /// `args = ['static, 'a]`. This will then allow /// `infer_opaque_definition_from_instantiation` to determine that /// `_Return<'_a> = &'_a i32`. /// @@ -73,8 +73,8 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!(?member_constraints); for (opaque_type_key, concrete_type) in opaque_ty_decls { - let substs = opaque_type_key.substs; - debug!(?concrete_type, ?substs); + let args = opaque_type_key.args; + debug!(?concrete_type, ?args); let mut subst_regions = vec![self.universal_regions.fr_static]; @@ -95,7 +95,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { ty::Region::new_error_with_message( infcx.tcx, concrete_type.span, - "opaque type with non-universal region substs", + "opaque type with non-universal region args", ) } } @@ -110,17 +110,17 @@ impl<'tcx> RegionInferenceContext<'tcx> { } debug!(?subst_regions); - // Next, insert universal regions from substs, so we can translate regions that appear - // in them but are not subject to member constraints, for instance closure substs. - let universal_substs = infcx.tcx.fold_regions(substs, |region, _| { + // Next, insert universal regions from args, so we can translate regions that appear + // in them but are not subject to member constraints, for instance closure args. + let universal_args = infcx.tcx.fold_regions(args, |region, _| { if let ty::RePlaceholder(..) = region.kind() { - // Higher kinded regions don't need remapping, they don't refer to anything outside of this the substs. + // Higher kinded regions don't need remapping, they don't refer to anything outside of this the args. return region; } let vid = self.to_region_vid(region); to_universal_region(vid, &mut subst_regions) }); - debug!(?universal_substs); + debug!(?universal_args); debug!(?subst_regions); // Deduplicate the set of regions while keeping the chosen order. @@ -139,7 +139,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { debug!(?universal_concrete_type); let opaque_type_key = - OpaqueTypeKey { def_id: opaque_type_key.def_id, substs: universal_substs }; + OpaqueTypeKey { def_id: opaque_type_key.def_id, args: universal_args }; let ty = infcx.infer_opaque_definition_from_instantiation( opaque_type_key, universal_concrete_type, @@ -175,7 +175,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { /// Map the regions in the type to named regions. This is similar to what /// `infer_opaque_types` does, but can infer any universal region, not only - /// ones from the substs for the opaque type. It also doesn't double check + /// ones from the args for the opaque type. It also doesn't double check /// that the regions produced are in fact equal to the named region they are /// replaced with. This is fine because this function is only to improve the /// region names in error messages. @@ -185,6 +185,21 @@ impl<'tcx> RegionInferenceContext<'tcx> { { tcx.fold_regions(ty, |region, _| match *region { ty::ReVar(vid) => { + let scc = self.constraint_sccs.scc(vid); + + // Special handling of higher-ranked regions. + if self.scc_universes[scc] != ty::UniverseIndex::ROOT { + match self.scc_values.placeholders_contained_in(scc).enumerate().last() { + // If the region contains a single placeholder then they're equal. + Some((0, placeholder)) => { + return ty::Region::new_placeholder(tcx, placeholder); + } + + // Fallback: this will produce a cryptic error message. + _ => return region, + } + } + // Find something that we can name let upper_bound = self.approx_universal_upper_bound(vid); let upper_bound = &self.definitions[upper_bound]; @@ -238,7 +253,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> { /// # Parameters /// /// - `def_id`, the `impl Trait` type - /// - `substs`, the substs used to instantiate this opaque type + /// - `args`, the args used to instantiate this opaque type /// - `instantiated_ty`, the inferred type C1 -- fully resolved, lifted version of /// `opaque_defn.concrete_ty` #[instrument(level = "debug", skip(self))] @@ -309,11 +324,11 @@ fn check_opaque_type_well_formed<'tcx>( }) .build(); let ocx = ObligationCtxt::new(&infcx); - let identity_substs = InternalSubsts::identity_for_item(tcx, def_id); + let identity_args = GenericArgs::identity_for_item(tcx, def_id); // Require that the hidden type actually fulfills all the bounds of the opaque type, even without // the bounds that the function supplies. - let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_substs); + let opaque_ty = Ty::new_opaque(tcx, def_id.to_def_id(), identity_args); ocx.eq(&ObligationCause::misc(definition_span, def_id), param_env, opaque_ty, definition_ty) .map_err(|err| { infcx @@ -339,8 +354,8 @@ fn check_opaque_type_well_formed<'tcx>( // version. let errors = ocx.select_all_or_error(); - // This is still required for many(half of the tests in ui/type-alias-impl-trait) - // tests to pass + // This is fishy, but we check it again in `check_opaque_meets_bounds`. + // Remove once we can prepopulate with known hidden types. let _ = infcx.take_opaque_types(); if errors.is_empty() { @@ -356,40 +371,27 @@ fn check_opaque_type_parameter_valid( span: Span, ) -> Result<(), ErrorGuaranteed> { let opaque_ty_hir = tcx.hir().expect_item(opaque_type_key.def_id); - match opaque_ty_hir.expect_opaque_ty().origin { - // No need to check return position impl trait (RPIT) - // because for type and const parameters they are correct - // by construction: we convert - // - // fn foo() -> impl Trait - // - // into - // - // type Foo - // fn foo() -> Foo. - // - // For lifetime parameters we convert - // - // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> - // - // into - // - // type foo::<'p0..'pn>::Foo<'q0..'qm> - // fn foo() -> foo::<'static..'static>::Foo<'l0..'lm>. - // - // which would error here on all of the `'static` args. - OpaqueTyOrigin::FnReturn(..) | OpaqueTyOrigin::AsyncFn(..) => return Ok(()), - // Check these - OpaqueTyOrigin::TyAlias { .. } => {} - } + let is_ty_alias = match opaque_ty_hir.expect_opaque_ty().origin { + OpaqueTyOrigin::TyAlias { .. } => true, + OpaqueTyOrigin::AsyncFn(..) | OpaqueTyOrigin::FnReturn(..) => false, + }; + let opaque_generics = tcx.generics_of(opaque_type_key.def_id); let mut seen_params: FxIndexMap<_, Vec<_>> = FxIndexMap::default(); - for (i, arg) in opaque_type_key.substs.iter().enumerate() { + for (i, arg) in opaque_type_key.args.iter().enumerate() { + if let Err(guar) = arg.error_reported() { + return Err(guar); + } + let arg_is_param = match arg.unpack() { GenericArgKind::Type(ty) => matches!(ty.kind(), ty::Param(_)), - GenericArgKind::Lifetime(lt) => { + GenericArgKind::Lifetime(lt) if is_ty_alias => { matches!(*lt, ty::ReEarlyBound(_) | ty::ReFree(_)) } + // FIXME(#113916): we can't currently check for unique lifetime params, + // see that issue for more. We will also have to ignore unused lifetime + // params for RPIT, but that's comparatively trivial ✨ + GenericArgKind::Lifetime(_) => continue, GenericArgKind::Const(ct) => matches!(ct.kind(), ty::ConstKind::Param(_)), }; @@ -419,7 +421,7 @@ fn check_opaque_type_parameter_valid( return Err(tcx .sess .struct_span_err(span, "non-defining opaque type use in defining scope") - .span_note(spans, format!("{} used multiple times", descr)) + .span_note(spans, format!("{descr} used multiple times")) .emit()); } } diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 9290e7479..d205862cd 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -470,7 +470,7 @@ fn region_value_str(elements: impl IntoIterator) -> String } push_sep(&mut result); - result.push_str(&format!("{:?}", fr)); + result.push_str(&format!("{fr:?}")); } RegionElement::PlaceholderRegion(placeholder) => { @@ -481,7 +481,7 @@ fn region_value_str(elements: impl IntoIterator) -> String } push_sep(&mut result); - result.push_str(&format!("{:?}", placeholder)); + result.push_str(&format!("{placeholder:?}")); } } } @@ -497,7 +497,7 @@ fn region_value_str(elements: impl IntoIterator) -> String fn push_location_range(str: &mut String, location1: Location, location2: Location) { if location1 == location2 { - str.push_str(&format!("{:?}", location1)); + str.push_str(&format!("{location1:?}")); } else { assert_eq!(location1.block, location2.block); str.push_str(&format!( diff --git a/compiler/rustc_borrowck/src/renumber.rs b/compiler/rustc_borrowck/src/renumber.rs index 4389d2b60..4c69ea843 100644 --- a/compiler/rustc_borrowck/src/renumber.rs +++ b/compiler/rustc_borrowck/src/renumber.rs @@ -6,7 +6,7 @@ use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::mir::visit::{MutVisitor, TyContext}; use rustc_middle::mir::Constant; use rustc_middle::mir::{Body, Location, Promoted}; -use rustc_middle::ty::subst::SubstsRef; +use rustc_middle::ty::GenericArgsRef; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable}; use rustc_span::{Span, Symbol}; @@ -94,10 +94,10 @@ impl<'a, 'tcx> MutVisitor<'tcx> for RegionRenumberer<'a, 'tcx> { } #[instrument(skip(self), level = "debug")] - fn visit_substs(&mut self, substs: &mut SubstsRef<'tcx>, location: Location) { - *substs = self.renumber_regions(*substs, || RegionCtxt::Location(location)); + fn visit_args(&mut self, args: &mut GenericArgsRef<'tcx>, location: Location) { + *args = self.renumber_regions(*args, || RegionCtxt::Location(location)); - debug!(?substs); + debug!(?args); } #[instrument(skip(self), level = "debug")] diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index fceae5bb3..d1d8cfa74 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -398,7 +398,7 @@ pub(crate) enum CaptureReasonSuggest<'tcx> { #[suggestion( borrowck_suggest_create_freash_reborrow, applicability = "maybe-incorrect", - code = "as_mut().", + code = ".as_mut()", style = "verbose" )] FreshReborrow { diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index c19fbf20c..16f5e68a0 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -90,11 +90,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ) { self.prove_predicate( ty::Binder::dummy(ty::PredicateKind::Clause(ty::ClauseKind::Trait( - ty::TraitPredicate { - trait_ref, - constness: ty::BoundConstness::NotConst, - polarity: ty::ImplPolarity::Positive, - }, + ty::TraitPredicate { trait_ref, polarity: ty::ImplPolarity::Positive }, ))), locations, category, diff --git a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs index 71eae7b27..21d8026e1 100644 --- a/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs +++ b/compiler/rustc_borrowck/src/type_check/constraint_conversion.rs @@ -5,7 +5,7 @@ use rustc_infer::infer::outlives::obligations::{TypeOutlives, TypeOutlivesDelega use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; use rustc_infer::infer::{self, InferCtxt, SubregionOrigin}; use rustc_middle::mir::{ClosureOutlivesSubject, ClosureRegionRequirements, ConstraintCategory}; -use rustc_middle::ty::subst::GenericArgKind; +use rustc_middle::ty::GenericArgKind; use rustc_middle::ty::{self, TyCtxt}; use rustc_middle::ty::{TypeFoldable, TypeVisitableExt}; use rustc_span::{Span, DUMMY_SP}; @@ -89,20 +89,20 @@ impl<'a, 'tcx> ConstraintConversion<'a, 'tcx> { /// Given an instance of the closure type, this method instantiates the "extra" requirements /// that we computed for the closure. This has the effect of adding new outlives obligations - /// to existing region variables in `closure_substs`. + /// to existing region variables in `closure_args`. #[instrument(skip(self), level = "debug")] pub fn apply_closure_requirements( &mut self, closure_requirements: &ClosureRegionRequirements<'tcx>, closure_def_id: DefId, - closure_substs: ty::SubstsRef<'tcx>, + closure_args: ty::GenericArgsRef<'tcx>, ) { - // Extract the values of the free regions in `closure_substs` + // Extract the values of the free regions in `closure_args` // into a vector. These are the regions that we will be // relating to one another. let closure_mapping = &UniversalRegions::closure_mapping( self.tcx, - closure_substs, + closure_args, closure_requirements.num_external_vids, closure_def_id.expect_local(), ); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs index b344ab46a..c621df371 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs @@ -2,7 +2,7 @@ use crate::def_use::{self, DefUse}; use crate::location::{LocationIndex, LocationTable}; use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, Place}; -use rustc_middle::ty::subst::GenericArg; +use rustc_middle::ty::GenericArg; use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex}; use super::TypeChecker; @@ -20,7 +20,7 @@ struct UseFactsExtractor<'me, 'tcx> { } // A Visitor to walk through the MIR and extract point-wise facts -impl UseFactsExtractor<'_, '_> { +impl<'tcx> UseFactsExtractor<'_, 'tcx> { fn location_to_index(&self, location: Location) -> LocationIndex { self.location_table.mid_index(location) } @@ -45,7 +45,7 @@ impl UseFactsExtractor<'_, '_> { self.path_accessed_at_base.push((path, self.location_to_index(location))); } - fn place_to_mpi(&self, place: &Place<'_>) -> Option { + fn place_to_mpi(&self, place: &Place<'tcx>) -> Option { match self.move_data.rev_lookup.find(place.as_ref()) { LookupResult::Exact(mpi) => Some(mpi), LookupResult::Parent(mmpi) => mmpi, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index eb02604b9..5702d39db 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -161,8 +161,12 @@ impl<'me, 'typeck, 'flow, 'tcx> LivenessResults<'me, 'typeck, 'flow, 'tcx> { } } - // Runs dropck for locals whose liveness isn't relevant. This is - // necessary to eagerly detect unbound recursion during drop glue computation. + /// Runs dropck for locals whose liveness isn't relevant. This is + /// necessary to eagerly detect unbound recursion during drop glue computation. + /// + /// These are all the locals which do not potentially reference a region local + /// to this body. Locals which only reference free regions are always drop-live + /// and can therefore safely be dropped. fn dropck_boring_locals(&mut self, boring_locals: Vec) { for local in boring_locals { let local_ty = self.cx.body.local_decls[local].ty; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a15e1065c..50d875dfa 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -30,12 +30,12 @@ use rustc_middle::traits::query::NoSolution; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::CastTy; -use rustc_middle::ty::subst::{SubstsRef, UserSubsts}; use rustc_middle::ty::visit::TypeVisitableExt; use rustc_middle::ty::{ self, Binder, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, Dynamic, OpaqueHiddenType, OpaqueTypeKey, RegionVid, Ty, TyCtxt, UserType, UserTypeAnnotationIndex, }; +use rustc_middle::ty::{GenericArgsRef, UserArgs}; use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::symbol::sym; use rustc_span::{Span, DUMMY_SP}; @@ -389,15 +389,12 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } else { self.cx.ascribe_user_type( constant.literal.ty(), - UserType::TypeOf( - uv.def, - UserSubsts { substs: uv.substs, user_self_ty: None }, - ), + UserType::TypeOf(uv.def, UserArgs { args: uv.args, user_self_ty: None }), locations.span(&self.cx.body), ); } } else if let Some(static_def_id) = constant.check_static_ptr(tcx) { - let unnormalized_ty = tcx.type_of(static_def_id).subst_identity(); + let unnormalized_ty = tcx.type_of(static_def_id).instantiate_identity(); let normalized_ty = self.cx.normalize(unnormalized_ty, locations); let literal_ty = constant.literal.ty().builtin_deref(true).unwrap().ty; @@ -411,19 +408,13 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> { } } - if let ty::FnDef(def_id, substs) = *constant.literal.ty().kind() { - // const_trait_impl: use a non-const param env when checking that a FnDef type is well formed. - // this is because the well-formedness of the function does not need to be proved to have `const` - // impls for trait bounds. - let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, substs); - let prev = self.cx.param_env; - self.cx.param_env = prev.without_const(); + if let ty::FnDef(def_id, args) = *constant.literal.ty().kind() { + let instantiated_predicates = tcx.predicates_of(def_id).instantiate(tcx, args); self.cx.normalize_and_prove_instantiated_predicates( def_id, instantiated_predicates, locations, ); - self.cx.param_env = prev; } } } @@ -507,14 +498,13 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { /// Checks that the types internal to the `place` match up with /// what would be expected. + #[instrument(level = "debug", skip(self, location), ret)] fn sanitize_place( &mut self, place: &Place<'tcx>, location: Location, context: PlaceContext, ) -> PlaceTy<'tcx> { - debug!("sanitize_place: {:?}", place); - let mut place_ty = PlaceTy::from_ty(self.body().local_decls[place.local].ty); for elem in place.projection.iter() { @@ -617,7 +607,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { } } - #[instrument(skip(self), level = "debug")] + #[instrument(skip(self, location), ret, level = "debug")] fn sanitize_projection( &mut self, base: PlaceTy<'tcx>, @@ -626,7 +616,6 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { location: Location, context: PlaceContext, ) -> PlaceTy<'tcx> { - debug!("sanitize_projection: {:?} {:?} {:?}", base, pi, place); let tcx = self.tcx(); let base_ty = base.ty; match pi { @@ -666,7 +655,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }) } ProjectionElem::Downcast(maybe_name, index) => match base_ty.kind() { - ty::Adt(adt_def, _substs) if adt_def.is_enum() => { + ty::Adt(adt_def, _args) if adt_def.is_enum() => { if index.as_usize() >= adt_def.variants().len() { PlaceTy::from_ty(span_mirbug_and_err!( self, @@ -776,16 +765,16 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { ) -> Result, FieldAccessError> { let tcx = self.tcx(); - let (variant, substs) = match base_ty { + let (variant, args) = match base_ty { PlaceTy { ty, variant_index: Some(variant_index) } => match *ty.kind() { - ty::Adt(adt_def, substs) => (adt_def.variant(variant_index), substs), - ty::Generator(def_id, substs, _) => { - let mut variants = substs.as_generator().state_tys(def_id, tcx); + ty::Adt(adt_def, args) => (adt_def.variant(variant_index), args), + ty::Generator(def_id, args, _) => { + let mut variants = args.as_generator().state_tys(def_id, tcx); let Some(mut variant) = variants.nth(variant_index.into()) else { bug!( "variant_index of generator out of range: {:?}/{:?}", variant_index, - substs.as_generator().state_tys(def_id, tcx).count() + args.as_generator().state_tys(def_id, tcx).count() ); }; return match variant.nth(field.index()) { @@ -796,29 +785,24 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { _ => bug!("can't have downcast of non-adt non-generator type"), }, PlaceTy { ty, variant_index: None } => match *ty.kind() { - ty::Adt(adt_def, substs) if !adt_def.is_enum() => { - (adt_def.variant(FIRST_VARIANT), substs) + ty::Adt(adt_def, args) if !adt_def.is_enum() => { + (adt_def.variant(FIRST_VARIANT), args) } - ty::Closure(_, substs) => { - return match substs - .as_closure() - .tupled_upvars_ty() - .tuple_fields() - .get(field.index()) - { + ty::Closure(_, args) => { + return match args.as_closure().upvar_tys().get(field.index()) { Some(&ty) => Ok(ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_closure().upvar_tys().count(), + field_count: args.as_closure().upvar_tys().len(), }), }; } - ty::Generator(_, substs, _) => { + ty::Generator(_, args, _) => { // Only prefix fields (upvars and current state) are // accessible without a variant index. - return match substs.as_generator().prefix_tys().nth(field.index()) { - Some(ty) => Ok(ty), + return match args.as_generator().prefix_tys().get(field.index()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_generator().prefix_tys().count(), + field_count: args.as_generator().prefix_tys().len(), }), }; } @@ -840,7 +824,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> { }; if let Some(field) = variant.fields.get(field) { - Ok(self.cx.normalize(field.ty(tcx, substs), location)) + Ok(self.cx.normalize(field.ty(tcx, args), location)) } else { Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() }) } @@ -1065,7 +1049,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ocx.infcx.add_item_bounds_for_hidden_type( opaque_type_key.def_id.to_def_id(), - opaque_type_key.substs, + opaque_type_key.args, cause, param_env, hidden_ty.ty, @@ -1770,32 +1754,32 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let tcx = self.tcx(); match *ak { - AggregateKind::Adt(adt_did, variant_index, substs, _, active_field_index) => { + AggregateKind::Adt(adt_did, variant_index, args, _, active_field_index) => { let def = tcx.adt_def(adt_did); let variant = &def.variant(variant_index); let adj_field_index = active_field_index.unwrap_or(field_index); if let Some(field) = variant.fields.get(adj_field_index) { - Ok(self.normalize(field.ty(tcx, substs), location)) + Ok(self.normalize(field.ty(tcx, args), location)) } else { Err(FieldAccessError::OutOfRange { field_count: variant.fields.len() }) } } - AggregateKind::Closure(_, substs) => { - match substs.as_closure().upvar_tys().nth(field_index.as_usize()) { - Some(ty) => Ok(ty), + AggregateKind::Closure(_, args) => { + match args.as_closure().upvar_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_closure().upvar_tys().count(), + field_count: args.as_closure().upvar_tys().len(), }), } } - AggregateKind::Generator(_, substs, _) => { + AggregateKind::Generator(_, args, _) => { // It doesn't make sense to look at a field beyond the prefix; // these require a variant index, and are not initialized in // aggregate rvalues. - match substs.as_generator().prefix_tys().nth(field_index.as_usize()) { - Some(ty) => Ok(ty), + match args.as_generator().prefix_tys().get(field_index.as_usize()) { + Some(ty) => Ok(*ty), None => Err(FieldAccessError::OutOfRange { - field_count: substs.as_generator().prefix_tys().count(), + field_count: args.as_generator().prefix_tys().len(), }), } } @@ -1821,8 +1805,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { let def_id = uv.def; if tcx.def_kind(def_id) == DefKind::InlineConst { let def_id = def_id.expect_local(); - let predicates = - self.prove_closure_bounds(tcx, def_id, uv.substs, location); + let predicates = self.prove_closure_bounds(tcx, def_id, uv.args, location); self.normalize_and_prove_instantiated_predicates( def_id.to_def_id(), predicates, @@ -1939,7 +1922,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { CastKind::PointerCoercion(PointerCoercion::ClosureFnPointer(unsafety)) => { let sig = match op.ty(body, tcx).kind() { - ty::Closure(_, substs) => substs.as_closure().sig(), + ty::Closure(_, args) => args.as_closure().sig(), _ => bug!(), }; let ty_fn_ptr_from = @@ -2039,28 +2022,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } CastKind::PointerCoercion(PointerCoercion::MutToConstPointer) => { - let ty::RawPtr(ty::TypeAndMut { - ty: ty_from, - mutbl: hir::Mutability::Mut, - }) = op.ty(body, tcx).kind() else { - span_mirbug!( - self, - rvalue, - "unexpected base type for cast {:?}", - ty, - ); + let ty::RawPtr(ty::TypeAndMut { ty: ty_from, mutbl: hir::Mutability::Mut }) = + op.ty(body, tcx).kind() + else { + span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,); return; }; - let ty::RawPtr(ty::TypeAndMut { - ty: ty_to, - mutbl: hir::Mutability::Not, - }) = ty.kind() else { - span_mirbug!( - self, - rvalue, - "unexpected target type for cast {:?}", - ty, - ); + let ty::RawPtr(ty::TypeAndMut { ty: ty_to, mutbl: hir::Mutability::Not }) = + ty.kind() + else { + span_mirbug!(self, rvalue, "unexpected target type for cast {:?}", ty,); return; }; if let Err(terr) = self.sub_types( @@ -2603,8 +2574,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { ); let (def_id, instantiated_predicates) = match *aggregate_kind { - AggregateKind::Adt(adt_did, _, substs, _, _) => { - (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, substs)) + AggregateKind::Adt(adt_did, _, args, _, _) => { + (adt_did, tcx.predicates_of(adt_did).instantiate(tcx, args)) } // For closures, we have some **extra requirements** we @@ -2626,9 +2597,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { // desugaring. A closure gets desugared to a struct, and // these extra requirements are basically like where // clauses on the struct. - AggregateKind::Closure(def_id, substs) - | AggregateKind::Generator(def_id, substs, _) => { - (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), substs, location)) + AggregateKind::Closure(def_id, args) | AggregateKind::Generator(def_id, args, _) => { + (def_id, self.prove_closure_bounds(tcx, def_id.expect_local(), args, location)) } AggregateKind::Array(_) | AggregateKind::Tuple => { @@ -2647,7 +2617,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { &mut self, tcx: TyCtxt<'tcx>, def_id: LocalDefId, - substs: SubstsRef<'tcx>, + args: GenericArgsRef<'tcx>, location: Location, ) -> ty::InstantiatedPredicates<'tcx> { if let Some(closure_requirements) = &tcx.mir_borrowck(def_id).closure_requirements { @@ -2665,26 +2635,26 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { .apply_closure_requirements( &closure_requirements, def_id.to_def_id(), - substs, + args, ); } - // Now equate closure substs to regions inherited from `typeck_root_def_id`. Fixes #98589. + // Now equate closure args to regions inherited from `typeck_root_def_id`. Fixes #98589. let typeck_root_def_id = tcx.typeck_root_def_id(self.body.source.def_id()); - let typeck_root_substs = ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id); + let typeck_root_args = ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id); - let parent_substs = match tcx.def_kind(def_id) { - DefKind::Closure => substs.as_closure().parent_substs(), - DefKind::Generator => substs.as_generator().parent_substs(), - DefKind::InlineConst => substs.as_inline_const().parent_substs(), + let parent_args = match tcx.def_kind(def_id) { + DefKind::Closure => args.as_closure().parent_args(), + DefKind::Generator => args.as_generator().parent_args(), + DefKind::InlineConst => args.as_inline_const().parent_args(), other => bug!("unexpected item {:?}", other), }; - let parent_substs = tcx.mk_substs(parent_substs); + let parent_args = tcx.mk_args(parent_args); - assert_eq!(typeck_root_substs.len(), parent_substs.len()); - if let Err(_) = self.eq_substs( - typeck_root_substs, - parent_substs, + assert_eq!(typeck_root_args.len(), parent_args.len()); + if let Err(_) = self.eq_args( + typeck_root_args, + parent_args, location.to_locations(), ConstraintCategory::BoringNoLocation, ) { @@ -2692,12 +2662,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { self, def_id, "could not relate closure to parent {:?} != {:?}", - typeck_root_substs, - parent_substs + typeck_root_args, + parent_args ); } - tcx.predicates_of(def_id).instantiate(tcx, substs) + tcx.predicates_of(def_id).instantiate(tcx, args) } #[instrument(skip(self, body), level = "debug")] diff --git a/compiler/rustc_borrowck/src/type_check/relate_tys.rs b/compiler/rustc_borrowck/src/type_check/relate_tys.rs index 8c4bfb2c6..e0c629562 100644 --- a/compiler/rustc_borrowck/src/type_check/relate_tys.rs +++ b/compiler/rustc_borrowck/src/type_check/relate_tys.rs @@ -42,10 +42,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { } /// Add sufficient constraints to ensure `a == b`. See also [Self::relate_types]. - pub(super) fn eq_substs( + pub(super) fn eq_args( &mut self, - a: ty::SubstsRef<'tcx>, - b: ty::SubstsRef<'tcx>, + a: ty::GenericArgsRef<'tcx>, + b: ty::GenericArgsRef<'tcx>, locations: Locations, category: ConstraintCategory<'tcx>, ) -> Result<(), NoSolution> { diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 7821b82bf..56945f43f 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -12,7 +12,6 @@ //! The code in this file doesn't *do anything* with those results; it //! just returns them for other code to use. -use either::Either; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Diagnostic; use rustc_hir as hir; @@ -22,8 +21,8 @@ use rustc_hir::BodyOwnerKind; use rustc_index::IndexVec; use rustc_infer::infer::NllRegionVariableOrigin; use rustc_middle::ty::fold::TypeFoldable; -use rustc_middle::ty::{self, InlineConstSubsts, InlineConstSubstsParts, RegionVid, Ty, TyCtxt}; -use rustc_middle::ty::{InternalSubsts, SubstsRef}; +use rustc_middle::ty::{self, InlineConstArgs, InlineConstArgsParts, RegionVid, Ty, TyCtxt}; +use rustc_middle::ty::{GenericArgs, GenericArgsRef}; use rustc_span::symbol::{kw, sym}; use rustc_span::Symbol; use std::iter; @@ -88,26 +87,26 @@ pub struct UniversalRegions<'tcx> { #[derive(Copy, Clone, Debug)] pub enum DefiningTy<'tcx> { /// The MIR is a closure. The signature is found via - /// `ClosureSubsts::closure_sig_ty`. - Closure(DefId, SubstsRef<'tcx>), + /// `ClosureArgs::closure_sig_ty`. + Closure(DefId, GenericArgsRef<'tcx>), /// The MIR is a generator. The signature is that generators take /// no parameters and return the result of - /// `ClosureSubsts::generator_return_ty`. - Generator(DefId, SubstsRef<'tcx>, hir::Movability), + /// `ClosureArgs::generator_return_ty`. + Generator(DefId, GenericArgsRef<'tcx>, hir::Movability), - /// The MIR is a fn item with the given `DefId` and substs. The signature + /// The MIR is a fn item with the given `DefId` and args. The signature /// of the function can be bound then with the `fn_sig` query. - FnDef(DefId, SubstsRef<'tcx>), + FnDef(DefId, GenericArgsRef<'tcx>), /// The MIR represents some form of constant. The signature then /// is that it has no inputs and a single return value, which is /// the value of the constant. - Const(DefId, SubstsRef<'tcx>), + Const(DefId, GenericArgsRef<'tcx>), /// The MIR represents an inline const. The signature has no inputs and a - /// single return value found via `InlineConstSubsts::ty`. - InlineConst(DefId, SubstsRef<'tcx>), + /// single return value found via `InlineConstArgs::ty`. + InlineConst(DefId, GenericArgsRef<'tcx>), } impl<'tcx> DefiningTy<'tcx> { @@ -115,14 +114,12 @@ impl<'tcx> DefiningTy<'tcx> { /// not a closure or generator, there are no upvars, and hence it /// will be an empty list. The order of types in this list will /// match up with the upvar order in the HIR, typesystem, and MIR. - pub fn upvar_tys(self) -> impl Iterator> + 'tcx { + pub fn upvar_tys(self) -> &'tcx ty::List> { match self { - DefiningTy::Closure(_, substs) => Either::Left(substs.as_closure().upvar_tys()), - DefiningTy::Generator(_, substs, _) => { - Either::Right(Either::Left(substs.as_generator().upvar_tys())) - } + DefiningTy::Closure(_, args) => args.as_closure().upvar_tys(), + DefiningTy::Generator(_, args, _) => args.as_generator().upvar_tys(), DefiningTy::FnDef(..) | DefiningTy::Const(..) | DefiningTy::InlineConst(..) => { - Either::Right(Either::Right(iter::empty())) + ty::List::empty() } } } @@ -164,9 +161,9 @@ struct UniversalRegionIndices<'tcx> { /// used because trait matching and type-checking will feed us /// region constraints that reference those regions and we need to /// be able to map them to our internal `RegionVid`. This is - /// basically equivalent to an `InternalSubsts`, except that it also + /// basically equivalent to an `GenericArgs`, except that it also /// contains an entry for `ReStatic` -- it might be nice to just - /// use a substs, and then handle `ReStatic` another way. + /// use a args, and then handle `ReStatic` another way. indices: FxHashMap, RegionVid>, /// The vid assigned to `'static`. Used only for diagnostics. @@ -243,13 +240,13 @@ impl<'tcx> UniversalRegions<'tcx> { /// `V[1]: V[2]`. pub fn closure_mapping( tcx: TyCtxt<'tcx>, - closure_substs: SubstsRef<'tcx>, + closure_args: GenericArgsRef<'tcx>, expected_num_vars: usize, closure_def_id: LocalDefId, ) -> IndexVec> { let mut region_mapping = IndexVec::with_capacity(expected_num_vars); region_mapping.push(tcx.lifetimes.re_static); - tcx.for_each_free_region(&closure_substs, |fr| { + tcx.for_each_free_region(&closure_args, |fr| { region_mapping.push(fr); }); @@ -334,11 +331,11 @@ impl<'tcx> UniversalRegions<'tcx> { /// state. pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diagnostic) { match self.defining_ty { - DefiningTy::Closure(def_id, substs) => { + DefiningTy::Closure(def_id, args) => { err.note(format!( - "defining type: {} with closure substs {:#?}", - tcx.def_path_str_with_substs(def_id, substs), - &substs[tcx.generics_of(def_id).parent_count..], + "defining type: {} with closure args {:#?}", + tcx.def_path_str_with_args(def_id, args), + &args[tcx.generics_of(def_id).parent_count..], )); // FIXME: It'd be nice to print the late-bound regions @@ -350,11 +347,11 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(format!("late-bound region is {:?}", self.to_region_vid(r))); }); } - DefiningTy::Generator(def_id, substs, _) => { + DefiningTy::Generator(def_id, args, _) => { err.note(format!( - "defining type: {} with generator substs {:#?}", - tcx.def_path_str_with_substs(def_id, substs), - &substs[tcx.generics_of(def_id).parent_count..], + "defining type: {} with generator args {:#?}", + tcx.def_path_str_with_args(def_id, args), + &args[tcx.generics_of(def_id).parent_count..], )); // FIXME: As above, we'd like to print out the region @@ -364,22 +361,19 @@ impl<'tcx> UniversalRegions<'tcx> { err.note(format!("late-bound region is {:?}", self.to_region_vid(r))); }); } - DefiningTy::FnDef(def_id, substs) => { - err.note(format!( - "defining type: {}", - tcx.def_path_str_with_substs(def_id, substs), - )); + DefiningTy::FnDef(def_id, args) => { + err.note(format!("defining type: {}", tcx.def_path_str_with_args(def_id, args),)); } - DefiningTy::Const(def_id, substs) => { + DefiningTy::Const(def_id, args) => { err.note(format!( "defining constant type: {}", - tcx.def_path_str_with_substs(def_id, substs), + tcx.def_path_str_with_args(def_id, args), )); } - DefiningTy::InlineConst(def_id, substs) => { + DefiningTy::InlineConst(def_id, args) => { err.note(format!( "defining inline constant type: {}", - tcx.def_path_str_with_substs(def_id, substs), + tcx.def_path_str_with_args(def_id, args), )); } } @@ -501,8 +495,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { .as_var(); let region = ty::Region::new_var(self.infcx.tcx, reg_vid); - let va_list_ty = - self.infcx.tcx.type_of(va_list_did).subst(self.infcx.tcx, &[region.into()]); + let va_list_ty = self + .infcx + .tcx + .type_of(va_list_did) + .instantiate(self.infcx.tcx, &[region.into()]); unnormalized_input_tys = self.infcx.tcx.mk_type_list_from_iter( unnormalized_input_tys.iter().copied().chain(iter::once(va_list_ty)), @@ -522,7 +519,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { debug!("build: local regions = {}..{}", first_local_index, num_universals); let yield_ty = match defining_ty { - DefiningTy::Generator(_, substs, _) => Some(substs.as_generator().yield_ty()), + DefiningTy::Generator(_, args, _) => Some(args.as_generator().yield_ty()), _ => None, }; @@ -548,7 +545,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { match tcx.hir().body_owner_kind(self.mir_def) { BodyOwnerKind::Closure | BodyOwnerKind::Fn => { - let defining_ty = tcx.type_of(self.mir_def).subst_identity(); + let defining_ty = tcx.type_of(self.mir_def).instantiate_identity(); debug!("defining_ty (pre-replacement): {:?}", defining_ty); @@ -556,11 +553,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { self.infcx.replace_free_regions_with_nll_infer_vars(FR, defining_ty); match *defining_ty.kind() { - ty::Closure(def_id, substs) => DefiningTy::Closure(def_id, substs), - ty::Generator(def_id, substs, movability) => { - DefiningTy::Generator(def_id, substs, movability) + ty::Closure(def_id, args) => DefiningTy::Closure(def_id, args), + ty::Generator(def_id, args, movability) => { + DefiningTy::Generator(def_id, args, movability) } - ty::FnDef(def_id, substs) => DefiningTy::FnDef(def_id, substs), + ty::FnDef(def_id, args) => DefiningTy::FnDef(def_id, args), _ => span_bug!( tcx.def_span(self.mir_def), "expected defining type for `{:?}`: `{:?}`", @@ -571,11 +568,11 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { } BodyOwnerKind::Const | BodyOwnerKind::Static(..) => { - let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id); + let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); if self.mir_def.to_def_id() == typeck_root_def_id { - let substs = - self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_substs); - DefiningTy::Const(self.mir_def.to_def_id(), substs) + let args = + self.infcx.replace_free_regions_with_nll_infer_vars(FR, identity_args); + DefiningTy::Const(self.mir_def.to_def_id(), args) } else { // FIXME this line creates a dependency between borrowck and typeck. // @@ -584,18 +581,18 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // into borrowck, which is ICE #78174. // // As a workaround, inline consts have an additional generic param (`ty` - // below), so that `type_of(inline_const_def_id).substs(substs)` uses the + // below), so that `type_of(inline_const_def_id).args(args)` uses the // proper type with NLL infer vars. let ty = tcx .typeck(self.mir_def) .node_type(tcx.local_def_id_to_hir_id(self.mir_def)); - let substs = InlineConstSubsts::new( + let args = InlineConstArgs::new( tcx, - InlineConstSubstsParts { parent_substs: identity_substs, ty }, + InlineConstArgsParts { parent_args: identity_args, ty }, ) - .substs; - let substs = self.infcx.replace_free_regions_with_nll_infer_vars(FR, substs); - DefiningTy::InlineConst(self.mir_def.to_def_id(), substs) + .args; + let args = self.infcx.replace_free_regions_with_nll_infer_vars(FR, args); + DefiningTy::InlineConst(self.mir_def.to_def_id(), args) } } } @@ -612,29 +609,29 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { ) -> UniversalRegionIndices<'tcx> { let tcx = self.infcx.tcx; let typeck_root_def_id = tcx.typeck_root_def_id(self.mir_def.to_def_id()); - let identity_substs = InternalSubsts::identity_for_item(tcx, typeck_root_def_id); - let fr_substs = match defining_ty { - DefiningTy::Closure(_, substs) - | DefiningTy::Generator(_, substs, _) - | DefiningTy::InlineConst(_, substs) => { + let identity_args = GenericArgs::identity_for_item(tcx, typeck_root_def_id); + let fr_args = match defining_ty { + DefiningTy::Closure(_, args) + | DefiningTy::Generator(_, args, _) + | DefiningTy::InlineConst(_, args) => { // In the case of closures, we rely on the fact that - // the first N elements in the ClosureSubsts are + // the first N elements in the ClosureArgs are // inherited from the `typeck_root_def_id`. // Therefore, when we zip together (below) with - // `identity_substs`, we will get only those regions + // `identity_args`, we will get only those regions // that correspond to early-bound regions declared on // the `typeck_root_def_id`. - assert!(substs.len() >= identity_substs.len()); - assert_eq!(substs.regions().count(), identity_substs.regions().count()); - substs + assert!(args.len() >= identity_args.len()); + assert_eq!(args.regions().count(), identity_args.regions().count()); + args } - DefiningTy::FnDef(_, substs) | DefiningTy::Const(_, substs) => substs, + DefiningTy::FnDef(_, args) | DefiningTy::Const(_, args) => args, }; let global_mapping = iter::once((tcx.lifetimes.re_static, fr_static)); let subst_mapping = - iter::zip(identity_substs.regions(), fr_substs.regions().map(|r| r.as_var())); + iter::zip(identity_args.regions(), fr_args.regions().map(|r| r.as_var())); UniversalRegionIndices { indices: global_mapping.chain(subst_mapping).collect(), fr_static } } @@ -646,9 +643,9 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { ) -> ty::Binder<'tcx, &'tcx ty::List>> { let tcx = self.infcx.tcx; match defining_ty { - DefiningTy::Closure(def_id, substs) => { + DefiningTy::Closure(def_id, args) => { assert_eq!(self.mir_def.to_def_id(), def_id); - let closure_sig = substs.as_closure().sig(); + let closure_sig = args.as_closure().sig(); let inputs_and_output = closure_sig.inputs_and_output(); let bound_vars = tcx.mk_bound_variable_kinds_from_iter( inputs_and_output @@ -661,7 +658,7 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { kind: ty::BrEnv, }; let env_region = ty::Region::new_late_bound(tcx, ty::INNERMOST, br); - let closure_ty = tcx.closure_env_ty(def_id, substs, env_region).unwrap(); + let closure_ty = tcx.closure_env_ty(def_id, args, env_region).unwrap(); // The "inputs" of the closure in the // signature appear as a tuple. The MIR side @@ -681,18 +678,18 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { ) } - DefiningTy::Generator(def_id, substs, movability) => { + DefiningTy::Generator(def_id, args, movability) => { assert_eq!(self.mir_def.to_def_id(), def_id); - let resume_ty = substs.as_generator().resume_ty(); - let output = substs.as_generator().return_ty(); - let generator_ty = Ty::new_generator(tcx, def_id, substs, movability); + let resume_ty = args.as_generator().resume_ty(); + let output = args.as_generator().return_ty(); + let generator_ty = Ty::new_generator(tcx, def_id, args, movability); let inputs_and_output = self.infcx.tcx.mk_type_list(&[generator_ty, resume_ty, output]); ty::Binder::dummy(inputs_and_output) } DefiningTy::FnDef(def_id, _) => { - let sig = tcx.fn_sig(def_id).subst_identity(); + let sig = tcx.fn_sig(def_id).instantiate_identity(); let sig = indices.fold_to_region_vids(tcx, sig); sig.inputs_and_output() } @@ -701,14 +698,14 @@ impl<'cx, 'tcx> UniversalRegionsBuilder<'cx, 'tcx> { // For a constant body, there are no inputs, and one // "output" (the type of the constant). assert_eq!(self.mir_def.to_def_id(), def_id); - let ty = tcx.type_of(self.mir_def).subst_identity(); + let ty = tcx.type_of(self.mir_def).instantiate_identity(); let ty = indices.fold_to_region_vids(tcx, ty); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } - DefiningTy::InlineConst(def_id, substs) => { + DefiningTy::InlineConst(def_id, args) => { assert_eq!(self.mir_def.to_def_id(), def_id); - let ty = substs.as_inline_const().ty(); + let ty = args.as_inline_const().ty(); ty::Binder::dummy(tcx.mk_type_list(&[ty])) } } @@ -929,7 +926,9 @@ fn for_each_late_bound_region_in_item<'tcx>( } for bound_var in tcx.late_bound_vars(tcx.hir().local_def_id_to_hir_id(mir_def_id)) { - let ty::BoundVariableKind::Region(bound_region) = bound_var else { continue; }; + let ty::BoundVariableKind::Region(bound_region) = bound_var else { + continue; + }; let liberated_region = ty::Region::new_free(tcx, mir_def_id.to_def_id(), bound_region); f(liberated_region); } -- cgit v1.2.3