summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_borrowck/src/region_infer
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-30 03:59:35 +0000
commitd1b2d29528b7794b41e66fc2136e395a02f8529b (patch)
treea4a17504b260206dec3cf55b2dca82929a348ac2 /compiler/rustc_borrowck/src/region_infer
parentReleasing progress-linux version 1.72.1+dfsg1-1~progress7.99u1. (diff)
downloadrustc-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')
-rw-r--r--compiler/rustc_borrowck/src/region_infer/dump_mir.rs11
-rw-r--r--compiler/rustc_borrowck/src/region_infer/graphviz.rs4
-rw-r--r--compiler/rustc_borrowck/src/region_infer/mod.rs61
-rw-r--r--compiler/rustc_borrowck/src/region_infer/opaque_types.rs98
-rw-r--r--compiler/rustc_borrowck/src/region_infer/values.rs6
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!(