summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer/src/infer/outlives
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src/infer/outlives')
-rw-r--r--compiler/rustc_infer/src/infer/outlives/components.rs40
-rw-r--r--compiler/rustc_infer/src/infer/outlives/mod.rs2
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs31
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs12
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs13
5 files changed, 76 insertions, 22 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/components.rs b/compiler/rustc_infer/src/infer/outlives/components.rs
index ff23087fe..cb63d2f18 100644
--- a/compiler/rustc_infer/src/infer/outlives/components.rs
+++ b/compiler/rustc_infer/src/infer/outlives/components.rs
@@ -143,7 +143,7 @@ fn compute_components<'tcx>(
// through and constrain Pi.
let mut subcomponents = smallvec![];
let mut subvisited = SsoHashSet::new();
- compute_components_recursive(tcx, ty.into(), &mut subcomponents, &mut subvisited);
+ compute_alias_components_recursive(tcx, ty, &mut subcomponents, &mut subvisited);
out.push(Component::EscapingAlias(subcomponents.into_iter().collect()));
}
}
@@ -193,7 +193,43 @@ fn compute_components<'tcx>(
///
/// This should not be used to get the components of `parent` itself.
/// Use [push_outlives_components] instead.
-pub(super) fn compute_components_recursive<'tcx>(
+pub(super) fn compute_alias_components_recursive<'tcx>(
+ tcx: TyCtxt<'tcx>,
+ alias_ty: Ty<'tcx>,
+ out: &mut SmallVec<[Component<'tcx>; 4]>,
+ visited: &mut SsoHashSet<GenericArg<'tcx>>,
+) {
+ let ty::Alias(kind, alias_ty) = alias_ty.kind() else { bug!() };
+ let opt_variances = if *kind == ty::Opaque { tcx.variances_of(alias_ty.def_id) } else { &[] };
+ for (index, child) in alias_ty.substs.iter().enumerate() {
+ if opt_variances.get(index) == Some(&ty::Bivariant) {
+ continue;
+ }
+ if !visited.insert(child) {
+ continue;
+ }
+ match child.unpack() {
+ GenericArgKind::Type(ty) => {
+ compute_components(tcx, ty, out, visited);
+ }
+ GenericArgKind::Lifetime(lt) => {
+ // Ignore late-bound regions.
+ if !lt.is_late_bound() {
+ out.push(Component::Region(lt));
+ }
+ }
+ GenericArgKind::Const(_) => {
+ compute_components_recursive(tcx, child, out, visited);
+ }
+ }
+ }
+}
+
+/// Collect [Component]s for *all* the substs of `parent`.
+///
+/// This should not be used to get the components of `parent` itself.
+/// Use [push_outlives_components] instead.
+fn compute_components_recursive<'tcx>(
tcx: TyCtxt<'tcx>,
parent: GenericArg<'tcx>,
out: &mut SmallVec<[Component<'tcx>; 4]>,
diff --git a/compiler/rustc_infer/src/infer/outlives/mod.rs b/compiler/rustc_infer/src/infer/outlives/mod.rs
index 9a9a1696b..8a44d5031 100644
--- a/compiler/rustc_infer/src/infer/outlives/mod.rs
+++ b/compiler/rustc_infer/src/infer/outlives/mod.rs
@@ -61,7 +61,7 @@ impl<'tcx> InferCtxt<'tcx> {
};
let lexical_region_resolutions = LexicalRegionResolutions {
- values: rustc_index::vec::IndexVec::from_elem_n(
+ values: rustc_index::IndexVec::from_elem_n(
crate::infer::lexical_region_resolve::VarValue::Value(self.tcx.lifetimes.re_erased),
var_infos.len(),
),
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index ccf11c61b..9c20c814b 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -256,7 +256,7 @@ where
// this point it never will be
self.tcx.sess.delay_span_bug(
origin.span(),
- &format!("unresolved inference variable in outlives: {:?}", v),
+ format!("unresolved inference variable in outlives: {:?}", v),
);
}
}
@@ -344,12 +344,14 @@ where
// the problem is to add `T: 'r`, which isn't true. So, if there are no
// inference variables, we use a verify constraint instead of adding
// edges, which winds up enforcing the same condition.
+ let is_opaque = alias_ty.kind(self.tcx) == ty::Opaque;
if approx_env_bounds.is_empty()
&& trait_bounds.is_empty()
- && (alias_ty.needs_infer() || alias_ty.kind(self.tcx) == ty::Opaque)
+ && (alias_ty.has_infer() || is_opaque)
{
debug!("no declared bounds");
- self.substs_must_outlive(alias_ty.substs, origin, region);
+ let opt_variances = is_opaque.then(|| self.tcx.variances_of(alias_ty.def_id));
+ self.substs_must_outlive(alias_ty.substs, origin, region, opt_variances);
return;
}
@@ -395,22 +397,31 @@ where
self.delegate.push_verify(origin, GenericKind::Alias(alias_ty), region, verify_bound);
}
+ #[instrument(level = "debug", skip(self))]
fn substs_must_outlive(
&mut self,
substs: SubstsRef<'tcx>,
origin: infer::SubregionOrigin<'tcx>,
region: ty::Region<'tcx>,
+ opt_variances: Option<&[ty::Variance]>,
) {
let constraint = origin.to_constraint_category();
- for k in substs {
+ for (index, k) in substs.iter().enumerate() {
match k.unpack() {
GenericArgKind::Lifetime(lt) => {
- self.delegate.push_sub_region_constraint(
- origin.clone(),
- region,
- lt,
- constraint,
- );
+ let variance = if let Some(variances) = opt_variances {
+ variances[index]
+ } else {
+ ty::Invariant
+ };
+ if variance == ty::Invariant {
+ self.delegate.push_sub_region_constraint(
+ origin.clone(),
+ region,
+ lt,
+ constraint,
+ );
+ }
}
GenericArgKind::Type(ty) => {
self.type_must_outlive(origin.clone(), ty, region, constraint);
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 01f900f05..cd2462d3c 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -13,9 +13,11 @@ use crate::infer::region_constraints::VerifyIfEq;
/// Given a "verify-if-eq" type test like:
///
-/// exists<'a...> {
-/// verify_if_eq(some_type, bound_region)
-/// }
+/// ```rust,ignore (pseudo-Rust)
+/// exists<'a...> {
+/// verify_if_eq(some_type, bound_region)
+/// }
+/// ```
///
/// and the type `test_ty` that the type test is being tested against,
/// returns:
@@ -185,7 +187,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
} else if pattern == value {
Ok(pattern)
} else {
- relate::super_relate_tys(self, pattern, value)
+ relate::structurally_relate_tys(self, pattern, value)
}
}
@@ -199,7 +201,7 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
if pattern == value {
Ok(pattern)
} else {
- relate::super_relate_consts(self, pattern, value)
+ relate::structurally_relate_consts(self, pattern, value)
}
}
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index bae246418..c2bf0f3db 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -1,4 +1,4 @@
-use crate::infer::outlives::components::{compute_components_recursive, Component};
+use crate::infer::outlives::components::{compute_alias_components_recursive, Component};
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::region_constraints::VerifyIfEq;
use crate::infer::VerifyBound;
@@ -130,7 +130,12 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// see the extensive comment in projection_must_outlive
let recursive_bound = {
let mut components = smallvec![];
- compute_components_recursive(self.tcx, alias_ty_as_ty.into(), &mut components, visited);
+ compute_alias_components_recursive(
+ self.tcx,
+ alias_ty_as_ty.into(),
+ &mut components,
+ visited,
+ );
self.bound_from_components(&components, visited)
};
@@ -174,7 +179,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
// this point it never will be
self.tcx.sess.delay_span_bug(
rustc_span::DUMMY_SP,
- &format!("unresolved inference variable in outlives: {:?}", v),
+ format!("unresolved inference variable in outlives: {:?}", v),
);
// add a bound that never holds
VerifyBound::AnyBound(vec![])
@@ -272,7 +277,7 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
///
/// It will not, however, work for higher-ranked bounds like:
///
- /// ```compile_fail,E0311
+ /// ```ignore(this does compile today, previously was marked as `compile_fail,E0311`)
/// trait Foo<'a, 'b>
/// where for<'x> <Self as Foo<'x, 'b>>::Bar: 'x
/// {