about summary refs log tree commit diff
diff options
context:
space:
mode:
authorOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-05-19 12:18:16 +0000
committerOli Scherer <git-spam-no-reply9815368754983@oli-obk.de>2022-09-21 13:11:54 +0000
commit90b6744af7a5c3944ef7d534b315467386e38673 (patch)
treeb75fc62b69f795e1200d19acd4d967247652e9ac
parent37928f59865b5ff53b95fe2f3c02491890a4129d (diff)
downloadrust-90b6744af7a5c3944ef7d534b315467386e38673.tar.gz
rust-90b6744af7a5c3944ef7d534b315467386e38673.zip
Also collect bounds from the ParamEnv for opaque types
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs9
-rw-r--r--compiler/rustc_infer/src/infer/outlives/verify.rs69
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds2.rs3
-rw-r--r--src/test/ui/type-alias-impl-trait/implied_bounds2.stderr12
4 files changed, 34 insertions, 59 deletions
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index ad5fbb9a158..ceea02e7817 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -318,7 +318,7 @@ where
         );
 
         let generic = GenericKind::Param(param_ty);
-        let verify_bound = self.verify_bound.generic_bound(generic);
+        let verify_bound = self.verify_bound.param_bound(param_ty);
         self.delegate.push_verify(origin, generic, region, verify_bound);
     }
 
@@ -476,7 +476,12 @@ where
         // projection outlive; in some cases, this may add insufficient
         // edges into the inference graph, leading to inference failures
         // even though a satisfactory solution exists.
-        let verify_bound = self.verify_bound.generic_bound(generic);
+        let verify_bound = self.verify_bound.projection_opaque_bounds(
+            generic,
+            def_id,
+            substs,
+            &mut Default::default(),
+        );
         debug!("projection_must_outlive: pushing {:?}", verify_bound);
         self.delegate.push_verify(origin, generic, region, verify_bound);
     }
diff --git a/compiler/rustc_infer/src/infer/outlives/verify.rs b/compiler/rustc_infer/src/infer/outlives/verify.rs
index 040843d8370..f5caa8d684e 100644
--- a/compiler/rustc_infer/src/infer/outlives/verify.rs
+++ b/compiler/rustc_infer/src/infer/outlives/verify.rs
@@ -38,21 +38,8 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         Self { tcx, region_bound_pairs, implicit_region_bound, param_env }
     }
 
-    /// Returns a "verify bound" that encodes what we know about
-    /// `generic` and the regions it outlives.
-    pub fn generic_bound(&self, generic: GenericKind<'tcx>) -> VerifyBound<'tcx> {
-        let mut visited = SsoHashSet::new();
-        match generic {
-            GenericKind::Param(param_ty) => self.param_bound(param_ty),
-            GenericKind::Projection(projection_ty) => {
-                self.projection_bound(projection_ty, &mut visited)
-            }
-            GenericKind::Opaque(def_id, substs) => self.opaque_bound(def_id, substs),
-        }
-    }
-
     #[instrument(level = "debug", skip(self))]
-    fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
+    pub fn param_bound(&self, param_ty: ty::ParamTy) -> VerifyBound<'tcx> {
         // Start with anything like `T: 'a` we can scrape from the
         // environment. If the environment contains something like
         // `for<'a> T: 'a`, then we know that `T` outlives everything.
@@ -116,20 +103,21 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
     }
 
     #[instrument(level = "debug", skip(self, visited))]
-    fn projection_bound(
+    pub fn projection_opaque_bounds(
         &self,
-        projection_ty: ty::ProjectionTy<'tcx>,
+        generic: GenericKind<'tcx>,
+        def_id: DefId,
+        substs: SubstsRef<'tcx>,
         visited: &mut SsoHashSet<GenericArg<'tcx>>,
     ) -> VerifyBound<'tcx> {
-        let projection_ty_as_ty =
-            self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
+        let generic_ty = generic.to_ty(self.tcx);
 
         // Search the env for where clauses like `P: 'a`.
-        let env_bounds = self
-            .approx_declared_bounds_from_env(GenericKind::Projection(projection_ty))
+        let projection_opaque_bounds = self
+            .approx_declared_bounds_from_env(generic)
             .into_iter()
             .map(|binder| {
-                if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == projection_ty_as_ty {
+                if let Some(ty::OutlivesPredicate(ty, r)) = binder.no_bound_vars() && ty == generic_ty {
                     // Micro-optimize if this is an exact match (this
                     // occurs often when there are no region variables
                     // involved).
@@ -139,35 +127,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
                     VerifyBound::IfEq(verify_if_eq_b)
                 }
             });
-
         // Extend with bounds that we can find from the trait.
-        let trait_bounds = self
-            .bounds(projection_ty.item_def_id, projection_ty.substs)
-            .map(|r| VerifyBound::OutlivedBy(r));
+        let trait_bounds = self.bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r));
 
         // see the extensive comment in projection_must_outlive
         let recursive_bound = {
             let mut components = smallvec![];
-            let ty = self.tcx.mk_projection(projection_ty.item_def_id, projection_ty.substs);
-            compute_components_recursive(self.tcx, ty.into(), &mut components, visited);
+            compute_components_recursive(self.tcx, generic_ty.into(), &mut components, visited);
             self.bound_from_components(&components, visited)
         };
 
-        VerifyBound::AnyBound(env_bounds.chain(trait_bounds).collect()).or(recursive_bound)
-    }
-
-    fn opaque_bound(&self, def_id: DefId, substs: SubstsRef<'tcx>) -> VerifyBound<'tcx> {
-        let bounds: Vec<_> =
-            self.bounds(def_id, substs).map(|r| VerifyBound::OutlivedBy(r)).collect();
-        trace!("{:#?}", bounds);
-        if bounds.is_empty() {
-            // No bounds means the value must not have any lifetimes.
-            // FIXME: should we implicitly add 'static to `tcx.item_bounds` for opaque types, just
-            // like we add `Sized`?
-            VerifyBound::OutlivedBy(self.tcx.lifetimes.re_static)
-        } else {
-            VerifyBound::AnyBound(bounds)
-        }
+        VerifyBound::AnyBound(projection_opaque_bounds.chain(trait_bounds).collect())
+            .or(recursive_bound)
     }
 
     fn bound_from_components(
@@ -199,8 +170,18 @@ impl<'cx, 'tcx> VerifyBoundCx<'cx, 'tcx> {
         match *component {
             Component::Region(lt) => VerifyBound::OutlivedBy(lt),
             Component::Param(param_ty) => self.param_bound(param_ty),
-            Component::Opaque(did, substs) => self.opaque_bound(did, substs),
-            Component::Projection(projection_ty) => self.projection_bound(projection_ty, visited),
+            Component::Opaque(did, substs) => self.projection_opaque_bounds(
+                GenericKind::Opaque(did, substs),
+                did,
+                substs,
+                visited,
+            ),
+            Component::Projection(projection_ty) => self.projection_opaque_bounds(
+                GenericKind::Projection(projection_ty),
+                projection_ty.item_def_id,
+                projection_ty.substs,
+                visited,
+            ),
             Component::EscapingProjection(ref components) => {
                 self.bound_from_components(components, visited)
             }
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds2.rs b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs
index d2ad062e799..b4c4c013cd2 100644
--- a/src/test/ui/type-alias-impl-trait/implied_bounds2.rs
+++ b/src/test/ui/type-alias-impl-trait/implied_bounds2.rs
@@ -1,9 +1,10 @@
+// check-pass
+
 #![feature(type_alias_impl_trait)]
 
 type Ty<'a, A> = impl Sized + 'a;
 fn defining<'a, A>() -> Ty<'a, A> {}
 fn assert_static<T: 'static>() {}
 fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::<Ty<'a, A>>() }
-//~^ ERROR: may not live long enough
 
 fn main() {}
diff --git a/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr b/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr
deleted file mode 100644
index b1c42c2c37f..00000000000
--- a/src/test/ui/type-alias-impl-trait/implied_bounds2.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0310]: the opaque type `Ty<'_, A>::{opaque#0}` may not live long enough
-  --> $DIR/implied_bounds2.rs:6:46
-   |
-LL | fn test<'a, A>() where Ty<'a, A>: 'static, { assert_static::<Ty<'a, A>>() }
-   |                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: consider adding an explicit lifetime bound `Ty<'_, A>::{opaque#0}: 'static`...
-   = note: ...so that the type `Ty<'_, A>` will meet its required lifetime bounds
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0310`.