-
Notifications
You must be signed in to change notification settings - Fork 13.8k
Closed
Description
Hi, consider the following code:
#![feature(specialization)]
#![feature(optin_builtin_traits)]
use std::ops::Deref;
use std::ops::DerefMut;
// =================
// === WithLabel ===
// =================
struct WithLabel<T>(String, T);
auto trait IsNotWithLabel {}
impl<T> !IsNotWithLabel for WithLabel<T> {}
pub trait HasLabel {
fn label(&self) -> &String;
}
impl<T> HasLabel for WithLabel<T> {
fn label(&self) -> &String {
&self.0
}
}
impl<T> HasLabel for T
where T: Deref + IsNotWithLabel, <Self as Deref>::Target : HasLabel {
default fn label(&self) -> &String {
self.deref().label()
}
}
impl<T> Deref for WithLabel<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.1
}
}
// ==============
// === WithID ===
// ==============
struct WithID<T>(i32, T);
pub trait HasID {
fn id(&self) -> &i32;
}
impl<T> HasID for WithID<T> {
fn id(&self) -> &i32 {
&self.0
}
}
auto trait IsNotWithID {}
impl<T> !IsNotWithID for WithID<T> {}
impl<T> HasID for T
where T: Deref + IsNotWithID, <Self as Deref>::Target : HasID {
default fn id(&self) -> &i32 {
self.deref().id()
}
}
impl<T> Deref for WithID<T> {
type Target = T;
fn deref(&self) -> &Self::Target {
&self.1
}
}
// =============
// === Usage ===
// =============
struct A(i32);
type X = WithLabel<WithID<A>>;
fn test<T: HasID + HasLabel> (t: T) {
println!("{:?}", t.label());
println!("{:?}", t.id());
}
fn main() {
let v1 = WithLabel("label1".to_string(), WithID(0, A(1)));
// test(v1); // THIS DOES NOT COMPILE
}
Everything compiles fine, but the last line (commented out). The error is:
error[E0277]: the trait bound `WithID<A>: IsNotWithID` is not satisfied in `WithLabel<WithID<A>>`
--> src/main.rs:88:10
|
81 | fn test<T: HasID + HasLabel> (t: T) {
| ---- ----- required by this bound in `test`
...
88 | test(v1);
| ^^ within `WithLabel<WithID<A>>`, the trait `IsNotWithID` is not implemented for `WithID<A>`
|
= help: the following implementations were found:
<WithID<T> as IsNotWithID>
= note: required because it appears within the type `WithLabel<WithID<A>>`
= note: required because of the requirements on the impl of `HasID` for `WithLabel<WithID<A>>`
And this is not correct. The type of v1
is WithLabel<WithID<A>>
. When passing it to test
we must prove that WithLabel<WithID<A>> : HasID + HasLabel
. Let's start with HasID
:
- The
impl<T> HasID for WithID<T>
is obviously not matched. - The
impl<T> HasID for T
is matched, including it's constraints:T: Deref + IsNotWithID
, and<Self as Deref>::Target : HasID
, becauseTarget
resolves toWithID<A>
and there is only 1 instance that matchesWithID<A>: HasID
.
The constraint WithLabel<WithID<A>> : HasLabel
is simple to be checked – only the impl<T> HasLabel for WithLabel<T>
is matched here.
Metadata
Metadata
Assignees
Labels
No labels