about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-09-05 20:15:03 +0200
committerGitHub <noreply@github.com>2023-09-05 20:15:03 +0200
commit8c0490782e8ba3da4aaf9250e886478b9d3a7f48 (patch)
tree4a30fae8d92047ec9e58349de633c0dbadd7cb41
parentc7d5c12cc87d9df08c1a04ea5c9045b53569b7ae (diff)
parent98fa0c93ee031277e64eaee11fe9dbfe2147f532 (diff)
downloadrust-8c0490782e8ba3da4aaf9250e886478b9d3a7f48.tar.gz
rust-8c0490782e8ba3da4aaf9250e886478b9d3a7f48.zip
Rollup merge of #115559 - lcnr:implied-bounds-unconstrained, r=aliemjay
implied bounds: do not ICE on unconstrained region vars

fixes #112832

see tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs for a minimal example showing why this is necessary.

r? types

cc ``@compiler-errors`` ``@aliemjay`` https://rust-lang.zulipchat.com/#narrow/stream/144729-t-types/topic/assoc.20type.20bound.20in.20super.20trait
-rw-r--r--compiler/rustc_trait_selection/src/traits/outlives_bounds.rs14
-rw-r--r--tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs28
-rw-r--r--tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs20
3 files changed, 53 insertions, 9 deletions
diff --git a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
index 339baf611f3..32bbd626d4e 100644
--- a/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
+++ b/compiler/rustc_trait_selection/src/traits/outlives_bounds.rs
@@ -57,16 +57,12 @@ impl<'a, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'tcx> {
         let ty = OpportunisticRegionResolver::new(self).fold_ty(ty);
 
         // We do not expect existential variables in implied bounds.
-        // We may however encounter unconstrained lifetime variables in invalid
-        // code. See #110161 for context.
+        // We may however encounter unconstrained lifetime variables
+        // in very rare cases.
+        //
+        // See `ui/implied-bounds/implied-bounds-unconstrained-2.rs` for
+        // an example.
         assert!(!ty.has_non_region_infer());
-        if ty.has_infer() {
-            self.tcx.sess.delay_span_bug(
-                self.tcx.def_span(body_id),
-                "skipped implied_outlives_bounds due to unconstrained lifetimes",
-            );
-            return vec![];
-        }
 
         let mut canonical_var_values = OriginalQueryValues::default();
         let canonical_ty =
diff --git a/tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs b/tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs
new file mode 100644
index 00000000000..025e5176ff7
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-unconstrained-1.rs
@@ -0,0 +1,28 @@
+// check-pass
+
+// Regression test for #112832.
+pub trait QueryDb {
+    type Db;
+}
+
+pub struct QueryTable<Q, DB> {
+    db: DB,
+    storage: Q,
+}
+
+// We normalize `<Q as QueryDb>::Db` to `<Q as AsyncQueryFunction<'d>>::SendDb`
+// using the where-bound. 'd is an unconstrained region variable which previously
+// triggered an assert.
+impl<Q> QueryTable<Q, <Q as QueryDb>::Db> where Q: for<'d> AsyncQueryFunction<'d> {}
+
+pub trait AsyncQueryFunction<'d>: QueryDb<Db = <Self as AsyncQueryFunction<'d>>::SendDb> {
+    type SendDb: 'd;
+}
+
+pub trait QueryStorageOpsAsync<Q>
+where
+    Q: for<'d> AsyncQueryFunction<'d>,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs b/tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs
new file mode 100644
index 00000000000..976054facee
--- /dev/null
+++ b/tests/ui/implied-bounds/implied-bounds-unconstrained-2.rs
@@ -0,0 +1,20 @@
+// check-pass
+
+// Another minimized regression test for #112832.
+trait Trait {
+    type Assoc;
+}
+
+trait Sub<'a>: Trait<Assoc = <Self as Sub<'a>>::SubAssoc> {
+    type SubAssoc;
+}
+
+// By using the where-clause we normalize `<T as Trait>::Assoc` to
+// `<T as Sub<'a>>::SubAssoc` where `'a` is an unconstrained region
+// variable.
+fn foo<T>(x: <T as Trait>::Assoc)
+where
+    for<'a> T: Sub<'a>,
+{}
+
+fn main() {}