summaryrefslogtreecommitdiffstats
path: root/compiler/rustc_infer/src/infer/opaque_types.rs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_infer/src/infer/opaque_types.rs')
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs102
1 files changed, 59 insertions, 43 deletions
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index a982f11f7..524f7a39e 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -332,32 +332,11 @@ impl<'tcx> InferCtxt<'tcx> {
concrete_ty: Ty<'tcx>,
span: Span,
) {
- let def_id = opaque_type_key.def_id;
-
- let tcx = self.tcx;
-
let concrete_ty = self.resolve_vars_if_possible(concrete_ty);
-
debug!(?concrete_ty);
- let first_own_region = match self.opaque_ty_origin_unchecked(def_id, span) {
- hir::OpaqueTyOrigin::FnReturn(..) | hir::OpaqueTyOrigin::AsyncFn(..) => {
- // We lower
- //
- // 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>.
- //
- // For these types we only iterate over `'l0..lm` below.
- tcx.generics_of(def_id).parent_count
- }
- // These opaque type inherit all lifetime parameters from their
- // parent, so we have to check them all.
- hir::OpaqueTyOrigin::TyAlias => 0,
- };
+ let variances = self.tcx.variances_of(opaque_type_key.def_id);
+ debug!(?variances);
// For a case like `impl Foo<'a, 'b>`, we would generate a constraint
// `'r in ['a, 'b, 'static]` for each region `'r` that appears in the
@@ -370,9 +349,12 @@ impl<'tcx> InferCtxt<'tcx> {
// type can be equal to any of the region parameters of the
// opaque type definition.
let choice_regions: Lrc<Vec<ty::Region<'tcx>>> = Lrc::new(
- opaque_type_key.substs[first_own_region..]
+ opaque_type_key
+ .substs
.iter()
- .filter_map(|arg| match arg.unpack() {
+ .enumerate()
+ .filter(|(i, _)| variances[*i] == ty::Variance::Invariant)
+ .filter_map(|(_, arg)| match arg.unpack() {
GenericArgKind::Lifetime(r) => Some(r),
GenericArgKind::Type(_) | GenericArgKind::Const(_) => None,
})
@@ -381,6 +363,7 @@ impl<'tcx> InferCtxt<'tcx> {
);
concrete_ty.visit_with(&mut ConstrainOpaqueTypeRegionVisitor {
+ tcx: self.tcx,
op: |r| self.member_constraint(opaque_type_key, span, concrete_ty, r, &choice_regions),
});
}
@@ -427,24 +410,25 @@ impl<'tcx> InferCtxt<'tcx> {
}
}
-// Visitor that requires that (almost) all regions in the type visited outlive
-// `least_region`. We cannot use `push_outlives_components` because regions in
-// closure signatures are not included in their outlives components. We need to
-// ensure all regions outlive the given bound so that we don't end up with,
-// say, `ReVar` appearing in a return type and causing ICEs when other
-// functions end up with region constraints involving regions from other
-// functions.
-//
-// We also cannot use `for_each_free_region` because for closures it includes
-// the regions parameters from the enclosing item.
-//
-// We ignore any type parameters because impl trait values are assumed to
-// capture all the in-scope type parameters.
-struct ConstrainOpaqueTypeRegionVisitor<OP> {
- op: OP,
+/// Visitor that requires that (almost) all regions in the type visited outlive
+/// `least_region`. We cannot use `push_outlives_components` because regions in
+/// closure signatures are not included in their outlives components. We need to
+/// ensure all regions outlive the given bound so that we don't end up with,
+/// say, `ReVar` appearing in a return type and causing ICEs when other
+/// functions end up with region constraints involving regions from other
+/// functions.
+///
+/// We also cannot use `for_each_free_region` because for closures it includes
+/// the regions parameters from the enclosing item.
+///
+/// We ignore any type parameters because impl trait values are assumed to
+/// capture all the in-scope type parameters.
+pub struct ConstrainOpaqueTypeRegionVisitor<'tcx, OP: FnMut(ty::Region<'tcx>)> {
+ pub tcx: TyCtxt<'tcx>,
+ pub op: OP,
}
-impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<OP>
+impl<'tcx, OP> TypeVisitor<'tcx> for ConstrainOpaqueTypeRegionVisitor<'tcx, OP>
where
OP: FnMut(ty::Region<'tcx>),
{
@@ -490,6 +474,31 @@ where
substs.as_generator().yield_ty().visit_with(self);
substs.as_generator().resume_ty().visit_with(self);
}
+
+ ty::Opaque(def_id, ref substs) => {
+ // Skip lifetime paramters that are not captures.
+ let variances = self.tcx.variances_of(*def_id);
+
+ for (v, s) in std::iter::zip(variances, substs.iter()) {
+ if *v != ty::Variance::Bivariant {
+ s.visit_with(self);
+ }
+ }
+ }
+
+ ty::Projection(proj)
+ if self.tcx.def_kind(proj.item_def_id) == DefKind::ImplTraitPlaceholder =>
+ {
+ // Skip lifetime paramters that are not captures.
+ let variances = self.tcx.variances_of(proj.item_def_id);
+
+ for (v, s) in std::iter::zip(variances, proj.substs.iter()) {
+ if *v != ty::Variance::Bivariant {
+ s.visit_with(self);
+ }
+ }
+ }
+
_ => {
ty.super_visit_with(self);
}
@@ -586,7 +595,9 @@ impl<'tcx> InferCtxt<'tcx> {
ct_op: |ct| ct,
});
- if let ty::PredicateKind::Projection(projection) = predicate.kind().skip_binder() {
+ if let ty::PredicateKind::Clause(ty::Clause::Projection(projection)) =
+ predicate.kind().skip_binder()
+ {
if projection.term.references_error() {
// No point on adding these obligations since there's a type error involved.
return Ok(InferOk { value: (), obligations: vec![] });
@@ -595,7 +606,12 @@ impl<'tcx> InferCtxt<'tcx> {
}
// Require that the predicate holds for the concrete type.
debug!(?predicate);
- obligations.push(traits::Obligation::new(cause.clone(), param_env, predicate));
+ obligations.push(traits::Obligation::new(
+ self.tcx,
+ cause.clone(),
+ param_env,
+ predicate,
+ ));
}
Ok(InferOk { value: (), obligations })
}