about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2024-01-16 13:33:04 +0000
committerbors <bors@rust-lang.org>2024-01-16 13:33:04 +0000
commit533cfde67caa9c15cc01a685d247bb92ace96e81 (patch)
tree7ea6f4d5abd6e51adf70accd94b39cbdd751090d
parentfa0dc208d0a34027c1d3cca7d47975d8238bcfde (diff)
parent985e1e031b0d9d7c54812931c2beb57b0d304a94 (diff)
downloadrust-533cfde67caa9c15cc01a685d247bb92ace96e81.tar.gz
rust-533cfde67caa9c15cc01a685d247bb92ace96e81.zip
Auto merge of #119947 - compiler-errors:old-solver-instantiate-response, r=lcnr
Make sure to instantiate placeholders correctly in old solver

When creating the query substitution guess for an input placeholder type like `!1_T` (in universe 1), we were guessing the response substitution with something like `!0_T`. This failed to unify with `!1_T`, causing an ICE.

This PR reworks the query substitution guess code to work a bit more like the new solver. I'm *pretty* sure this is correct, though I'd really appreciate some scrutiny from someone (*cough* lcnr) who knows a bit more about query instantiation :)

Fixes #119941

r? lcnr
-rw-r--r--compiler/rustc_infer/src/infer/canonical/query_response.rs16
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs23
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr11
-rw-r--r--tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs27
7 files changed, 106 insertions, 4 deletions
diff --git a/compiler/rustc_infer/src/infer/canonical/query_response.rs b/compiler/rustc_infer/src/infer/canonical/query_response.rs
index 8cca4c6231f..1f071a9ff0b 100644
--- a/compiler/rustc_infer/src/infer/canonical/query_response.rs
+++ b/compiler/rustc_infer/src/infer/canonical/query_response.rs
@@ -483,7 +483,13 @@ impl<'tcx> InferCtxt<'tcx> {
         let result_subst = CanonicalVarValues {
             var_values: self.tcx.mk_args_from_iter(
                 query_response.variables.iter().enumerate().map(|(index, info)| {
-                    if info.is_existential() {
+                    if info.universe() != ty::UniverseIndex::ROOT {
+                        // A variable from inside a binder of the query. While ideally these shouldn't
+                        // exist at all, we have to deal with them for now.
+                        self.instantiate_canonical_var(cause.span, info, |u| {
+                            universe_map[u.as_usize()]
+                        })
+                    } else if info.is_existential() {
                         match opt_values[BoundVar::new(index)] {
                             Some(k) => k,
                             None => self.instantiate_canonical_var(cause.span, info, |u| {
@@ -491,9 +497,11 @@ impl<'tcx> InferCtxt<'tcx> {
                             }),
                         }
                     } else {
-                        self.instantiate_canonical_var(cause.span, info, |u| {
-                            universe_map[u.as_usize()]
-                        })
+                        // For placeholders which were already part of the input, we simply map this
+                        // universal bound variable back the placeholder of the input.
+                        opt_values[BoundVar::new(index)].expect(
+                            "expected placeholder to be unified with itself during response",
+                        )
                     }
                 }),
             ),
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr
new file mode 100644
index 00000000000..4082d6d47e7
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.current.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unifying-placeholders-in-query-response-2.rs:5:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr
new file mode 100644
index 00000000000..4082d6d47e7
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unifying-placeholders-in-query-response-2.rs:5:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs
new file mode 100644
index 00000000000..bbf1a1f72db
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response-2.rs
@@ -0,0 +1,23 @@
+// revisions: current next
+//[next] compile-flags: -Znext-solver
+// check-pass
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+trait Id {
+    type Output: ?Sized;
+}
+
+impl<T: ?Sized> Id for T {
+    type Output = T;
+}
+
+trait Everyone {}
+impl<T: ?Sized> Everyone for T {}
+
+fn hello() where for<T> <T as Id>::Output: Everyone {}
+
+fn main() {
+    hello();
+}
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr
new file mode 100644
index 00000000000..040009efbde
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.current.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unifying-placeholders-in-query-response.rs:5:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr
new file mode 100644
index 00000000000..040009efbde
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.next.stderr
@@ -0,0 +1,11 @@
+warning: the feature `non_lifetime_binders` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/unifying-placeholders-in-query-response.rs:5:12
+   |
+LL | #![feature(non_lifetime_binders)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #108185 <https://github.com/rust-lang/rust/issues/108185> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs
new file mode 100644
index 00000000000..5e28a2ba8b9
--- /dev/null
+++ b/tests/ui/traits/non_lifetime_binders/unifying-placeholders-in-query-response.rs
@@ -0,0 +1,27 @@
+// revisions: current next
+//[next] compile-flags: -Znext-solver
+// check-pass
+
+#![feature(non_lifetime_binders)]
+//~^ WARN the feature `non_lifetime_binders` is incomplete
+
+pub trait Foo<T: ?Sized> {
+    type Bar<K: ?Sized>: ?Sized;
+}
+
+impl Foo<usize> for () {
+    type Bar<K: ?Sized> = K;
+}
+
+pub fn f<T1, T2>(a: T1, b: T2)
+where
+    T1: for<T> Foo<usize, Bar<T> = T>,
+    T2: for<T> Foo<usize, Bar<T> = <T1 as Foo<usize>>::Bar<T>>,
+{
+}
+
+fn it_works() {
+    f((), ());
+}
+
+fn main() {}