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_borrowck/src/region_infer | |
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_borrowck/src/region_infer')
5 files changed, 94 insertions, 86 deletions
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<ty::RegionVid> = 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<ClosureOutlivesSubject<'tcx>> { 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<P0..Pn>() -> impl Trait - // - // into - // - // type Foo<P0...Pn> - // fn foo<P0..Pn>() -> Foo<P0...Pn>. - // - // For lifetime parameters we convert - // - // fn foo<'l0..'ln>() -> impl Trait<'l0..'lm> - // - // into - // - // type foo::<'p0..'pn>::Foo<'q0..'qm> - // fn foo<l0..'ln>() -> 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<Item = RegionElement>) -> 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<Item = RegionElement>) -> 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<Item = RegionElement>) -> 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!( |