-
Notifications
You must be signed in to change notification settings - Fork 13.7k
Open
Labels
A-trait-systemArea: Trait systemArea: Trait systemC-bugCategory: This is a bug.Category: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.WG-trait-system-refactorThe Rustc Trait System Refactor Initiative (-Znext-solver)The Rustc Trait System Refactor Initiative (-Znext-solver)
Description
The following compiles but should not
use std::marker::Unpin;
fn is_unpin<T: Unpin>() {}
trait OtherTrait {
type Assoc
where
Self: Unpin;
}
struct LocalTy;
impl Unpin for LocalTy
where
Self: OtherTrait<Assoc = LocalTy>,
{}
impl<T> OtherTrait for T {
type Assoc = T
where
Self: Unpin;
}
fn main() {
is_unpin::<LocalTy>()
}
proving LocalTy: Unpin
results in the following cycle:
LocalTy: Unpin
LocalTy: OtherTrait
(trivially true)<LocalTy as OtherTrait>::Assoc = LocalTy
LocalTy: Unpin
(cycle!)
While it's sound for this cycle to be coinductive, with our current rules it should not be. The new solver will also start out with this being inductive. Fulfill correctly detects this as an inductive cycle. Evaluate does not.
Note that using that is incredibly fragile as it depends on the following performance optimization to avoid fulfill:
rust/compiler/rustc_trait_selection/src/traits/fulfill.rs
Lines 604 to 614 in cce9e72
if obligation.predicate.is_global() { | |
// no type variables present, can use evaluation for better caching. | |
// FIXME: consider caching errors too. | |
if infcx.predicate_must_hold_considering_regions(obligation) { | |
debug!( | |
"selecting trait at depth {} evaluated to holds", | |
obligation.recursion_depth | |
); | |
return ProcessResult::Changed(vec![]); | |
} | |
} |
So the following code does result in the expected error 😁
use std::marker::Unpin;
fn is_unpin<T: Unpin>() {}
trait OtherTrait {
type Assoc
where
Self: Unpin;
}
struct LocalTy<'a>(&'a ());
impl<'a> Unpin for LocalTy<'a>
where
Self: OtherTrait<Assoc = LocalTy<'a>>,
{}
impl<T> OtherTrait for T {
type Assoc = T
where
Self: Unpin;
}
fn main() {
is_unpin::<LocalTy<'static>>()
}
error[E0275]: overflow evaluating the requirement `LocalTy<'_>: OtherTrait`
--> src/main.rs:12:10
|
12 | impl<'a> Unpin for LocalTy<'a>
| ^^^^^
|
= help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`test1`)
note: required for `LocalTy<'_>` to implement `Unpin`
--> src/main.rs:12:10
|
12 | impl<'a> Unpin for LocalTy<'a>
| ^^^^^ ^^^^^^^^^^^
note: required by a bound in `OtherTrait::Assoc`
--> src/main.rs:8:15
|
6 | type Assoc
| ----- required by a bound in this
7 | where
8 | Self: Unpin;
| ^^^^^ required by this bound in `OtherTrait::Assoc`
compiler-errors
Metadata
Metadata
Assignees
Labels
A-trait-systemArea: Trait systemArea: Trait systemC-bugCategory: This is a bug.Category: This is a bug.T-typesRelevant to the types team, which will review and decide on the PR/issue.Relevant to the types team, which will review and decide on the PR/issue.WG-trait-system-refactorThe Rustc Trait System Refactor Initiative (-Znext-solver)The Rustc Trait System Refactor Initiative (-Znext-solver)