about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-11-27 08:13:49 +0100
committerGitHub <noreply@github.com>2024-11-27 08:13:49 +0100
commit762a661705c52a6d99e8af37fc06aca573e35659 (patch)
tree6b17dafbbd45840085177a0650aa31b9369c9401
parent3cce78b0d125f3fd0179b51245f24587467cd2bc (diff)
parentfa66288a32bc202b4a12513d1961190025d2d576 (diff)
downloadrust-762a661705c52a6d99e8af37fc06aca573e35659.tar.gz
rust-762a661705c52a6d99e8af37fc06aca573e35659.zip
Rollup merge of #133493 - lcnr:fulfill-fudge, r=compiler-errors
do not constrain infer vars in `find_best_leaf_obligation`

This ended up causing an ICE by making the following code path reachable by incorrectly constraining an inference variable while computing the best obligation for a preceding ambiguity. Closes #129444.

https://github.com/rust-lang/rust/blob/f2abf827c128120ed7a874d02973947968c158b8/compiler/rustc_trait_selection/src/solve/fulfill.rs#L312-L314

I have to be honest, I don't fully understand how that change removes all the additional diagnostics :3

r? `@compiler-errors`
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill.rs17
-rw-r--r--tests/crashes/129444.rs15
-rw-r--r--tests/ui/coherence/fuzzing/best-obligation-ICE.rs20
-rw-r--r--tests/ui/coherence/fuzzing/best-obligation-ICE.stderr69
-rw-r--r--tests/ui/impl-trait/unsized_coercion.next.stderr30
-rw-r--r--tests/ui/impl-trait/unsized_coercion.rs3
-rw-r--r--tests/ui/impl-trait/unsized_coercion3.next.stderr30
-rw-r--r--tests/ui/impl-trait/unsized_coercion3.old.stderr2
-rw-r--r--tests/ui/impl-trait/unsized_coercion3.rs2
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs6
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr42
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs2
-rw-r--r--tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr14
13 files changed, 114 insertions, 138 deletions
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs
index 311dc214de6..0f90c45d032 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs
@@ -346,12 +346,21 @@ fn find_best_leaf_obligation<'tcx>(
     consider_ambiguities: bool,
 ) -> PredicateObligation<'tcx> {
     let obligation = infcx.resolve_vars_if_possible(obligation.clone());
+    // FIXME: we use a probe here as the `BestObligation` visitor does not
+    // check whether it uses candidates which get shadowed by where-bounds.
+    //
+    // We should probably fix the visitor to not do so instead, as this also
+    // means the leaf obligation may be incorrect.
     infcx
-        .visit_proof_tree(obligation.clone().into(), &mut BestObligation {
-            obligation: obligation.clone(),
-            consider_ambiguities,
+        .fudge_inference_if_ok(|| {
+            infcx
+                .visit_proof_tree(obligation.clone().into(), &mut BestObligation {
+                    obligation: obligation.clone(),
+                    consider_ambiguities,
+                })
+                .break_value()
+                .ok_or(())
         })
-        .break_value()
         .unwrap_or(obligation)
 }
 
diff --git a/tests/crashes/129444.rs b/tests/crashes/129444.rs
deleted file mode 100644
index b1b547b5191..00000000000
--- a/tests/crashes/129444.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-//@ known-bug: rust-lang/rust#129444
-
-//@ compile-flags: -Znext-solver=coherence
-
-trait Trait {
-    type Assoc;
-}
-
-struct W<T: Trait>(*mut T);
-impl<T: ?Trait> Trait for W<W<W<T>>> {}
-
-trait NoOverlap {}
-impl<T: Trait<W<T>>> NoOverlap for T {}
-
-impl<T: Trait<Assoc = u32>> NoOverlap for W<T> {}
diff --git a/tests/ui/coherence/fuzzing/best-obligation-ICE.rs b/tests/ui/coherence/fuzzing/best-obligation-ICE.rs
new file mode 100644
index 00000000000..49f40b579d4
--- /dev/null
+++ b/tests/ui/coherence/fuzzing/best-obligation-ICE.rs
@@ -0,0 +1,20 @@
+// A regression test for #129444. This previously ICE'd as
+// computing the best obligation for one ambiguous obligation
+// added spurious inference constraints which caused another
+// candidate to pass.
+trait Trait {
+    type Assoc;
+}
+
+struct W<T: Trait>(*mut T);
+impl<T> Trait for W<W<W<T>>> {}
+//~^ ERROR the trait bound `W<W<T>>: Trait` is not satisfied
+//~| ERROR the trait bound `W<T>: Trait` is not satisfied
+//~| ERROR the trait bound `T: Trait` is not satisfied
+//~| ERROR not all trait items implemented, missing: `Assoc`
+
+trait NoOverlap {}
+impl<T: Trait> NoOverlap for T {}
+impl<T: Trait<Assoc = u32>> NoOverlap for W<T> {}
+//~^ ERROR conflicting implementations of trait `NoOverlap` for type `W<W<W<W<_>>>>`
+fn main() {}
diff --git a/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr b/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr
new file mode 100644
index 00000000000..88de8023f6d
--- /dev/null
+++ b/tests/ui/coherence/fuzzing/best-obligation-ICE.stderr
@@ -0,0 +1,69 @@
+error[E0277]: the trait bound `W<W<T>>: Trait` is not satisfied
+  --> $DIR/best-obligation-ICE.rs:10:19
+   |
+LL | impl<T> Trait for W<W<W<T>>> {}
+   |                   ^^^^^^^^^^ the trait `Trait` is not implemented for `W<W<T>>`
+   |
+note: required by a bound in `W`
+  --> $DIR/best-obligation-ICE.rs:9:13
+   |
+LL | struct W<T: Trait>(*mut T);
+   |             ^^^^^ required by this bound in `W`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | impl<T> Trait for W<W<W<T>>> where W<W<T>>: Trait {}
+   |                              ++++++++++++++++++++
+
+error[E0277]: the trait bound `W<T>: Trait` is not satisfied
+  --> $DIR/best-obligation-ICE.rs:10:19
+   |
+LL | impl<T> Trait for W<W<W<T>>> {}
+   |                   ^^^^^^^^^^ the trait `Trait` is not implemented for `W<T>`
+   |
+note: required by a bound in `W`
+  --> $DIR/best-obligation-ICE.rs:9:13
+   |
+LL | struct W<T: Trait>(*mut T);
+   |             ^^^^^ required by this bound in `W`
+help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
+   |
+LL | impl<T> Trait for W<W<W<T>>> where W<T>: Trait {}
+   |                              +++++++++++++++++
+
+error[E0277]: the trait bound `T: Trait` is not satisfied
+  --> $DIR/best-obligation-ICE.rs:10:19
+   |
+LL | impl<T> Trait for W<W<W<T>>> {}
+   |                   ^^^^^^^^^^ the trait `Trait` is not implemented for `T`
+   |
+note: required by a bound in `W`
+  --> $DIR/best-obligation-ICE.rs:9:13
+   |
+LL | struct W<T: Trait>(*mut T);
+   |             ^^^^^ required by this bound in `W`
+help: consider restricting type parameter `T`
+   |
+LL | impl<T: Trait> Trait for W<W<W<T>>> {}
+   |       +++++++
+
+error[E0046]: not all trait items implemented, missing: `Assoc`
+  --> $DIR/best-obligation-ICE.rs:10:1
+   |
+LL |     type Assoc;
+   |     ---------- `Assoc` from trait
+...
+LL | impl<T> Trait for W<W<W<T>>> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `Assoc` in implementation
+
+error[E0119]: conflicting implementations of trait `NoOverlap` for type `W<W<W<W<_>>>>`
+  --> $DIR/best-obligation-ICE.rs:18:1
+   |
+LL | impl<T: Trait> NoOverlap for T {}
+   | ------------------------------ first implementation here
+LL | impl<T: Trait<Assoc = u32>> NoOverlap for W<T> {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `W<W<W<W<_>>>>`
+
+error: aborting due to 5 previous errors
+
+Some errors have detailed explanations: E0046, E0119, E0277.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/impl-trait/unsized_coercion.next.stderr b/tests/ui/impl-trait/unsized_coercion.next.stderr
index 4cebd26a5be..bea5ddb0aef 100644
--- a/tests/ui/impl-trait/unsized_coercion.next.stderr
+++ b/tests/ui/impl-trait/unsized_coercion.next.stderr
@@ -1,35 +1,11 @@
 error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
-  --> $DIR/unsized_coercion.rs:15:17
+  --> $DIR/unsized_coercion.rs:14:17
    |
 LL |         let x = hello();
    |                 ^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `dyn Trait`
 
-error[E0308]: mismatched types
-  --> $DIR/unsized_coercion.rs:19:5
-   |
-LL | fn hello() -> Box<impl Trait> {
-   |               ---------------
-   |               |   |
-   |               |   the expected opaque type
-   |               expected `Box<impl Trait>` because of return type
-...
-LL |     Box::new(1u32)
-   |     ^^^^^^^^^^^^^^ types differ
-   |
-   = note: expected struct `Box<impl Trait>`
-              found struct `Box<u32>`
-
-error[E0277]: the size for values of type `dyn Trait` cannot be known at compilation time
-  --> $DIR/unsized_coercion.rs:12:1
-   |
-LL | fn hello() -> Box<impl Trait> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |
-   = help: the trait `Sized` is not implemented for `dyn Trait`
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/unsized_coercion.rs b/tests/ui/impl-trait/unsized_coercion.rs
index b3791b38abc..2cbf0d25d7e 100644
--- a/tests/ui/impl-trait/unsized_coercion.rs
+++ b/tests/ui/impl-trait/unsized_coercion.rs
@@ -10,13 +10,12 @@ trait Trait {}
 impl Trait for u32 {}
 
 fn hello() -> Box<impl Trait> {
-    //[next]~^ ERROR the size for values of type `dyn Trait` cannot be known at compilation time
     if true {
         let x = hello();
         //[next]~^ ERROR: the size for values of type `dyn Trait` cannot be known at compilation time
         let y: Box<dyn Trait> = x;
     }
-    Box::new(1u32) //[next]~ ERROR: mismatched types
+    Box::new(1u32)
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/unsized_coercion3.next.stderr b/tests/ui/impl-trait/unsized_coercion3.next.stderr
index d1e1809cf16..28771e01813 100644
--- a/tests/ui/impl-trait/unsized_coercion3.next.stderr
+++ b/tests/ui/impl-trait/unsized_coercion3.next.stderr
@@ -1,35 +1,11 @@
 error[E0277]: the trait bound `dyn Send: Trait` is not satisfied
-  --> $DIR/unsized_coercion3.rs:14:17
+  --> $DIR/unsized_coercion3.rs:13:17
    |
 LL |         let x = hello();
    |                 ^^^^^^^ the trait `Trait` is not implemented for `dyn Send`
    |
    = help: the trait `Trait` is implemented for `u32`
 
-error[E0308]: mismatched types
-  --> $DIR/unsized_coercion3.rs:19:5
-   |
-LL | fn hello() -> Box<impl Trait + ?Sized> {
-   |               ------------------------
-   |               |   |
-   |               |   the expected opaque type
-   |               expected `Box<impl Trait + ?Sized>` because of return type
-...
-LL |     Box::new(1u32)
-   |     ^^^^^^^^^^^^^^ types differ
-   |
-   = note: expected struct `Box<impl Trait + ?Sized>`
-              found struct `Box<u32>`
-
-error[E0277]: the trait bound `dyn Send: Trait` is not satisfied
-  --> $DIR/unsized_coercion3.rs:11:1
-   |
-LL | fn hello() -> Box<impl Trait + ?Sized> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Send`
-   |
-   = help: the trait `Trait` is implemented for `u32`
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0277, E0308.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/unsized_coercion3.old.stderr b/tests/ui/impl-trait/unsized_coercion3.old.stderr
index 3bb9f9c2095..52a72b84a8d 100644
--- a/tests/ui/impl-trait/unsized_coercion3.old.stderr
+++ b/tests/ui/impl-trait/unsized_coercion3.old.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
-  --> $DIR/unsized_coercion3.rs:16:32
+  --> $DIR/unsized_coercion3.rs:15:32
    |
 LL |         let y: Box<dyn Send> = x;
    |                                ^ doesn't have a size known at compile-time
diff --git a/tests/ui/impl-trait/unsized_coercion3.rs b/tests/ui/impl-trait/unsized_coercion3.rs
index c1dd5350e22..ebfbb2955de 100644
--- a/tests/ui/impl-trait/unsized_coercion3.rs
+++ b/tests/ui/impl-trait/unsized_coercion3.rs
@@ -9,7 +9,6 @@ trait Trait {}
 impl Trait for u32 {}
 
 fn hello() -> Box<impl Trait + ?Sized> {
-    //[next]~^ ERROR: the trait bound `dyn Send: Trait` is not satisfied
     if true {
         let x = hello();
         //[next]~^ ERROR: the trait bound `dyn Send: Trait` is not satisfied
@@ -17,7 +16,6 @@ fn hello() -> Box<impl Trait + ?Sized> {
         //[old]~^ ERROR: the size for values of type `impl Trait + ?Sized` cannot be know
     }
     Box::new(1u32)
-    //[next]~^ ERROR: mismatched types
 }
 
 fn main() {}
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
index 1260cca5106..cbd591eec96 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.rs
@@ -14,13 +14,7 @@ fn main() {
 
 fn weird0() -> impl Sized + !Sized {}
 //~^ ERROR the trait bound `(): !Sized` is not satisfied
-//~| ERROR the trait bound `(): !Sized` is not satisfied
-//~| ERROR the trait bound `(): !Sized` is not satisfied
 fn weird1() -> impl !Sized + Sized {}
 //~^ ERROR the trait bound `(): !Sized` is not satisfied
-//~| ERROR the trait bound `(): !Sized` is not satisfied
-//~| ERROR the trait bound `(): !Sized` is not satisfied
 fn weird2() -> impl !Sized {}
 //~^ ERROR the trait bound `(): !Sized` is not satisfied
-//~| ERROR the trait bound `(): !Sized` is not satisfied
-//~| ERROR the trait bound `(): !Sized` is not satisfied
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
index 4ec578a3b7b..3dad6d534fd 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-bound.stderr
@@ -5,53 +5,17 @@ LL | fn weird0() -> impl Sized + !Sized {}
    |                ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
 
 error[E0277]: the trait bound `(): !Sized` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-bound.rs:15:36
-   |
-LL | fn weird0() -> impl Sized + !Sized {}
-   |                                    ^^ the trait bound `(): !Sized` is not satisfied
-
-error[E0277]: the trait bound `(): !Sized` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-bound.rs:15:1
-   |
-LL | fn weird0() -> impl Sized + !Sized {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
-
-error[E0277]: the trait bound `(): !Sized` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-bound.rs:19:16
+  --> $DIR/opaque-type-unsatisfied-bound.rs:17:16
    |
 LL | fn weird1() -> impl !Sized + Sized {}
    |                ^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
 
 error[E0277]: the trait bound `(): !Sized` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-bound.rs:19:36
-   |
-LL | fn weird1() -> impl !Sized + Sized {}
-   |                                    ^^ the trait bound `(): !Sized` is not satisfied
-
-error[E0277]: the trait bound `(): !Sized` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-bound.rs:19:1
-   |
-LL | fn weird1() -> impl !Sized + Sized {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
-
-error[E0277]: the trait bound `(): !Sized` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-bound.rs:23:16
+  --> $DIR/opaque-type-unsatisfied-bound.rs:19:16
    |
 LL | fn weird2() -> impl !Sized {}
    |                ^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
 
-error[E0277]: the trait bound `(): !Sized` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-bound.rs:23:28
-   |
-LL | fn weird2() -> impl !Sized {}
-   |                            ^^ the trait bound `(): !Sized` is not satisfied
-
-error[E0277]: the trait bound `(): !Sized` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-bound.rs:23:1
-   |
-LL | fn weird2() -> impl !Sized {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Sized` is not satisfied
-
 error[E0277]: the trait bound `impl !Trait: Trait` is not satisfied
   --> $DIR/opaque-type-unsatisfied-bound.rs:12:13
    |
@@ -66,6 +30,6 @@ note: required by a bound in `consume`
 LL | fn consume(_: impl Trait) {}
    |                    ^^^^^ required by this bound in `consume`
 
-error: aborting due to 10 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
index c6826578658..39422914afc 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.rs
@@ -4,7 +4,5 @@
 
 fn produce() -> impl !Fn<(u32,)> {}
 //~^ ERROR the trait bound `(): !Fn(u32)` is not satisfied
-//~| ERROR the trait bound `(): !Fn(u32)` is not satisfied
-//~| ERROR the trait bound `(): !Fn(u32)` is not satisfied
 
 fn main() {}
diff --git a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
index f81f0a23ac3..760e5aa62f2 100644
--- a/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
+++ b/tests/ui/traits/negative-bounds/opaque-type-unsatisfied-fn-bound.stderr
@@ -4,18 +4,6 @@ error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied
 LL | fn produce() -> impl !Fn<(u32,)> {}
    |                 ^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied
 
-error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:34
-   |
-LL | fn produce() -> impl !Fn<(u32,)> {}
-   |                                  ^^ the trait bound `(): !Fn(u32)` is not satisfied
-
-error[E0277]: the trait bound `(): !Fn(u32)` is not satisfied
-  --> $DIR/opaque-type-unsatisfied-fn-bound.rs:5:1
-   |
-LL | fn produce() -> impl !Fn<(u32,)> {}
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait bound `(): !Fn(u32)` is not satisfied
-
-error: aborting due to 3 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0277`.