Skip to content

Commit

Permalink
Rollup merge of rust-lang#109619 - compiler-errors:new-solver-still-f…
Browse files Browse the repository at this point in the history
…urther-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);
}
```
  • Loading branch information
matthiaskrgr authored Mar 26, 2023
2 parents e0cbfb9 + 3310f72 commit 3646445
Show file tree
Hide file tree
Showing 6 changed files with 111 additions and 3 deletions.
4 changes: 2 additions & 2 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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, "<:"),
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion compiler/rustc_trait_selection/src/solve/project_goals.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
30 changes: 30 additions & 0 deletions tests/ui/traits/new-solver/specialization-transmute.rs
Original file line number Diff line number Diff line change
@@ -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);
}
31 changes: 31 additions & 0 deletions tests/ui/traits/new-solver/specialization-transmute.stderr
Original file line number Diff line number Diff line change
@@ -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`.
22 changes: 22 additions & 0 deletions tests/ui/traits/new-solver/specialization-unconstrained.rs
Original file line number Diff line number Diff line change
@@ -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 == ()`
}
25 changes: 25 additions & 0 deletions tests/ui/traits/new-solver/specialization-unconstrained.stderr
Original file line number Diff line number Diff line change
@@ -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`.

0 comments on commit 3646445

Please sign in to comment.