about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-03-26 08:39:27 +0200
committerGitHub <noreply@github.com>2023-03-26 08:39:27 +0200
commit705435fe0115e6a56112cbf4cbe8cb51bf061a18 (patch)
tree17f77772aba579e32335109fcd4dc5eb75c4a3bd
parent236178698ab28fa9d9e9d979f42837ef468016e7 (diff)
parent3310f72db9205d23f7900d85055c5cd0eec17814 (diff)
downloadrust-705435fe0115e6a56112cbf4cbe8cb51bf061a18.tar.gz
rust-705435fe0115e6a56112cbf4cbe8cb51bf061a18.zip
Rollup merge of #109619 - compiler-errors:new-solver-still-further-specializable, r=BoxyUwU
Still-further-specializable projections are ambiguous in new solver

Fixes https://github.com/rust-lang/rust/pull/108896/files#r1148450781

r? ``@BoxyUwU`` (though feel free to re-roll)

---

This can be used to create an unsound transmute function with the new solver:

```rust
#![feature(specialization)]

trait Default {
   type Id;

   fn intu(&self) -> &Self::Id;
}

impl<T> Default for T {
   default type Id = T;

   fn intu(&self) -> &Self::Id {
        self
   }
}

fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
    *t.intu()
}

use std::num::NonZeroU8;
fn main() {
    let s = transmute::<u8, Option<NonZeroU8>>(0);
    assert_eq!(s, None);
}
```
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs4
-rw-r--r--compiler/rustc_trait_selection/src/solve/project_goals.rs2
-rw-r--r--tests/ui/traits/new-solver/specialization-transmute.rs30
-rw-r--r--tests/ui/traits/new-solver/specialization-transmute.stderr31
-rw-r--r--tests/ui/traits/new-solver/specialization-unconstrained.rs22
-rw-r--r--tests/ui/traits/new-solver/specialization-unconstrained.stderr25
6 files changed, 111 insertions, 3 deletions
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index e3cd5cca785..c6a56df5a5e 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -653,8 +653,8 @@ pub enum AliasRelationDirection {
 impl std::fmt::Display for AliasRelationDirection {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         match self {
-            AliasRelationDirection::Equate => write!(f, " == "),
-            AliasRelationDirection::Subtype => write!(f, " <: "),
+            AliasRelationDirection::Equate => write!(f, "=="),
+            AliasRelationDirection::Subtype => write!(f, "<:"),
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/solve/project_goals.rs b/compiler/rustc_trait_selection/src/solve/project_goals.rs
index 525b3105538..14c5b83c6ca 100644
--- a/compiler/rustc_trait_selection/src/solve/project_goals.rs
+++ b/compiler/rustc_trait_selection/src/solve/project_goals.rs
@@ -174,7 +174,7 @@ impl<'tcx> assembly::GoalKind<'tcx> for ProjectionPredicate<'tcx> {
                 goal.predicate.def_id(),
                 impl_def_id
             )? else {
-                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes);
+                return ecx.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS);
             };
 
             if !assoc_def.item.defaultness(tcx).has_value() {
diff --git a/tests/ui/traits/new-solver/specialization-transmute.rs b/tests/ui/traits/new-solver/specialization-transmute.rs
new file mode 100644
index 00000000000..a54701df4ef
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-transmute.rs
@@ -0,0 +1,30 @@
+// compile-flags: -Ztrait-solver=next
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+trait Default {
+   type Id;
+
+   fn intu(&self) -> &Self::Id;
+}
+
+impl<T> Default for T {
+   default type Id = T;
+
+   fn intu(&self) -> &Self::Id {
+        self
+        //~^ ERROR cannot satisfy `T <: <T as Default>::Id`
+   }
+}
+
+fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
+    *t.intu()
+}
+
+use std::num::NonZeroU8;
+fn main() {
+    let s = transmute::<u8, Option<NonZeroU8>>(0);
+    //~^ ERROR cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>
+    assert_eq!(s, None);
+}
diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr
new file mode 100644
index 00000000000..e67c56afc0d
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-transmute.stderr
@@ -0,0 +1,31 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-transmute.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0284]: type annotations needed: cannot satisfy `T <: <T as Default>::Id`
+  --> $DIR/specialization-transmute.rs:16:9
+   |
+LL |         self
+   |         ^^^^ cannot satisfy `T <: <T as Default>::Id`
+
+error[E0284]: type annotations needed: cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>`
+  --> $DIR/specialization-transmute.rs:27:13
+   |
+LL |     let s = transmute::<u8, Option<NonZeroU8>>(0);
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot satisfy `<u8 as Default>::Id == Option<NonZeroU8>`
+   |
+note: required by a bound in `transmute`
+  --> $DIR/specialization-transmute.rs:21:25
+   |
+LL | fn transmute<T: Default<Id = U>, U: Copy>(t: T) -> U {
+   |                         ^^^^^^ required by this bound in `transmute`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0284`.
diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.rs b/tests/ui/traits/new-solver/specialization-unconstrained.rs
new file mode 100644
index 00000000000..02150689ee5
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-unconstrained.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Ztrait-solver=next
+
+#![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
+
+// Do not treat the RHS of a projection-goal as an unconstrained `Certainty::Yes` response
+// if the impl is still further specializable.
+
+trait Default {
+   type Id;
+}
+
+impl<T> Default for T {
+   default type Id = T;
+}
+
+fn test<T: Default<Id = U>, U>() {}
+
+fn main() {
+    test::<u32, ()>();
+    //~^ ERROR cannot satisfy `<u32 as Default>::Id == ()`
+}
diff --git a/tests/ui/traits/new-solver/specialization-unconstrained.stderr b/tests/ui/traits/new-solver/specialization-unconstrained.stderr
new file mode 100644
index 00000000000..910925cbaeb
--- /dev/null
+++ b/tests/ui/traits/new-solver/specialization-unconstrained.stderr
@@ -0,0 +1,25 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-unconstrained.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+   = help: consider using `min_specialization` instead, which is more stable and complete
+   = note: `#[warn(incomplete_features)]` on by default
+
+error[E0284]: type annotations needed: cannot satisfy `<u32 as Default>::Id == ()`
+  --> $DIR/specialization-unconstrained.rs:20:5
+   |
+LL |     test::<u32, ()>();
+   |     ^^^^^^^^^^^^^^^ cannot satisfy `<u32 as Default>::Id == ()`
+   |
+note: required by a bound in `test`
+  --> $DIR/specialization-unconstrained.rs:17:20
+   |
+LL | fn test<T: Default<Id = U>, U>() {}
+   |                    ^^^^^^ required by this bound in `test`
+
+error: aborting due to previous error; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0284`.