diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 03:59:35 +0000 |
commit | d1b2d29528b7794b41e66fc2136e395a02f8529b (patch) | |
tree | a4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_mir_build/src | |
parent | Releasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.tar.xz rustc-d1b2d29528b7794b41e66fc2136e395a02f8529b.zip |
Merging upstream version 1.73.0+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'compiler/rustc_mir_build/src')
24 files changed, 546 insertions, 338 deletions
diff --git a/compiler/rustc_mir_build/src/build/custom/parse.rs b/compiler/rustc_mir_build/src/build/custom/parse.rs index 803207d9d..60c4a0416 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse.rs @@ -74,7 +74,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { kind @ StmtKind::Let { pattern, .. } => { return Err(ParseError { span: pattern.span, - item_description: format!("{:?}", kind), + item_description: format!("{kind:?}"), expected: "expression".to_string(), }); } @@ -241,9 +241,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }); } - let Some(trailing) = block.expr else { - return Err(self.expr_error(expr_id, "terminator")) - }; + let Some(trailing) = block.expr else { return Err(self.expr_error(expr_id, "terminator")) }; let span = self.thir[trailing].span; let terminator = self.parse_terminator(trailing)?; data.terminator = Some(Terminator { diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs index 4cb9d7bab..26662f5de 100644 --- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs +++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs @@ -61,11 +61,9 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { }) }, @call("mir_call", args) => { - let destination = self.parse_place(args[0])?; - let target = self.parse_block(args[1])?; - self.parse_call(args[2], destination, target) + self.parse_call(args) }, - ExprKind::Match { scrutinee, arms } => { + ExprKind::Match { scrutinee, arms, .. } => { let discr = self.parse_operand(*scrutinee)?; self.parse_match(arms, expr.span).map(|t| TerminatorKind::SwitchInt { discr, targets: t }) }, @@ -78,7 +76,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { span, item_description: "no arms".to_string(), expected: "at least one arm".to_string(), - }) + }); }; let otherwise = &self.thir[*otherwise]; @@ -87,7 +85,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { span: otherwise.span, item_description: format!("{:?}", otherwise.pattern.kind), expected: "wildcard pattern".to_string(), - }) + }); }; let otherwise = self.parse_block(otherwise.body)?; @@ -100,7 +98,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { span: arm.pattern.span, item_description: format!("{:?}", arm.pattern.kind), expected: "constant pattern".to_string(), - }) + }); }; values.push(value.eval_bits(self.tcx, self.param_env, arm.pattern.ty)); targets.push(self.parse_block(arm.body)?); @@ -109,13 +107,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise)) } - fn parse_call( - &self, - expr_id: ExprId, - destination: Place<'tcx>, - target: BasicBlock, - ) -> PResult<TerminatorKind<'tcx>> { - parse_by_kind!(self, expr_id, _, "function call", + fn parse_call(&self, args: &[ExprId]) -> PResult<TerminatorKind<'tcx>> { + let (destination, call) = parse_by_kind!(self, args[0], _, "function call", + ExprKind::Assign { lhs, rhs } => (*lhs, *rhs), + ); + let destination = self.parse_place(destination)?; + let target = self.parse_block(args[1])?; + + parse_by_kind!(self, call, _, "function call", ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => { let fun = self.parse_operand(*fun)?; let args = args @@ -192,12 +191,12 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> { fields.iter().map(|e| self.parse_operand(*e)).collect::<Result<_, _>>()? )) }, - ExprKind::Adt(box AdtExpr{ adt_def, variant_index, substs, fields, .. }) => { + ExprKind::Adt(box AdtExpr{ adt_def, variant_index, args, fields, .. }) => { let is_union = adt_def.is_union(); let active_field_index = is_union.then(|| fields[0].name); Ok(Rvalue::Aggregate( - Box::new(AggregateKind::Adt(adt_def.did(), *variant_index, substs, None, active_field_index)), + Box::new(AggregateKind::Adt(adt_def.did(), *variant_index, args, None, active_field_index)), fields.iter().map(|f| self.parse_operand(f.expr)).collect::<Result<_, _>>()? )) }, diff --git a/compiler/rustc_mir_build/src/build/expr/as_constant.rs b/compiler/rustc_mir_build/src/build/expr/as_constant.rs index 3fe751ae0..aaa37446e 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_constant.rs @@ -75,10 +75,10 @@ pub fn as_constant_inner<'tcx>( Constant { span, user_ty, literal } } - ExprKind::NamedConst { def_id, substs, ref user_ty } => { + ExprKind::NamedConst { def_id, args, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); - let uneval = mir::UnevaluatedConst::new(def_id, substs); + let uneval = mir::UnevaluatedConst::new(def_id, args); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty, span, literal } @@ -89,8 +89,8 @@ pub fn as_constant_inner<'tcx>( Constant { user_ty: None, span, literal } } - ExprKind::ConstBlock { did: def_id, substs } => { - let uneval = mir::UnevaluatedConst::new(def_id, substs); + ExprKind::ConstBlock { did: def_id, args } => { + let uneval = mir::UnevaluatedConst::new(def_id, args); let literal = ConstantKind::Unevaluated(uneval, ty); Constant { user_ty: None, span, literal } diff --git a/compiler/rustc_mir_build/src/build/expr/as_place.rs b/compiler/rustc_mir_build/src/build/expr/as_place.rs index 60acd279f..2e7ef265a 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_place.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_place.rs @@ -175,11 +175,8 @@ fn to_upvars_resolved_place_builder<'tcx>( projection: &[PlaceElem<'tcx>], ) -> Option<PlaceBuilder<'tcx>> { let Some((capture_index, capture)) = - find_capture_matching_projections( - &cx.upvars, - var_hir_id, - &projection, - ) else { + find_capture_matching_projections(&cx.upvars, var_hir_id, &projection) + else { let closure_span = cx.tcx.def_span(closure_def_id); if !enable_precise_capture(closure_span) { bug!( @@ -189,10 +186,7 @@ fn to_upvars_resolved_place_builder<'tcx>( projection ) } else { - debug!( - "No associated capture found for {:?}[{:#?}]", - var_hir_id, projection, - ); + debug!("No associated capture found for {:?}[{:#?}]", var_hir_id, projection,); } return None; }; @@ -242,6 +236,9 @@ fn strip_prefix<'a, 'tcx>( } assert_matches!(iter.next(), Some(ProjectionElem::Field(..))); } + HirProjectionKind::OpaqueCast => { + assert_matches!(iter.next(), Some(ProjectionElem::OpaqueCast(..))); + } HirProjectionKind::Index | HirProjectionKind::Subslice => { bug!("unexpected projection kind: {:?}", projection); } @@ -736,5 +733,5 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// Precise capture is enabled if user is using Rust Edition 2021 or higher. fn enable_precise_capture(closure_span: Span) -> bool { - closure_span.rust_2021() + closure_span.at_least_rust_2021() } diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs index 32ffb990b..3220a184d 100644 --- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs @@ -16,7 +16,7 @@ use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::cast::{mir_cast_kind, CastTy}; use rustc_middle::ty::layout::IntegerExt; -use rustc_middle::ty::{self, Ty, UpvarSubsts}; +use rustc_middle::ty::{self, Ty, UpvarArgs}; use rustc_span::Span; impl<'a, 'tcx> Builder<'a, 'tcx> { @@ -382,7 +382,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } ExprKind::Closure(box ClosureExpr { closure_id, - substs, + args, ref upvars, movability, ref fake_reads, @@ -470,19 +470,15 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }) .collect(); - let result = match substs { - UpvarSubsts::Generator(substs) => { + let result = match args { + UpvarArgs::Generator(args) => { // We implicitly set the discriminant to 0. See // librustc_mir/transform/deaggregator.rs for details. let movability = movability.unwrap(); - Box::new(AggregateKind::Generator( - closure_id.to_def_id(), - substs, - movability, - )) + Box::new(AggregateKind::Generator(closure_id.to_def_id(), args, movability)) } - UpvarSubsts::Closure(substs) => { - Box::new(AggregateKind::Closure(closure_id.to_def_id(), substs)) + UpvarArgs::Closure(args) => { + Box::new(AggregateKind::Closure(closure_id.to_def_id(), args)) } }; block.and(Rvalue::Aggregate(result, operands)) @@ -778,8 +774,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // Not in a closure debug_assert!( local == ty::CAPTURE_STRUCT_LOCAL, - "Expected local to be Local(1), found {:?}", - local + "Expected local to be Local(1), found {local:?}" ); // Not in a closure debug_assert!( diff --git a/compiler/rustc_mir_build/src/build/expr/into.rs b/compiler/rustc_mir_build/src/build/expr/into.rs index e30fdcbbe..a5c86e31a 100644 --- a/compiler/rustc_mir_build/src/build/expr/into.rs +++ b/compiler/rustc_mir_build/src/build/expr/into.rs @@ -47,7 +47,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Block { block: ast_block } => { this.ast_block(destination, block, ast_block, source_info) } - ExprKind::Match { scrutinee, ref arms } => { + ExprKind::Match { scrutinee, ref arms, .. } => { this.match_expr(destination, expr_span, block, &this.thir[scrutinee], arms) } ExprKind::If { cond, then, else_opt, if_then_scope } => { @@ -317,7 +317,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ExprKind::Adt(box AdtExpr { adt_def, variant_index, - substs, + args, ref user_ty, ref fields, ref base, @@ -382,7 +382,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let adt = Box::new(AggregateKind::Adt( adt_def.did(), variant_index, - substs, + args, user_ty, active_field_index, )); diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs index 10770213c..3c4507407 100644 --- a/compiler/rustc_mir_build/src/build/matches/mod.rs +++ b/compiler/rustc_mir_build/src/build/matches/mod.rs @@ -607,9 +607,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // }; // ``` if let Some(place) = initializer.try_to_place(self) { - let LocalInfo::User(BindingForm::Var( - VarBindingForm { opt_match_place: Some((ref mut match_place, _)), .. }, - )) = **self.local_decls[local].local_info.as_mut().assert_crate_local() else { + let LocalInfo::User(BindingForm::Var(VarBindingForm { + opt_match_place: Some((ref mut match_place, _)), + .. + })) = **self.local_decls[local].local_info.as_mut().assert_crate_local() + else { bug!("Let binding to non-user variable.") }; *match_place = Some(place); @@ -804,7 +806,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - PatKind::Variant { adt_def, substs: _, variant_index, ref subpatterns } => { + PatKind::Variant { adt_def, args: _, variant_index, ref subpatterns } => { for subpattern in subpatterns { let subpattern_user_ty = pattern_user_ty.clone().variant(adt_def, variant_index, subpattern.field); @@ -1625,9 +1627,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // at least the first candidate ought to be tested assert!( total_candidate_count > candidates.len(), - "{}, {:#?}", - total_candidate_count, - candidates + "{total_candidate_count}, {candidates:#?}" ); debug!("tested_candidates: {}", total_candidate_count - candidates.len()); debug!("untested_candidates: {}", candidates.len()); @@ -2242,7 +2242,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.var_debug_info.push(VarDebugInfo { name, source_info: debug_source_info, - references: 0, value: VarDebugInfoContents::Place(for_arm_body.into()), argument_index: None, }); @@ -2262,7 +2261,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.var_debug_info.push(VarDebugInfo { name, source_info: debug_source_info, - references: 0, value: VarDebugInfoContents::Place(ref_for_guard.into()), argument_index: None, }); diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs index f6b1955fd..17ac1f4e0 100644 --- a/compiler/rustc_mir_build/src/build/matches/simplify.rs +++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs @@ -259,13 +259,13 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } - PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { + PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => { let irrefutable = adt_def.variants().iter_enumerated().all(|(i, v)| { i == variant_index || { self.tcx.features().exhaustive_patterns && !v .inhabited_predicate(self.tcx, adt_def) - .subst(self.tcx, substs) + .instantiate(self.tcx, args) .apply_ignore_module(self.tcx, self.param_env) } }) && (adt_def.did().is_local() diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs index e6806177d..484e84909 100644 --- a/compiler/rustc_mir_build/src/build/matches/test.rs +++ b/compiler/rustc_mir_build/src/build/matches/test.rs @@ -30,7 +30,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { /// It is a bug to call this with a not-fully-simplified pattern. pub(super) fn test<'pat>(&mut self, match_pair: &MatchPair<'pat, 'tcx>) -> Test<'tcx> { match match_pair.pattern.kind { - PatKind::Variant { adt_def, substs: _, variant_index: _, subpatterns: _ } => Test { + PatKind::Variant { adt_def, args: _, variant_index: _, subpatterns: _ } => Test { span: match_pair.pattern.span, kind: TestKind::Switch { adt_def, @@ -88,7 +88,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { switch_ty: Ty<'tcx>, options: &mut FxIndexMap<ConstantKind<'tcx>, u128>, ) -> bool { - let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) else { + let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) + else { return false; }; @@ -126,7 +127,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { candidate: &Candidate<'pat, 'tcx>, variants: &mut BitSet<VariantIdx>, ) -> bool { - let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) else { + let Some(match_pair) = candidate.match_pairs.iter().find(|mp| mp.place == *test_place) + else { return false; }; @@ -173,16 +175,14 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { debug_assert_ne!( target_blocks[idx.index()], otherwise_block, - "no candidates for tested discriminant: {:?}", - discr, + "no candidates for tested discriminant: {discr:?}", ); Some((discr.val, target_blocks[idx.index()])) } else { debug_assert_eq!( target_blocks[idx.index()], otherwise_block, - "found candidates for untested discriminant: {:?}", - discr, + "found candidates for untested discriminant: {discr:?}", ); None } @@ -865,7 +865,7 @@ fn trait_method<'tcx>( tcx: TyCtxt<'tcx>, trait_def_id: DefId, method_name: Symbol, - substs: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, + args: impl IntoIterator<Item: Into<GenericArg<'tcx>>>, ) -> ConstantKind<'tcx> { // The unhygienic comparison here is acceptable because this is only // used on known traits. @@ -875,7 +875,7 @@ fn trait_method<'tcx>( .find(|item| item.kind == ty::AssocKind::Fn) .expect("trait method not found"); - let method_ty = Ty::new_fn_def(tcx, item.def_id, substs); + let method_ty = Ty::new_fn_def(tcx, item.def_id, args); ConstantKind::zero_sized(method_ty) } diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs index d828e71c7..2a23a69b5 100644 --- a/compiler/rustc_mir_build/src/build/mod.rs +++ b/compiler/rustc_mir_build/src/build/mod.rs @@ -10,6 +10,7 @@ use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{GeneratorKind, Node}; +use rustc_index::bit_set::GrowableBitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; use rustc_middle::hir::place::PlaceBase as HirPlaceBase; @@ -93,8 +94,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: LocalDefId) -> Body<'_> { || body.basic_blocks.has_free_regions() || body.var_debug_info.has_free_regions() || body.yield_ty().has_free_regions()), - "Unexpected free regions in MIR: {:?}", - body, + "Unexpected free regions in MIR: {body:?}", ); body @@ -215,6 +215,14 @@ struct Builder<'a, 'tcx> { unit_temp: Option<Place<'tcx>>, var_debug_info: Vec<VarDebugInfo<'tcx>>, + + // A cache for `maybe_lint_level_roots_bounded`. That function is called + // repeatedly, and each time it effectively traces a path through a tree + // structure from a node towards the root, doing an attribute check on each + // node along the way. This cache records which nodes trace all the way to + // the root (most of them do) and saves us from retracing many sub-paths + // many times, and rechecking many nodes. + lint_level_roots_cache: GrowableBitSet<hir::ItemLocalId>, } type CaptureMap<'tcx> = SortedIndexMultiMap<usize, hir::HirId, Capture<'tcx>>; @@ -473,7 +481,7 @@ fn construct_fn<'tcx>( let (yield_ty, return_ty) = if generator_kind.is_some() { let gen_ty = arguments[thir::UPVAR_ENV_PARAM].ty; let gen_sig = match gen_ty.kind() { - ty::Generator(_, gen_substs, ..) => gen_substs.as_generator().sig(), + ty::Generator(_, gen_args, ..) => gen_args.as_generator().sig(), _ => { span_bug!(span, "generator w/o generator type: {:?}", gen_ty) } @@ -562,7 +570,7 @@ fn construct_const<'a, 'tcx>( // Figure out what primary body this item has. let (span, const_ty_span) = match tcx.hir().get(hir_id) { Node::Item(hir::Item { - kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _), + kind: hir::ItemKind::Static(ty, _, _) | hir::ItemKind::Const(ty, _, _), span, .. }) @@ -618,11 +626,9 @@ fn construct_error(tcx: TyCtxt<'_>, def: LocalDefId, err: ErrorGuaranteed) -> Bo let num_params = match body_owner_kind { hir::BodyOwnerKind::Fn => tcx.fn_sig(def).skip_binder().inputs().skip_binder().len(), hir::BodyOwnerKind::Closure => { - let ty = tcx.type_of(def).subst_identity(); + let ty = tcx.type_of(def).instantiate_identity(); match ty.kind() { - ty::Closure(_, substs) => { - 1 + substs.as_closure().sig().inputs().skip_binder().len() - } + ty::Closure(_, args) => 1 + args.as_closure().sig().inputs().skip_binder().len(), ty::Generator(..) => 2, _ => bug!("expected closure or generator, found {ty:?}"), } @@ -725,6 +731,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { var_indices: Default::default(), unit_temp: None, var_debug_info: vec![], + lint_level_roots_cache: GrowableBitSet::new_empty(), }; assert_eq!(builder.cfg.start_new_block(), START_BLOCK); @@ -768,9 +775,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { closure_ty = *ty; } - let upvar_substs = match closure_ty.kind() { - ty::Closure(_, substs) => ty::UpvarSubsts::Closure(substs), - ty::Generator(_, substs, _) => ty::UpvarSubsts::Generator(substs), + let upvar_args = match closure_ty.kind() { + ty::Closure(_, args) => ty::UpvarArgs::Closure(args), + ty::Generator(_, args, _) => ty::UpvarArgs::Generator(args), _ => return, }; @@ -779,7 +786,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { // with the closure's DefId. Here, we run through that vec of UpvarIds for // the given closure and use the necessary information to create upvar // debuginfo and to fill `self.upvars`. - let capture_tys = upvar_substs.upvar_tys(); + let capture_tys = upvar_args.upvar_tys(); let tcx = self.tcx; self.upvars = tcx @@ -813,7 +820,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { }; self.var_debug_info.push(VarDebugInfo { name, - references: 0, source_info: SourceInfo::outermost(captured_place.var_ident.span), value: VarDebugInfoContents::Place(use_place), argument_index: None, @@ -844,7 +850,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { self.var_debug_info.push(VarDebugInfo { name, source_info, - references: 0, value: VarDebugInfoContents::Place(arg_local.into()), argument_index: Some(argument_index as u16 + 1), }); @@ -969,9 +974,9 @@ pub(crate) fn parse_float_into_scalar( match float_ty { ty::FloatTy::F32 => { let Ok(rust_f) = num.parse::<f32>() else { return None }; - let mut f = num.parse::<Single>().unwrap_or_else(|e| { - panic!("apfloat::ieee::Single failed to parse `{}`: {:?}", num, e) - }); + let mut f = num + .parse::<Single>() + .unwrap_or_else(|e| panic!("apfloat::ieee::Single failed to parse `{num}`: {e:?}")); assert!( u128::from(rust_f.to_bits()) == f.to_bits(), @@ -992,9 +997,9 @@ pub(crate) fn parse_float_into_scalar( } ty::FloatTy::F64 => { let Ok(rust_f) = num.parse::<f64>() else { return None }; - let mut f = num.parse::<Double>().unwrap_or_else(|e| { - panic!("apfloat::ieee::Double failed to parse `{}`: {:?}", num, e) - }); + let mut f = num + .parse::<Double>() + .unwrap_or_else(|e| panic!("apfloat::ieee::Double failed to parse `{num}`: {e:?}")); assert!( u128::from(rust_f.to_bits()) == f.to_bits(), diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs index 72374102c..a96288a11 100644 --- a/compiler/rustc_mir_build/src/build/scope.rs +++ b/compiler/rustc_mir_build/src/build/scope.rs @@ -90,8 +90,8 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::middle::region; use rustc_middle::mir::*; use rustc_middle::thir::{Expr, LintLevel}; - use rustc_middle::ty::Ty; +use rustc_session::lint::Level; use rustc_span::{Span, DUMMY_SP}; #[derive(Debug)] @@ -760,20 +760,25 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { ) { let (current_root, parent_root) = if self.tcx.sess.opts.unstable_opts.maximal_hir_to_mir_coverage { - // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently the - // the only part of rustc that tracks MIR -> HIR is the `SourceScopeLocalData::lint_root` - // field that tracks lint levels for MIR locations. Normally the number of source scopes - // is limited to the set of nodes with lint annotations. The -Zmaximal-hir-to-mir-coverage - // flag changes this behavior to maximize the number of source scopes, increasing the - // granularity of the MIR->HIR mapping. + // Some consumers of rustc need to map MIR locations back to HIR nodes. Currently + // the the only part of rustc that tracks MIR -> HIR is the + // `SourceScopeLocalData::lint_root` field that tracks lint levels for MIR + // locations. Normally the number of source scopes is limited to the set of nodes + // with lint annotations. The -Zmaximal-hir-to-mir-coverage flag changes this + // behavior to maximize the number of source scopes, increasing the granularity of + // the MIR->HIR mapping. (current_id, parent_id) } else { - // Use `maybe_lint_level_root_bounded` with `self.hir_id` as a bound - // to avoid adding Hir dependencies on our parents. - // We estimate the true lint roots here to avoid creating a lot of source scopes. + // Use `maybe_lint_level_root_bounded` to avoid adding Hir dependencies on our + // parents. We estimate the true lint roots here to avoid creating a lot of source + // scopes. ( - self.tcx.maybe_lint_level_root_bounded(current_id, self.hir_id), - self.tcx.maybe_lint_level_root_bounded(parent_id, self.hir_id), + self.maybe_lint_level_root_bounded(current_id), + if parent_id == self.hir_id { + parent_id // this is very common + } else { + self.maybe_lint_level_root_bounded(parent_id) + }, ) }; @@ -783,6 +788,50 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { } } + /// Walks upwards from `orig_id` to find a node which might change lint levels with attributes. + /// It stops at `self.hir_id` and just returns it if reached. + fn maybe_lint_level_root_bounded(&mut self, orig_id: HirId) -> HirId { + // This assertion lets us just store `ItemLocalId` in the cache, rather + // than the full `HirId`. + assert_eq!(orig_id.owner, self.hir_id.owner); + + let mut id = orig_id; + let hir = self.tcx.hir(); + loop { + if id == self.hir_id { + // This is a moderately common case, mostly hit for previously unseen nodes. + break; + } + + if hir.attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) { + // This is a rare case. It's for a node path that doesn't reach the root due to an + // intervening lint level attribute. This result doesn't get cached. + return id; + } + + let next = hir.parent_id(id); + if next == id { + bug!("lint traversal reached the root of the crate"); + } + id = next; + + // This lookup is just an optimization; it can be removed without affecting + // functionality. It might seem strange to see this at the end of this loop, but the + // `orig_id` passed in to this function is almost always previously unseen, for which a + // lookup will be a miss. So we only do lookups for nodes up the parent chain, where + // cache lookups have a very high hit rate. + if self.lint_level_roots_cache.contains(id.local_id) { + break; + } + } + + // `orig_id` traced to `self_id`; record this fact. If `orig_id` is a leaf node it will + // rarely (never?) subsequently be searched for, but it's hard to know if that is the case. + // The performance wins from the cache all come from caching non-leaf nodes. + self.lint_level_roots_cache.insert(orig_id.local_id); + self.hir_id + } + /// Creates a new source scope, nested in the current one. pub(crate) fn new_source_scope( &mut self, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index 6b2b140fa..192bd4a83 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -91,7 +91,12 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> { kind.emit_unsafe_op_in_unsafe_fn_lint(self.tcx, self.hir_context, span); } SafetyContext::Safe => { - kind.emit_requires_unsafe_err(self.tcx, span, unsafe_op_in_unsafe_fn_allowed); + kind.emit_requires_unsafe_err( + self.tcx, + span, + self.hir_context, + unsafe_op_in_unsafe_fn_allowed, + ); } } } @@ -383,7 +388,7 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { ExprKind::Adt(box AdtExpr { adt_def, variant_index: _, - substs: _, + args: _, user_ty: _, fields: _, base: _, @@ -393,14 +398,14 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> { }, ExprKind::Closure(box ClosureExpr { closure_id, - substs: _, + args: _, upvars: _, movability: _, fake_reads: _, }) => { self.visit_inner_body(closure_id); } - ExprKind::ConstBlock { did, substs: _ } => { + ExprKind::ConstBlock { did, args: _ } => { let def_id = did.expect_local(); self.visit_inner_body(def_id); } @@ -602,98 +607,164 @@ impl UnsafeOpKind { &self, tcx: TyCtxt<'_>, span: Span, + hir_context: hir::HirId, unsafe_op_in_unsafe_fn_allowed: bool, ) { + let note_non_inherited = tcx.hir().parent_iter(hir_context).find(|(id, node)| { + if let hir::Node::Expr(block) = node + && let hir::ExprKind::Block(block, _) = block.kind + && let hir::BlockCheckMode::UnsafeBlock(_) = block.rules + { + true + } + else if let Some(sig) = tcx.hir().fn_sig_by_hir_id(*id) + && sig.header.is_unsafe() + { + true + } else { + false + } + }); + let unsafe_not_inherited_note = if let Some((id, _)) = note_non_inherited { + let span = tcx.hir().span(id); + let span = tcx.sess.source_map().guess_head_span(span); + Some(UnsafeNotInheritedNote { span }) + } else { + None + }; + match self { CallToUnsafeFunction(Some(did)) if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, + unsafe_not_inherited_note, function: &tcx.def_path_str(*did), }); } CallToUnsafeFunction(Some(did)) => { tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafe { span, + unsafe_not_inherited_note, function: &tcx.def_path_str(*did), }); } CallToUnsafeFunction(None) if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err( - CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { span }, + CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }, ); } CallToUnsafeFunction(None) => { - tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { span }); + tcx.sess.emit_err(CallToUnsafeFunctionRequiresUnsafeNameless { + span, + unsafe_not_inherited_note, + }); } UseOfInlineAssembly if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } UseOfInlineAssembly => { - tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { span }); + tcx.sess.emit_err(UseOfInlineAssemblyRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); } InitializingTypeWith if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } InitializingTypeWith => { - tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { span }); + tcx.sess.emit_err(InitializingTypeWithRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); } UseOfMutableStatic if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } UseOfMutableStatic => { - tcx.sess.emit_err(UseOfMutableStaticRequiresUnsafe { span }); + tcx.sess + .emit_err(UseOfMutableStaticRequiresUnsafe { span, unsafe_not_inherited_note }); } UseOfExternStatic if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } UseOfExternStatic => { - tcx.sess.emit_err(UseOfExternStaticRequiresUnsafe { span }); + tcx.sess + .emit_err(UseOfExternStaticRequiresUnsafe { span, unsafe_not_inherited_note }); } DerefOfRawPointer if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } DerefOfRawPointer => { - tcx.sess.emit_err(DerefOfRawPointerRequiresUnsafe { span }); + tcx.sess + .emit_err(DerefOfRawPointerRequiresUnsafe { span, unsafe_not_inherited_note }); } AccessToUnionField if unsafe_op_in_unsafe_fn_allowed => { - tcx.sess - .emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }); + tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }); } AccessToUnionField => { - tcx.sess.emit_err(AccessToUnionFieldRequiresUnsafe { span }); + tcx.sess + .emit_err(AccessToUnionFieldRequiresUnsafe { span, unsafe_not_inherited_note }); } MutationOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err( MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, + unsafe_not_inherited_note, }, ); } MutationOfLayoutConstrainedField => { - tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { span }); + tcx.sess.emit_err(MutationOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); } BorrowOfLayoutConstrainedField if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err( - BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span }, + BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { + span, + unsafe_not_inherited_note, + }, ); } BorrowOfLayoutConstrainedField => { - tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { span }); + tcx.sess.emit_err(BorrowOfLayoutConstrainedFieldRequiresUnsafe { + span, + unsafe_not_inherited_note, + }); } CallToFunctionWith(did) if unsafe_op_in_unsafe_fn_allowed => { tcx.sess.emit_err(CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { span, + unsafe_not_inherited_note, function: &tcx.def_path_str(*did), }); } CallToFunctionWith(did) => { tcx.sess.emit_err(CallToFunctionWithRequiresUnsafe { span, + unsafe_not_inherited_note, function: &tcx.def_path_str(*did), }); } @@ -712,9 +783,7 @@ pub fn thir_check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { return; } - let Ok((thir, expr)) = tcx.thir_body(def) else { - return - }; + let Ok((thir, expr)) = tcx.thir_body(def) else { return }; let thir = &thir.borrow(); // If `thir` is empty, a type error occurred, skip this body. if thir.exprs.is_empty() { diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs index df00cc75c..3ff3387a7 100644 --- a/compiler/rustc_mir_build/src/errors.rs +++ b/compiler/rustc_mir_build/src/errors.rs @@ -119,6 +119,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -128,6 +130,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNameless { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -138,6 +142,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -150,6 +156,8 @@ pub struct CallToUnsafeFunctionRequiresUnsafeNamelessUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -159,6 +167,8 @@ pub struct UseOfInlineAssemblyRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -168,6 +178,8 @@ pub struct UseOfInlineAssemblyRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -177,6 +189,8 @@ pub struct InitializingTypeWithRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -189,6 +203,8 @@ pub struct InitializingTypeWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -198,6 +214,8 @@ pub struct UseOfMutableStaticRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -207,6 +225,8 @@ pub struct UseOfMutableStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -216,6 +236,8 @@ pub struct UseOfExternStaticRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -225,6 +247,8 @@ pub struct UseOfExternStaticRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -234,6 +258,8 @@ pub struct DerefOfRawPointerRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -243,6 +269,8 @@ pub struct DerefOfRawPointerRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -252,6 +280,8 @@ pub struct AccessToUnionFieldRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -261,6 +291,8 @@ pub struct AccessToUnionFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -270,6 +302,8 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -282,6 +316,8 @@ pub struct MutationOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllow #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -291,6 +327,8 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafe { #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -303,6 +341,8 @@ pub struct BorrowOfLayoutConstrainedFieldRequiresUnsafeUnsafeOpInUnsafeFnAllowed #[primary_span] #[label] pub span: Span, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -313,6 +353,8 @@ pub struct CallToFunctionWithRequiresUnsafe<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, } #[derive(Diagnostic)] @@ -323,6 +365,15 @@ pub struct CallToFunctionWithRequiresUnsafeUnsafeOpInUnsafeFnAllowed<'a> { #[label] pub span: Span, pub function: &'a str, + #[subdiagnostic] + pub unsafe_not_inherited_note: Option<UnsafeNotInheritedNote>, +} + +#[derive(Subdiagnostic)] +#[label(mir_build_unsafe_not_inherited)] +pub struct UnsafeNotInheritedNote { + #[primary_span] + pub span: Span, } #[derive(LintDiagnostic)] @@ -403,17 +454,13 @@ impl<'a> IntoDiagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_, '_> { if self.span.eq_ctxt(self.expr_span) { // Get the span for the empty match body `{}`. let (indentation, more) = if let Some(snippet) = sm.indentation_before(self.span) { - (format!("\n{}", snippet), " ") + (format!("\n{snippet}"), " ") } else { (" ".to_string(), "") }; suggestion = Some(( self.span.shrink_to_hi().with_hi(self.expr_span.hi()), - format!( - " {{{indentation}{more}_ => todo!(),{indentation}}}", - indentation = indentation, - more = more, - ), + format!(" {{{indentation}{more}_ => todo!(),{indentation}}}",), )); } diff --git a/compiler/rustc_mir_build/src/lib.rs b/compiler/rustc_mir_build/src/lib.rs index 4fdc3178c..099fefbf0 100644 --- a/compiler/rustc_mir_build/src/lib.rs +++ b/compiler/rustc_mir_build/src/lib.rs @@ -19,7 +19,7 @@ extern crate rustc_middle; mod build; mod check_unsafety; mod errors; -mod lints; +pub mod lints; pub mod thir; use rustc_middle::query::Providers; diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs index 8e41957af..7fb73b5c7 100644 --- a/compiler/rustc_mir_build/src/lints.rs +++ b/compiler/rustc_mir_build/src/lints.rs @@ -3,27 +3,43 @@ use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; use rustc_hir::def::DefKind; -use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Operand, TerminatorKind}; -use rustc_middle::ty::subst::{GenericArg, InternalSubsts}; -use rustc_middle::ty::{self, Instance, TyCtxt}; +use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Terminator, TerminatorKind}; +use rustc_middle::ty::{self, Instance, Ty, TyCtxt}; +use rustc_middle::ty::{GenericArg, GenericArgs}; use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION; use rustc_span::Span; use std::ops::ControlFlow; pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + check_call_recursion(tcx, body); +} + +fn check_call_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { let def_id = body.source.def_id().expect_local(); if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) { - // If this is trait/impl method, extract the trait's substs. - let trait_substs = match tcx.trait_of_item(def_id.to_def_id()) { + // If this is trait/impl method, extract the trait's args. + let trait_args = match tcx.trait_of_item(def_id.to_def_id()) { Some(trait_def_id) => { - let trait_substs_count = tcx.generics_of(trait_def_id).count(); - &InternalSubsts::identity_for_item(tcx, def_id)[..trait_substs_count] + let trait_args_count = tcx.generics_of(trait_def_id).count(); + &GenericArgs::identity_for_item(tcx, def_id)[..trait_args_count] } _ => &[], }; - let mut vis = Search { tcx, body, reachable_recursive_calls: vec![], trait_substs }; + check_recursion(tcx, body, CallRecursion { trait_args }) + } +} + +fn check_recursion<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + classifier: impl TerminatorClassifier<'tcx>, +) { + let def_id = body.source.def_id().expect_local(); + + if let DefKind::Fn | DefKind::AssocFn = tcx.def_kind(def_id) { + let mut vis = Search { tcx, body, classifier, reachable_recursive_calls: vec![] }; if let Some(NonRecursive) = TriColorDepthFirstSearch::new(&body.basic_blocks).run_from_start(&mut vis) { @@ -46,20 +62,66 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { } } +/// Requires drop elaboration to have been performed first. +pub fn check_drop_recursion<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) { + let def_id = body.source.def_id().expect_local(); + + // First check if `body` is an `fn drop()` of `Drop` + if let DefKind::AssocFn = tcx.def_kind(def_id) && + let Some(trait_ref) = tcx.impl_of_method(def_id.to_def_id()).and_then(|def_id| tcx.impl_trait_ref(def_id)) && + let Some(drop_trait) = tcx.lang_items().drop_trait() && drop_trait == trait_ref.instantiate_identity().def_id { + + // It was. Now figure out for what type `Drop` is implemented and then + // check for recursion. + if let ty::Ref(_, dropped_ty, _) = tcx.liberate_late_bound_regions( + def_id.to_def_id(), + tcx.fn_sig(def_id).instantiate_identity().input(0), + ).kind() { + check_recursion(tcx, body, RecursiveDrop { drop_for: *dropped_ty }); + } + } +} + +trait TerminatorClassifier<'tcx> { + fn is_recursive_terminator( + &self, + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + terminator: &Terminator<'tcx>, + ) -> bool; +} + struct NonRecursive; -struct Search<'mir, 'tcx> { +struct Search<'mir, 'tcx, C: TerminatorClassifier<'tcx>> { tcx: TyCtxt<'tcx>, body: &'mir Body<'tcx>, - trait_substs: &'tcx [GenericArg<'tcx>], + classifier: C, reachable_recursive_calls: Vec<Span>, } -impl<'mir, 'tcx> Search<'mir, 'tcx> { +struct CallRecursion<'tcx> { + trait_args: &'tcx [GenericArg<'tcx>], +} + +struct RecursiveDrop<'tcx> { + /// The type that `Drop` is implemented for. + drop_for: Ty<'tcx>, +} + +impl<'tcx> TerminatorClassifier<'tcx> for CallRecursion<'tcx> { /// Returns `true` if `func` refers to the function we are searching in. - fn is_recursive_call(&self, func: &Operand<'tcx>, args: &[Operand<'tcx>]) -> bool { - let Search { tcx, body, trait_substs, .. } = *self; + fn is_recursive_terminator( + &self, + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + terminator: &Terminator<'tcx>, + ) -> bool { + let TerminatorKind::Call { func, args, .. } = &terminator.kind else { + return false; + }; + // Resolving function type to a specific instance that is being called is expensive. To // avoid the cost we check the number of arguments first, which is sufficient to reject // most of calls as non-recursive. @@ -70,30 +132,46 @@ impl<'mir, 'tcx> Search<'mir, 'tcx> { let param_env = tcx.param_env(caller); let func_ty = func.ty(body, tcx); - if let ty::FnDef(callee, substs) = *func_ty.kind() { - let normalized_substs = tcx.normalize_erasing_regions(param_env, substs); - let (callee, call_substs) = if let Ok(Some(instance)) = - Instance::resolve(tcx, param_env, callee, normalized_substs) + if let ty::FnDef(callee, args) = *func_ty.kind() { + let normalized_args = tcx.normalize_erasing_regions(param_env, args); + let (callee, call_args) = if let Ok(Some(instance)) = + Instance::resolve(tcx, param_env, callee, normalized_args) { - (instance.def_id(), instance.substs) + (instance.def_id(), instance.args) } else { - (callee, normalized_substs) + (callee, normalized_args) }; // FIXME(#57965): Make this work across function boundaries - // If this is a trait fn, the substs on the trait have to match, or we might be + // If this is a trait fn, the args on the trait have to match, or we might be // calling into an entirely different method (for example, a call from the default // method in the trait to `<A as Trait<B>>::method`, where `A` and/or `B` are // specific types). - return callee == caller && &call_substs[..trait_substs.len()] == trait_substs; + return callee == caller && &call_args[..self.trait_args.len()] == self.trait_args; } false } } -impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> { +impl<'tcx> TerminatorClassifier<'tcx> for RecursiveDrop<'tcx> { + fn is_recursive_terminator( + &self, + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, + terminator: &Terminator<'tcx>, + ) -> bool { + let TerminatorKind::Drop { place, .. } = &terminator.kind else { return false }; + + let dropped_ty = place.ty(body, tcx).ty; + dropped_ty == self.drop_for + } +} + +impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx>> + for Search<'mir, 'tcx, C> +{ type BreakVal = NonRecursive; fn node_examined( @@ -138,10 +216,8 @@ impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> { fn node_settled(&mut self, bb: BasicBlock) -> ControlFlow<Self::BreakVal> { // When we examine a node for the last time, remember it if it is a recursive call. let terminator = self.body[bb].terminator(); - if let TerminatorKind::Call { func, args, .. } = &terminator.kind { - if self.is_recursive_call(func, args) { - self.reachable_recursive_calls.push(terminator.source_info.span); - } + if self.classifier.is_recursive_terminator(self.tcx, self.body, terminator) { + self.reachable_recursive_calls.push(terminator.source_info.span); } ControlFlow::Continue(()) @@ -149,15 +225,14 @@ impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> { fn ignore_edge(&mut self, bb: BasicBlock, target: BasicBlock) -> bool { let terminator = self.body[bb].terminator(); - if terminator.unwind() == Some(&mir::UnwindAction::Cleanup(target)) - && terminator.successors().count() > 1 + let ignore_unwind = terminator.unwind() == Some(&mir::UnwindAction::Cleanup(target)) + && terminator.successors().count() > 1; + if ignore_unwind || self.classifier.is_recursive_terminator(self.tcx, self.body, terminator) { return true; } - // Don't traverse successors of recursive calls or false CFG edges. - match self.body[bb].terminator().kind { - TerminatorKind::Call { ref func, ref args, .. } => self.is_recursive_call(func, args), - TerminatorKind::FalseEdge { imaginary_target, .. } => imaginary_target == target, + match &terminator.kind { + TerminatorKind::FalseEdge { imaginary_target, .. } => imaginary_target == &target, _ => false, } } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 37537683f..6c1f7d7a6 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -15,9 +15,9 @@ use rustc_middle::thir::*; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, AutoBorrowMutability, PointerCoercion, }; -use rustc_middle::ty::subst::InternalSubsts; +use rustc_middle::ty::GenericArgs; use rustc_middle::ty::{ - self, AdtKind, InlineConstSubsts, InlineConstSubstsParts, ScalarInt, Ty, UpvarSubsts, UserType, + self, AdtKind, InlineConstArgs, InlineConstArgsParts, ScalarInt, Ty, UpvarArgs, UserType, }; use rustc_span::{sym, Span}; use rustc_target::abi::{FieldIdx, FIRST_VARIANT}; @@ -41,11 +41,6 @@ impl<'tcx> Cx<'tcx> { let mut expr = self.make_mirror_unadjusted(hir_expr); - let adjustment_span = match self.adjustment_span { - Some((hir_id, span)) if hir_id == hir_expr.hir_id => Some(span), - _ => None, - }; - trace!(?expr.ty); // Now apply adjustments, if any. @@ -53,12 +48,7 @@ impl<'tcx> Cx<'tcx> { for adjustment in self.typeck_results.expr_adjustments(hir_expr) { trace!(?expr, ?adjustment); let span = expr.span; - expr = self.apply_adjustment( - hir_expr, - expr, - adjustment, - adjustment_span.unwrap_or(span), - ); + expr = self.apply_adjustment(hir_expr, expr, adjustment, span); } } @@ -220,7 +210,7 @@ impl<'tcx> Cx<'tcx> { let res = self.typeck_results().qpath_res(qpath, source.hir_id); let ty = self.typeck_results().node_type(source.hir_id); - let ty::Adt(adt_def, substs) = ty.kind() else { + let ty::Adt(adt_def, args) = ty.kind() else { return ExprKind::Cast { source: self.mirror_expr(source) }; }; @@ -239,9 +229,7 @@ impl<'tcx> Cx<'tcx> { let param_env_ty = self.param_env.and(discr_ty); let size = tcx .layout_of(param_env_ty) - .unwrap_or_else(|e| { - panic!("could not compute layout for {:?}: {:?}", param_env_ty, e) - }) + .unwrap_or_else(|e| panic!("could not compute layout for {param_env_ty:?}: {e:?}")) .size; let lit = ScalarInt::try_from_uint(discr_offset as u128, size).unwrap(); @@ -252,7 +240,7 @@ impl<'tcx> Cx<'tcx> { // in case we are offsetting from a computed discriminant // and not the beginning of discriminants (which is always `0`) Some(did) => { - let kind = ExprKind::NamedConst { def_id: did, substs, user_ty: None }; + let kind = ExprKind::NamedConst { def_id: did, args, user_ty: None }; let lhs = self.thir.exprs.push(Expr { temp_lifetime, ty: discr_ty, span, kind }); let bin = ExprKind::Binary { op: BinOp::Add, lhs, rhs: offset }; @@ -274,7 +262,6 @@ impl<'tcx> Cx<'tcx> { fn make_mirror_unadjusted(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Expr<'tcx> { let tcx = self.tcx; let expr_ty = self.typeck_results().expr_ty(expr); - let expr_span = expr.span; let temp_lifetime = self.rvalue_scopes.temporary_scope(self.region_scope_tree, expr.hir_id.local_id); @@ -283,17 +270,11 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::MethodCall(segment, receiver, ref args, fn_span) => { // Rewrite a.b(c) into UFCS form like Trait::b(a, c) let expr = self.method_callee(expr, segment.ident.span, None); - // When we apply adjustments to the receiver, use the span of - // the overall method call for better diagnostics. args[0] - // is guaranteed to exist, since a method call always has a receiver. - let old_adjustment_span = - self.adjustment_span.replace((receiver.hir_id, expr_span)); info!("Using method span: {:?}", expr.span); let args = std::iter::once(receiver) .chain(args.iter()) .map(|expr| self.mirror_expr(expr)) .collect(); - self.adjustment_span = old_adjustment_span; ExprKind::Call { ty: expr.ty, fun: self.thir.exprs.push(expr), @@ -389,7 +370,7 @@ impl<'tcx> Cx<'tcx> { None }; if let Some((adt_def, index)) = adt_data { - let substs = self.typeck_results().node_substs(fun.hir_id); + let node_args = self.typeck_results().node_args(fun.hir_id); let user_provided_types = self.typeck_results().user_provided_types(); let user_ty = user_provided_types.get(fun.hir_id).copied().map(|mut u_ty| { @@ -410,7 +391,7 @@ impl<'tcx> Cx<'tcx> { .collect(); ExprKind::Adt(Box::new(AdtExpr { adt_def, - substs, + args: node_args, variant_index: index, fields: field_refs, user_ty, @@ -464,7 +445,6 @@ impl<'tcx> Cx<'tcx> { let rhs = self.mirror_expr(rhs); self.overloaded_operator(expr, Box::new([lhs, rhs])) } else { - // FIXME overflow match op.node { hir::BinOpKind::And => ExprKind::LogicalOp { op: LogicalOp::And, @@ -488,11 +468,17 @@ impl<'tcx> Cx<'tcx> { } } - hir::ExprKind::Index(ref lhs, ref index) => { + hir::ExprKind::Index(ref lhs, ref index, brackets_span) => { if self.typeck_results().is_method_call(expr) { let lhs = self.mirror_expr(lhs); let index = self.mirror_expr(index); - self.overloaded_place(expr, expr_ty, None, Box::new([lhs, index]), expr.span) + self.overloaded_place( + expr, + expr_ty, + None, + Box::new([lhs, index]), + brackets_span, + ) } else { ExprKind::Index { lhs: self.mirror_expr(lhs), index: self.mirror_expr(index) } } @@ -528,7 +514,7 @@ impl<'tcx> Cx<'tcx> { } hir::ExprKind::Struct(ref qpath, ref fields, ref base) => match expr_ty.kind() { - ty::Adt(adt, substs) => match adt.adt_kind() { + ty::Adt(adt, args) => match adt.adt_kind() { AdtKind::Struct | AdtKind::Union => { let user_provided_types = self.typeck_results().user_provided_types(); let user_ty = user_provided_types.get(expr.hir_id).copied().map(Box::new); @@ -536,7 +522,7 @@ impl<'tcx> Cx<'tcx> { ExprKind::Adt(Box::new(AdtExpr { adt_def: *adt, variant_index: FIRST_VARIANT, - substs, + args, user_ty, fields: self.field_refs(fields), base: base.map(|base| FruInfo { @@ -563,7 +549,7 @@ impl<'tcx> Cx<'tcx> { ExprKind::Adt(Box::new(AdtExpr { adt_def: *adt, variant_index: index, - substs, + args, user_ty, fields: self.field_refs(fields), base: None, @@ -582,10 +568,10 @@ impl<'tcx> Cx<'tcx> { hir::ExprKind::Closure { .. } => { let closure_ty = self.typeck_results().expr_ty(expr); - let (def_id, substs, movability) = match *closure_ty.kind() { - ty::Closure(def_id, substs) => (def_id, UpvarSubsts::Closure(substs), None), - ty::Generator(def_id, substs, movability) => { - (def_id, UpvarSubsts::Generator(substs), Some(movability)) + let (def_id, args, movability) = match *closure_ty.kind() { + ty::Closure(def_id, args) => (def_id, UpvarArgs::Closure(args), None), + ty::Generator(def_id, args, movability) => { + (def_id, UpvarArgs::Generator(args), Some(movability)) } _ => { span_bug!(expr.span, "closure expr w/o closure type: {:?}", closure_ty); @@ -597,7 +583,7 @@ impl<'tcx> Cx<'tcx> { .tcx .closure_captures(def_id) .iter() - .zip(substs.upvar_tys()) + .zip(args.upvar_tys()) .map(|(captured_place, ty)| { let upvars = self.capture_upvar(expr, captured_place, ty); self.thir.exprs.push(upvars) @@ -618,7 +604,7 @@ impl<'tcx> Cx<'tcx> { ExprKind::Closure(Box::new(ClosureExpr { closure_id: def_id, - substs, + args, upvars, movability, fake_reads, @@ -701,13 +687,11 @@ impl<'tcx> Cx<'tcx> { let ty = self.typeck_results().node_type(anon_const.hir_id); let did = anon_const.def_id.to_def_id(); let typeck_root_def_id = tcx.typeck_root_def_id(did); - let parent_substs = - tcx.erase_regions(InternalSubsts::identity_for_item(tcx, typeck_root_def_id)); - let substs = - InlineConstSubsts::new(tcx, InlineConstSubstsParts { parent_substs, ty }) - .substs; + let parent_args = + tcx.erase_regions(GenericArgs::identity_for_item(tcx, typeck_root_def_id)); + let args = InlineConstArgs::new(tcx, InlineConstArgsParts { parent_args, ty }).args; - ExprKind::ConstBlock { did, substs } + ExprKind::ConstBlock { did, args } } // Now comes the rote stuff: hir::ExprKind::Repeat(ref v, _) => { @@ -748,6 +732,7 @@ impl<'tcx> Cx<'tcx> { }, hir::ExprKind::Match(ref discr, ref arms, _) => ExprKind::Match { scrutinee: self.mirror_expr(discr), + scrutinee_hir_id: discr.hir_id, arms: arms.iter().map(|a| self.convert_arm(a)).collect(), }, hir::ExprKind::Loop(ref body, ..) => { @@ -826,12 +811,12 @@ impl<'tcx> Cx<'tcx> { Expr { temp_lifetime, ty: expr_ty, span: expr.span, kind } } - fn user_substs_applied_to_res( + fn user_args_applied_to_res( &mut self, hir_id: hir::HirId, res: Res, ) -> Option<Box<ty::CanonicalUserType<'tcx>>> { - debug!("user_substs_applied_to_res: res={:?}", res); + debug!("user_args_applied_to_res: res={:?}", res); let user_provided_type = match res { // A reference to something callable -- e.g., a fn, method, or // a tuple-struct or tuple-variant. This has the type of a @@ -849,15 +834,15 @@ impl<'tcx> Cx<'tcx> { // this variant -- but with the substitutions given by the // user. Res::Def(DefKind::Ctor(_, CtorKind::Const), _) => { - self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new) + self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new) } // `Self` is used in expression as a tuple struct constructor or a unit struct constructor - Res::SelfCtor(_) => self.user_substs_applied_to_ty_of_hir_id(hir_id).map(Box::new), + Res::SelfCtor(_) => self.user_args_applied_to_ty_of_hir_id(hir_id).map(Box::new), - _ => bug!("user_substs_applied_to_res: unexpected res {:?} at {:?}", res, hir_id), + _ => bug!("user_args_applied_to_res: unexpected res {:?} at {:?}", res, hir_id), }; - debug!("user_substs_applied_to_res: user_provided_type={:?}", user_provided_type); + debug!("user_args_applied_to_res: user_provided_type={:?}", user_provided_type); user_provided_type } @@ -876,13 +861,13 @@ impl<'tcx> Cx<'tcx> { self.typeck_results().type_dependent_def(expr.hir_id).unwrap_or_else(|| { span_bug!(expr.span, "no type-dependent def for method callee") }); - let user_ty = self.user_substs_applied_to_res(expr.hir_id, Res::Def(kind, def_id)); + let user_ty = self.user_args_applied_to_res(expr.hir_id, Res::Def(kind, def_id)); debug!("method_callee: user_ty={:?}", user_ty); ( Ty::new_fn_def( self.tcx(), def_id, - self.typeck_results().node_substs(expr.hir_id), + self.typeck_results().node_args(expr.hir_id), ), user_ty, ) @@ -909,14 +894,14 @@ impl<'tcx> Cx<'tcx> { } fn convert_path_expr(&mut self, expr: &'tcx hir::Expr<'tcx>, res: Res) -> ExprKind<'tcx> { - let substs = self.typeck_results().node_substs(expr.hir_id); + let args = self.typeck_results().node_args(expr.hir_id); match res { // A regular function, constructor function or a constant. Res::Def(DefKind::Fn, _) | Res::Def(DefKind::AssocFn, _) | Res::Def(DefKind::Ctor(_, CtorKind::Fn), _) | Res::SelfCtor(_) => { - let user_ty = self.user_substs_applied_to_res(expr.hir_id, res); + let user_ty = self.user_args_applied_to_res(expr.hir_id, res); ExprKind::ZstLiteral { user_ty } } @@ -931,8 +916,8 @@ impl<'tcx> Cx<'tcx> { } Res::Def(DefKind::Const, def_id) | Res::Def(DefKind::AssocConst, def_id) => { - let user_ty = self.user_substs_applied_to_res(expr.hir_id, res); - ExprKind::NamedConst { def_id, substs, user_ty } + let user_ty = self.user_args_applied_to_res(expr.hir_id, res); + ExprKind::NamedConst { def_id, args, user_ty } } Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id) => { @@ -943,10 +928,10 @@ impl<'tcx> Cx<'tcx> { match ty.kind() { // A unit struct/variant which is used as a value. // We return a completely different ExprKind here to account for this special case. - ty::Adt(adt_def, substs) => ExprKind::Adt(Box::new(AdtExpr { + ty::Adt(adt_def, args) => ExprKind::Adt(Box::new(AdtExpr { adt_def: *adt_def, variant_index: adt_def.variant_index_with_ctor_id(def_id), - substs, + args, user_ty, fields: Box::new([]), base: None, @@ -1093,6 +1078,9 @@ impl<'tcx> Cx<'tcx> { variant_index, name: field, }, + HirProjectionKind::OpaqueCast => { + ExprKind::Use { source: self.thir.exprs.push(captured_place_expr) } + } HirProjectionKind::Index | HirProjectionKind::Subslice => { // We don't capture these projections, so we can ignore them here continue; diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index e6a98d1aa..d98cc76ad 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -16,7 +16,6 @@ use rustc_hir::Node; use rustc_middle::middle::region; use rustc_middle::thir::*; use rustc_middle::ty::{self, RvalueScopes, Ty, TyCtxt}; -use rustc_span::Span; pub(crate) fn thir_body( tcx: TyCtxt<'_>, @@ -62,14 +61,6 @@ struct Cx<'tcx> { typeck_results: &'tcx ty::TypeckResults<'tcx>, rvalue_scopes: &'tcx RvalueScopes, - /// When applying adjustments to the expression - /// with the given `HirId`, use the given `Span`, - /// instead of the usual span. This is used to - /// assign the span of an overall method call - /// (e.g. `my_val.foo()`) to the adjustment expressions - /// for the receiver. - adjustment_span: Option<(HirId, Span)>, - /// False to indicate that adjustments should not be applied. Only used for `custom_mir` apply_adjustments: bool, @@ -110,7 +101,6 @@ impl<'tcx> Cx<'tcx> { typeck_results, rvalue_scopes: &typeck_results.rvalue_scopes, body_owner: def.to_def_id(), - adjustment_span: None, apply_adjustments: hir .attrs(hir_id) .iter() @@ -132,7 +122,7 @@ impl<'tcx> Cx<'tcx> { DefKind::Closure => { let closure_ty = self.typeck_results.node_type(owner_id); - let ty::Closure(closure_def_id, closure_substs) = *closure_ty.kind() else { + let ty::Closure(closure_def_id, closure_args) = *closure_ty.kind() else { bug!("closure expr does not have closure type: {:?}", closure_ty); }; @@ -144,7 +134,7 @@ impl<'tcx> Cx<'tcx> { }; let env_region = ty::Region::new_late_bound(self.tcx, ty::INNERMOST, br); let closure_env_ty = - self.tcx.closure_env_ty(closure_def_id, closure_substs, env_region).unwrap(); + self.tcx.closure_env_ty(closure_def_id, closure_args, env_region).unwrap(); let liberated_closure_env_ty = self.tcx.erase_late_bound_regions( ty::Binder::bind_with_vars(closure_env_ty, bound_vars), ); @@ -196,7 +186,7 @@ impl<'tcx> Cx<'tcx> { self.tcx .type_of(va_list_did) - .subst(self.tcx, &[self.tcx.lifetimes.re_erased.into()]) + .instantiate(self.tcx, &[self.tcx.lifetimes.re_erased.into()]) } else { fn_sig.inputs()[index] }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index ef60f08bf..383e80851 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -135,10 +135,12 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> { }); return; } - ExprKind::Match { scrutinee, box ref arms } => { + ExprKind::Match { scrutinee, scrutinee_hir_id, box ref arms } => { let source = match ex.span.desugaring_kind() { Some(DesugaringKind::ForLoop) => hir::MatchSource::ForLoopDesugar, - Some(DesugaringKind::QuestionMark) => hir::MatchSource::TryDesugar, + Some(DesugaringKind::QuestionMark) => { + hir::MatchSource::TryDesugar(scrutinee_hir_id) + } Some(DesugaringKind::Await) => hir::MatchSource::AwaitDesugar, _ => hir::MatchSource::Normal, }; @@ -277,7 +279,7 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { | hir::MatchSource::FormatArgs => report_arm_reachability(&cx, &report), // Unreachable patterns in try and await expressions occur when one of // the arms are an uninhabited type. Which is OK. - hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar => {} + hir::MatchSource::AwaitDesugar | hir::MatchSource::TryDesugar(_) => {} } // Check if the match is exhaustive. @@ -501,12 +503,12 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> { let witness_1_is_privately_uninhabited = if cx.tcx.features().exhaustive_patterns && let Some(witness_1) = witnesses.get(0) - && let ty::Adt(adt, substs) = witness_1.ty().kind() + && let ty::Adt(adt, args) = witness_1.ty().kind() && adt.is_enum() && let Constructor::Variant(variant_index) = witness_1.ctor() { let variant = adt.variant(*variant_index); - let inhabited = variant.inhabited_predicate(cx.tcx, *adt).subst(cx.tcx, substs); + let inhabited = variant.inhabited_predicate(cx.tcx, *adt).instantiate(cx.tcx, args); assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module)); !inhabited.apply_ignore_module(cx.tcx, cx.param_env) } else { @@ -691,7 +693,7 @@ fn non_exhaustive_match<'p, 'tcx>( err = create_e0004( cx.tcx.sess, sp, - format!("non-exhaustive patterns: {} not covered", joined_patterns), + format!("non-exhaustive patterns: {joined_patterns} not covered"), ); err.span_label(sp, pattern_not_covered_label(&witnesses, &joined_patterns)); patterns_len = witnesses.len(); @@ -721,15 +723,13 @@ fn non_exhaustive_match<'p, 'tcx>( && matches!(witnesses[0].ctor(), Constructor::NonExhaustive) { err.note(format!( - "`{}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \ + "`{scrut_ty}` does not have a fixed maximum value, so a wildcard `_` is necessary to match \ exhaustively", - scrut_ty, )); if cx.tcx.sess.is_nightly_build() { err.help(format!( "add `#![feature(precise_pointer_size_matching)]` to the crate attributes to \ - enable precise `{}` matching", - scrut_ty, + enable precise `{scrut_ty}` matching", )); } } @@ -745,18 +745,13 @@ fn non_exhaustive_match<'p, 'tcx>( [] if sp.eq_ctxt(expr_span) => { // Get the span for the empty match body `{}`. let (indentation, more) = if let Some(snippet) = sm.indentation_before(sp) { - (format!("\n{}", snippet), " ") + (format!("\n{snippet}"), " ") } else { (" ".to_string(), "") }; suggestion = Some(( sp.shrink_to_hi().with_hi(expr_span.hi()), - format!( - " {{{indentation}{more}{pattern} => todo!(),{indentation}}}", - indentation = indentation, - more = more, - pattern = pattern, - ), + format!(" {{{indentation}{more}{pattern} => todo!(),{indentation}}}",), )); } [only] => { @@ -765,7 +760,7 @@ fn non_exhaustive_match<'p, 'tcx>( && let Ok(with_trailing) = sm.span_extend_while(only.span, |c| c.is_whitespace() || c == ',') && sm.is_multiline(with_trailing) { - (format!("\n{}", snippet), true) + (format!("\n{snippet}"), true) } else { (" ".to_string(), false) }; @@ -780,7 +775,7 @@ fn non_exhaustive_match<'p, 'tcx>( }; suggestion = Some(( only.span.shrink_to_hi(), - format!("{}{}{} => todo!()", comma, pre_indentation, pattern), + format!("{comma}{pre_indentation}{pattern} => todo!()"), )); } [.., prev, last] => { @@ -803,7 +798,7 @@ fn non_exhaustive_match<'p, 'tcx>( if let Some(spacing) = spacing { suggestion = Some(( last.span.shrink_to_hi(), - format!("{}{}{} => todo!()", comma, spacing, pattern), + format!("{comma}{spacing}{pattern} => todo!()"), )); } } @@ -900,7 +895,7 @@ fn adt_defined_here<'p, 'tcx>( for pat in spans { span.push_span_label(pat, "not covered"); } - err.span_note(span, format!("`{}` defined here", ty)); + err.span_note(span, format!("`{ty}` defined here")); } } @@ -942,7 +937,9 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>( /// This analysis is *not* subsumed by NLL. fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) { // Extract `sub` in `binding @ sub`. - let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { return }; + let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { + return; + }; let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 050b01294..1376344cf 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -325,6 +325,11 @@ impl<'tcx> ConstToPat<'tcx> { // `PartialEq::eq` on it. return Err(FallbackToConstRef); } + ty::FnDef(..) => { + self.saw_const_match_error.set(true); + tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty }); + PatKind::Wild + } ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => { debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,); self.saw_const_match_error.set(true); @@ -332,20 +337,20 @@ impl<'tcx> ConstToPat<'tcx> { tcx.sess.emit_err(err); PatKind::Wild } - ty::Adt(adt_def, substs) if adt_def.is_enum() => { + ty::Adt(adt_def, args) if adt_def.is_enum() => { let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap(); let variant_index = VariantIdx::from_u32(variant_index.unwrap_leaf().try_to_u32().ok().unwrap()); PatKind::Variant { adt_def: *adt_def, - substs, + args, variant_index, subpatterns: self.field_pats( fields.iter().copied().zip( adt_def.variants()[variant_index] .fields .iter() - .map(|field| field.ty(self.tcx(), substs)), + .map(|field| field.ty(self.tcx(), args)), ), )?, } @@ -354,9 +359,9 @@ impl<'tcx> ConstToPat<'tcx> { subpatterns: self .field_pats(cv.unwrap_branch().iter().copied().zip(fields.iter()))?, }, - ty::Adt(def, substs) => PatKind::Leaf { + ty::Adt(def, args) => PatKind::Leaf { subpatterns: self.field_pats(cv.unwrap_branch().iter().copied().zip( - def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), substs)), + def.non_enum_variant().fields.iter().map(|field| field.ty(self.tcx(), args)), ))?, }, ty::Slice(elem_ty) => PatKind::Slice { @@ -440,7 +445,7 @@ impl<'tcx> ConstToPat<'tcx> { } } }, - ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) | ty::FnDef(..) => PatKind::Constant { + ty::Bool | ty::Char | ty::Int(_) | ty::Uint(_) => PatKind::Constant { value: mir::ConstantKind::Ty(ty::Const::new_value(tcx, cv, ty)), }, ty::FnPtr(..) | ty::RawPtr(..) => unreachable!(), diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs index 9df6d2f43..bee1c4e46 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs @@ -306,9 +306,9 @@ impl fmt::Debug for IntRange { let (lo, hi) = self.boundaries(); let bias = self.bias; let (lo, hi) = (lo ^ bias, hi ^ bias); - write!(f, "{}", lo)?; + write!(f, "{lo}")?; write!(f, "{}", RangeEnd::Included)?; - write!(f, "{}", hi) + write!(f, "{hi}") } } @@ -922,7 +922,7 @@ impl<'tcx> SplitWildcard<'tcx> { let kind = if cx.is_uninhabited(*sub_ty) { FixedLen(0) } else { VarLen(0, 0) }; smallvec![Slice(Slice::new(None, kind))] } - ty::Adt(def, substs) if def.is_enum() => { + ty::Adt(def, args) if def.is_enum() => { // If the enum is declared as `#[non_exhaustive]`, we treat it as if it had an // additional "unknown" constructor. // There is no point in enumerating all possible variants, because the user can't @@ -950,21 +950,19 @@ impl<'tcx> SplitWildcard<'tcx> { let is_secretly_empty = def.variants().is_empty() && !is_exhaustive_pat_feature && !pcx.is_top_level; - let mut ctors: SmallVec<[_; 1]> = def - .variants() - .iter_enumerated() - .filter(|(_, v)| { - // If `exhaustive_patterns` is enabled, we exclude variants known to be - // uninhabited. - !is_exhaustive_pat_feature - || v.inhabited_predicate(cx.tcx, *def).subst(cx.tcx, substs).apply( - cx.tcx, - cx.param_env, - cx.module, - ) - }) - .map(|(idx, _)| Variant(idx)) - .collect(); + let mut ctors: SmallVec<[_; 1]> = + def.variants() + .iter_enumerated() + .filter(|(_, v)| { + // If `exhaustive_patterns` is enabled, we exclude variants known to be + // uninhabited. + !is_exhaustive_pat_feature + || v.inhabited_predicate(cx.tcx, *def) + .instantiate(cx.tcx, args) + .apply(cx.tcx, cx.param_env, cx.module) + }) + .map(|(idx, _)| Variant(idx)) + .collect(); if is_secretly_empty || is_declared_nonexhaustive { ctors.push(NonExhaustive); @@ -1156,12 +1154,12 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { ty: Ty<'tcx>, variant: &'a VariantDef, ) -> impl Iterator<Item = (FieldIdx, Ty<'tcx>)> + Captures<'a> + Captures<'p> { - let ty::Adt(adt, substs) = ty.kind() else { bug!() }; + let ty::Adt(adt, args) = ty.kind() else { bug!() }; // Whether we must not match the fields of this variant exhaustively. let is_non_exhaustive = variant.is_field_list_non_exhaustive() && !adt.did().is_local(); variant.fields.iter().enumerate().filter_map(move |(i, field)| { - let ty = field.ty(cx.tcx, substs); + let ty = field.ty(cx.tcx, args); // `field.ty()` doesn't normalize after substituting. let ty = cx.tcx.normalize_erasing_regions(cx.param_env, ty); let is_visible = adt.is_enum() || field.vis.is_accessible_from(cx.module, cx.tcx); @@ -1183,11 +1181,11 @@ impl<'p, 'tcx> Fields<'p, 'tcx> { Single | Variant(_) => match pcx.ty.kind() { ty::Tuple(fs) => Fields::wildcards_from_tys(pcx.cx, fs.iter(), pcx.span), ty::Ref(_, rty, _) => Fields::wildcards_from_tys(pcx.cx, once(*rty), pcx.span), - ty::Adt(adt, substs) => { + ty::Adt(adt, args) => { if adt.is_box() { // The only legal patterns of type `Box` (outside `std`) are `_` and box // patterns. If we're here we can assume this is a box pattern. - Fields::wildcards_from_tys(pcx.cx, once(substs.type_at(0)), pcx.span) + Fields::wildcards_from_tys(pcx.cx, once(args.type_at(0)), pcx.span) } else { let variant = &adt.variant(constructor.variant_index_for_adt(*adt)); let tys = Fields::list_variant_nonhidden_fields(pcx.cx, pcx.ty, variant) @@ -1294,7 +1292,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { } fields = Fields::from_iter(cx, wilds); } - ty::Adt(adt, substs) if adt.is_box() => { + ty::Adt(adt, args) if adt.is_box() => { // The only legal patterns of type `Box` (outside `std`) are `_` and box // patterns. If we're here we can assume this is a box pattern. // FIXME(Nadrieril): A `Box` can in theory be matched either with `Box(_, @@ -1311,7 +1309,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { let pat = if let Some(pat) = pattern { mkpat(&pat.pattern) } else { - DeconstructedPat::wildcard(substs.type_at(0), pat.span) + DeconstructedPat::wildcard(args.type_at(0), pat.span) }; ctor = Single; fields = Fields::singleton(cx, pat); @@ -1437,7 +1435,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { // the pattern is a box pattern. PatKind::Deref { subpattern: subpatterns.next().unwrap() } } - ty::Adt(adt_def, substs) => { + ty::Adt(adt_def, args) => { let variant_index = self.ctor.variant_index_for_adt(*adt_def); let variant = &adt_def.variant(variant_index); let subpatterns = Fields::list_variant_nonhidden_fields(cx, self.ty, variant) @@ -1446,7 +1444,7 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> { .collect(); if adt_def.is_enum() { - PatKind::Variant { adt_def: *adt_def, substs, variant_index, subpatterns } + PatKind::Variant { adt_def: *adt_def, args, variant_index, subpatterns } } else { PatKind::Leaf { subpatterns } } @@ -1621,7 +1619,7 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> { // of `std`). So this branch is only reachable when the feature is enabled and // the pattern is a box pattern. let subpattern = self.iter_fields().next().unwrap(); - write!(f, "box {:?}", subpattern) + write!(f, "box {subpattern:?}") } ty::Adt(..) | ty::Tuple(..) => { let variant = match self.ty.kind() { @@ -1640,7 +1638,7 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> { write!(f, "(")?; for p in self.iter_fields() { write!(f, "{}", start_or_comma())?; - write!(f, "{:?}", p)?; + write!(f, "{p:?}")?; } write!(f, ")") } @@ -1676,11 +1674,11 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> { write!(f, "]") } &FloatRange(lo, hi, end) => { - write!(f, "{}", lo)?; - write!(f, "{}", end)?; - write!(f, "{}", hi) + write!(f, "{lo}")?; + write!(f, "{end}")?; + write!(f, "{hi}") } - IntRange(range) => write!(f, "{:?}", range), // Best-effort, will render e.g. `false` as `0..=0` + IntRange(range) => write!(f, "{range:?}"), // Best-effort, will render e.g. `false` as `0..=0` Wildcard | Missing { .. } | NonExhaustive => write!(f, "_ : {:?}", self.ty), Or => { for pat in self.iter_fields() { @@ -1688,7 +1686,7 @@ impl<'p, 'tcx> fmt::Debug for DeconstructedPat<'p, 'tcx> { } Ok(()) } - Str(value) => write!(f, "{}", value), + Str(value) => write!(f, "{value}"), Opaque => write!(f, "<constant pattern>"), } } diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 600995927..c08fe54c3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -23,10 +23,10 @@ use rustc_middle::mir::interpret::{ use rustc_middle::mir::{self, ConstantKind, UserTypeProjection}; use rustc_middle::mir::{BorrowKind, Mutability}; use rustc_middle::thir::{Ascription, BindingMode, FieldPat, LocalVarId, Pat, PatKind, PatRange}; -use rustc_middle::ty::subst::{GenericArg, SubstsRef}; use rustc_middle::ty::CanonicalUserTypeAnnotation; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::{self, AdtDef, Region, Ty, TyCtxt, UserType}; +use rustc_middle::ty::{GenericArg, GenericArgsRef}; use rustc_span::{Span, Symbol}; use rustc_target::abi::FieldIdx; @@ -416,8 +416,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { let enum_id = self.tcx.parent(variant_id); let adt_def = self.tcx.adt_def(enum_id); if adt_def.is_enum() { - let substs = match ty.kind() { - ty::Adt(_, substs) | ty::FnDef(_, substs) => substs, + let args = match ty.kind() { + ty::Adt(_, args) | ty::FnDef(_, args) => args, ty::Error(_) => { // Avoid ICE (#50585) return PatKind::Wild; @@ -426,7 +426,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { }; PatKind::Variant { adt_def, - substs, + args, variant_index: adt_def.variant_index_with_id(variant_id), subpatterns, } @@ -439,7 +439,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { DefKind::Struct | DefKind::Ctor(CtorOf::Struct, ..) | DefKind::Union - | DefKind::TyAlias + | DefKind::TyAlias { .. } | DefKind::AssocTy, _, ) @@ -460,7 +460,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } }; - if let Some(user_ty) = self.user_substs_applied_to_ty_of_hir_id(hir_id) { + if let Some(user_ty) = self.user_args_applied_to_ty_of_hir_id(hir_id) { debug!("lower_variant_or_leaf: kind={:?} user_ty={:?} span={:?}", kind, user_ty, span); let annotation = CanonicalUserTypeAnnotation { user_ty: Box::new(user_ty), @@ -496,13 +496,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { // Use `Reveal::All` here because patterns are always monomorphic even if their function // isn't. let param_env_reveal_all = self.param_env.with_reveal_all_normalized(self.tcx); - // N.B. There is no guarantee that substs collected in typeck results are fully normalized, + // N.B. There is no guarantee that args collected in typeck results are fully normalized, // so they need to be normalized in order to pass to `Instance::resolve`, which will ICE // if given unnormalized types. - let substs = self + let args = self .tcx - .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_substs(id)); - let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, substs) { + .normalize_erasing_regions(param_env_reveal_all, self.typeck_results.node_args(id)); + let instance = match ty::Instance::resolve(self.tcx, param_env_reveal_all, def_id, args) { Ok(Some(i)) => i, Ok(None) => { // It should be assoc consts if there's no error but we cannot resolve it. @@ -617,16 +617,14 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> { } let typeck_root_def_id = tcx.typeck_root_def_id(def_id.to_def_id()); - let parent_substs = - tcx.erase_regions(ty::InternalSubsts::identity_for_item(tcx, typeck_root_def_id)); - let substs = - ty::InlineConstSubsts::new(tcx, ty::InlineConstSubstsParts { parent_substs, ty }) - .substs; + let parent_args = + tcx.erase_regions(ty::GenericArgs::identity_for_item(tcx, typeck_root_def_id)); + let args = ty::InlineConstArgs::new(tcx, ty::InlineConstArgsParts { parent_args, ty }).args; - let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), substs, promoted: None }; - debug_assert!(!substs.has_free_regions()); + let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), args, promoted: None }; + debug_assert!(!args.has_free_regions()); - let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), substs: substs }; + let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args: args }; // First try using a valtree in order to destructure the constant into a pattern. if let Ok(Some(valtree)) = self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span)) @@ -754,7 +752,7 @@ macro_rules! ClonePatternFoldableImpls { ClonePatternFoldableImpls! { <'tcx> Span, FieldIdx, Mutability, Symbol, LocalVarId, usize, Region<'tcx>, Ty<'tcx>, BindingMode, AdtDef<'tcx>, - SubstsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>, + GenericArgsRef<'tcx>, &'tcx GenericArg<'tcx>, UserType<'tcx>, UserTypeProjection, CanonicalUserTypeAnnotation<'tcx> } @@ -804,10 +802,10 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> { is_primary, } } - PatKind::Variant { adt_def, substs, variant_index, ref subpatterns } => { + PatKind::Variant { adt_def, args, variant_index, ref subpatterns } => { PatKind::Variant { adt_def: adt_def.fold_with(folder), - substs: substs.fold_with(folder), + args: args.fold_with(folder), variant_index, subpatterns: subpatterns.fold_with(folder), } diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs index e5b635069..08cfe98bb 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs @@ -459,7 +459,7 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "+")?; for pat in self.iter() { - write!(f, " {:?} +", pat)?; + write!(f, " {pat:?} +")?; } Ok(()) } @@ -530,7 +530,7 @@ impl<'p, 'tcx> fmt::Debug for Matrix<'p, 'tcx> { let Matrix { patterns: m, .. } = self; let pretty_printed_matrix: Vec<Vec<String>> = - m.iter().map(|row| row.iter().map(|pat| format!("{:?}", pat)).collect()).collect(); + m.iter().map(|row| row.iter().map(|pat| format!("{pat:?}")).collect()).collect(); let column_count = m.iter().map(|row| row.len()).next().unwrap_or(0); assert!(m.iter().all(|row| row.len() == column_count)); diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs index 8d7c624a8..3b6276cfe 100644 --- a/compiler/rustc_mir_build/src/thir/print.rs +++ b/compiler/rustc_mir_build/src/thir/print.rs @@ -321,7 +321,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, format!("pat: {:?}", pat), depth_lvl + 1); print_indented!(self, "}", depth_lvl); } - Match { scrutinee, arms } => { + Match { scrutinee, arms, .. } => { print_indented!(self, "Match {", depth_lvl); print_indented!(self, "scrutinee:", depth_lvl + 1); self.print_expr(*scrutinee, depth_lvl + 2); @@ -427,10 +427,10 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { self.print_expr(*value, depth_lvl + 2); print_indented!(self, "}", depth_lvl); } - ConstBlock { did, substs } => { + ConstBlock { did, args } => { print_indented!(self, "ConstBlock {", depth_lvl); print_indented!(self, format!("did: {:?}", did), depth_lvl + 1); - print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1); + print_indented!(self, format!("args: {:?}", args), depth_lvl + 1); print_indented!(self, "}", depth_lvl); } Repeat { value, count } => { @@ -499,11 +499,11 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { ZstLiteral { user_ty } => { print_indented!(self, format!("ZstLiteral(user_ty: {:?})", user_ty), depth_lvl); } - NamedConst { def_id, substs, user_ty } => { + NamedConst { def_id, args, user_ty } => { print_indented!(self, "NamedConst {", depth_lvl); print_indented!(self, format!("def_id: {:?}", def_id), depth_lvl + 1); print_indented!(self, format!("user_ty: {:?}", user_ty), depth_lvl + 1); - print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1); + print_indented!(self, format!("args: {:?}", args), depth_lvl + 1); print_indented!(self, "}", depth_lvl); } ConstParam { param, def_id } => { @@ -560,7 +560,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { format!("variant_index: {:?}", adt_expr.variant_index), depth_lvl + 1 ); - print_indented!(self, format!("substs: {:?}", adt_expr.substs), depth_lvl + 1); + print_indented!(self, format!("args: {:?}", adt_expr.args), depth_lvl + 1); print_indented!(self, format!("user_ty: {:?}", adt_expr.user_ty), depth_lvl + 1); for (i, field_expr) in adt_expr.fields.iter().enumerate() { @@ -662,11 +662,11 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { print_indented!(self, "}", depth_lvl + 1); } - PatKind::Variant { adt_def, substs, variant_index, subpatterns } => { + PatKind::Variant { adt_def, args, variant_index, subpatterns } => { print_indented!(self, "Variant {", depth_lvl + 1); print_indented!(self, "adt_def: ", depth_lvl + 2); self.print_adt_def(*adt_def, depth_lvl + 3); - print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 2); + print_indented!(self, format!("args: {:?}", args), depth_lvl + 2); print_indented!(self, format!("variant_index: {:?}", variant_index), depth_lvl + 2); if subpatterns.len() > 0 { @@ -784,11 +784,11 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> { } fn print_closure_expr(&mut self, expr: &ClosureExpr<'tcx>, depth_lvl: usize) { - let ClosureExpr { closure_id, substs, upvars, movability, fake_reads } = expr; + let ClosureExpr { closure_id, args, upvars, movability, fake_reads } = expr; print_indented!(self, "ClosureExpr {", depth_lvl); print_indented!(self, format!("closure_id: {:?}", closure_id), depth_lvl + 1); - print_indented!(self, format!("substs: {:?}", substs), depth_lvl + 1); + print_indented!(self, format!("args: {:?}", args), depth_lvl + 1); if upvars.len() > 0 { print_indented!(self, "upvars: [", depth_lvl + 1); diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs index c58ed1ac0..9106b4d33 100644 --- a/compiler/rustc_mir_build/src/thir/util.rs +++ b/compiler/rustc_mir_build/src/thir/util.rs @@ -9,7 +9,7 @@ pub(crate) trait UserAnnotatedTyHelpers<'tcx> { /// Looks up the type associated with this hir-id and applies the /// user-given substitutions; the hir-id must map to a suitable /// type. - fn user_substs_applied_to_ty_of_hir_id( + fn user_args_applied_to_ty_of_hir_id( &self, hir_id: hir::HirId, ) -> Option<CanonicalUserType<'tcx>> { |