I want to implement the trait TryFrom in a case like this:
struct T1;
struct T2(T1);
impl<U> TryFrom<U> for T2 where U: Into<T1> {
type Error = ();
fn try_from(val:U) -> Result<T2, Self::Error> {
unimplemented!();
}
}
which gives me this error:
error[E0119]: conflicting implementations of trait `std::convert::TryFrom<_>` for type `T2`
--> src/lib.rs:4:1
|
4 | impl<U> TryFrom<U> for T2 where U: Into<T1> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<T, U> TryFrom<U> for T
where U: Into<T>;
Here U implement Into<T1> not Into<T2> thus I don't really understand the error. I tried to confirm there is no blanket implementation by implementing this and it compiles without conflict:
struct T1;
struct T2(T1);
impl Into<T2> for T1 {
fn into(self) -> T2 {
unimplemented!();
}
}
Is there any way around it? I don't want a default implementation here.
Trait implementations are not allowed to conflict. A type is perfectly allowed to implement both Into<T1> and Into<T2>. Your implementation would cause an ambiguity in this case whether to use the T: TryFrom<U> implementation by the built-in blanket implementation or from your blanket implementation. And thus there is a conflict and the compiler rejects your implementation.
Essentially you cannot implement TryFrom generically because of the blanket implementation; you can't avoid a potential conflict.
Your confirmation doesn't mean anything since there is no such blanket implementation for Into that would conflict between T1 and T2. If you tried to implement it generically, like impl Into<T2> for U where U: Into<T1>, that'd be a problem as well. The genericism is the core problem.
Related
Say I have this code:
pub trait A {}
pub trait B {}
pub trait SomeBehavior {
fn func() -> bool;
}
And I want to provide the blanket implementation for A and B like this:
impl <T> SomeBehavior for T where T: A {
fn func() -> bool { true }
}
impl <T> SomeBehavior for T where T: B {
fn func() -> bool { false }
}
But this gives following error:
error[E0119]: conflicting implementations of trait `SomeBehavior`
--> src/lib.rs:12:1
|
8 | impl <T> SomeBehavior for T where T: A {
| -------------------------------------- first implementation here
...
12 | impl <T> SomeBehavior for T where T: B {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
Why the compiler treats two different implementations on different traits as same implementation?
Rust has the concept of "trait coherence" which is the idea that for any combination of type and trait there should be at most one implementation of that trait. This is the concept that guides Rust's "orphan rule" and is designed to ensure that conflicting implementations can't occur in downstream crates.
So the problem with the two blanket implementations above is the possibility that a type can implement both A and B. There would then be two possible implementations for SomeBehavior for that type.
struct MyType;
impl A for MyType;
impl B for MyType;
let t = MyType;
let _ = t.func(); // how to choose?
Its not particularly well documented part of Rust unfortunately; likely because its complicated, its contentious, the rules have changed over the years, and will likely change again in the future. Resources are scattered between blog posts, RFCs, and issues but you can find the important bits in the Coherence section of the chalk book (the next-generation trait-solver).
There may be features added in the future that may allow this or something similar:
negative impls (unstable feature)
specialization (RFC)
crate-level where-clauses (blog article by Niko Matsakis)
It seems that when deriving Clone, Rust forwards the Clone trait requirement to Generics that do not require the trait, like if they are wrapped inside an Arc.
Do I misunderstand how Clone works or is this a compiler mistake?
Consider the following code, where a.clone() works, but b.clone() does not.
Also note that without the b.clone() call, the code compiles fine, indicating that #[derive(Clone)] worked.
use std::sync::Arc;
struct Unclonable {}
struct A<T>(Arc<T>);
impl<T> Clone for A<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
#[derive(Clone)]
struct B<T>(Arc<T>);
fn main() {
let a = A(Arc::new(Unclonable {}));
let b = B(Arc::new(Unclonable {}));
// Works
a.clone();
// Fails
b.clone();
}
|
3 | struct Unclonable {}
| ----------------- doesn't satisfy `Unclonable: Clone`
...
13 | struct B<T>(Arc<T>);
| --------------------
| |
| method `clone` not found for this
| doesn't satisfy `B<Unclonable>: Clone`
...
22 | b.clone();
| ^^^^^ method cannot be called on `B<Unclonable>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`Unclonable: Clone`
which is required by `B<Unclonable>: Clone`
= help: items from traits can only be used if the trait is implemented and in scope
= note: the following trait defines an item `clone`, perhaps you need to implement it:
candidate #1: `Clone`
help: consider annotating `Unclonable` with `#[derive(Clone)]`
|
3 | #[derive(Clone)]
|
When I expand the macros, I see the following generated code:
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2018::*;
#[macro_use]
extern crate std;
use std::sync::Arc;
struct Unclonable {}
struct A<T>(Arc<T>);
impl<T> Clone for A<T> {
fn clone(&self) -> Self {
Self(self.0.clone())
}
}
struct B<T>(Arc<T>);
#[automatically_derived]
#[allow(unused_qualifications)]
impl<T: ::core::clone::Clone> ::core::clone::Clone for B<T> {
#[inline]
fn clone(&self) -> B<T> {
match *self {
B(ref __self_0_0) => B(::core::clone::Clone::clone(&(*__self_0_0))),
}
}
}
fn main() {
let a = A(Arc::new(Unclonable {}));
let b = B(Arc::new(Unclonable {}));
a.clone();
b.clone();
}
What is going on?
Why would the Rust compiler add <T: ::core::clone::Clone>??
Or is this just one of those cases where the intended way is to implement Clone manually?
This is not a compiler bug, in the sense that it's a documented behavior, even though one might find it weird. The compiler will automatically add constraints to generic types when deriving, even if those constraints are not actually required in the implementation. For instance, deriving Clone for B<T> will only implement Clone for B<T> where T: Clone, even though it would be possibly to implement that regardless of whether T is Clone.
So, for the time being (maybe the compiler will get smarter about these cases in the future), yes, it's one of those cases where you have to implement manually.
If you don't mind a smallo dependency, you can avoid the drudgery1 of manual implementation using the derivative crate:
#[derive(Derivative)]
#[derivative(Clone(bound = ""))]
struct B<T>(Arc<T>);
Playground
1 In the case of a small struct the drudgery is not that bad, but in case of an enum with many variants, the implementation gets quite large.
Say I have this code:
pub trait A {}
pub trait B {}
pub trait SomeBehavior {
fn func() -> bool;
}
And I want to provide the blanket implementation for A and B like this:
impl <T> SomeBehavior for T where T: A {
fn func() -> bool { true }
}
impl <T> SomeBehavior for T where T: B {
fn func() -> bool { false }
}
But this gives following error:
error[E0119]: conflicting implementations of trait `SomeBehavior`
--> src/lib.rs:12:1
|
8 | impl <T> SomeBehavior for T where T: A {
| -------------------------------------- first implementation here
...
12 | impl <T> SomeBehavior for T where T: B {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
Why the compiler treats two different implementations on different traits as same implementation?
Rust has the concept of "trait coherence" which is the idea that for any combination of type and trait there should be at most one implementation of that trait. This is the concept that guides Rust's "orphan rule" and is designed to ensure that conflicting implementations can't occur in downstream crates.
So the problem with the two blanket implementations above is the possibility that a type can implement both A and B. There would then be two possible implementations for SomeBehavior for that type.
struct MyType;
impl A for MyType;
impl B for MyType;
let t = MyType;
let _ = t.func(); // how to choose?
Its not particularly well documented part of Rust unfortunately; likely because its complicated, its contentious, the rules have changed over the years, and will likely change again in the future. Resources are scattered between blog posts, RFCs, and issues but you can find the important bits in the Coherence section of the chalk book (the next-generation trait-solver).
There may be features added in the future that may allow this or something similar:
negative impls (unstable feature)
specialization (RFC)
crate-level where-clauses (blog article by Niko Matsakis)
I want trait implementations in Rust to be able to return arbitrary iterators (of specific item type) that may reference the original object with a lifetime 'a without having to explicitly mention 'a in the trait generics and everywhere where the trait is used or otherwise introducing significant trait bound bloat to user code. The only simple way I've figured to do this is that the trait has to be implemented for &'a MyStruct instead of MyStruct (this approach is used in some places in the standard library), but the significant drawback is that in generic code wrappers cannot “own” implementations of the trait (MyStruct) without exposing the lifetime in trait bounds all over the code. So nothing gained when ownership is needed.
Another way I figured out that should work (just done the simple test below so far) is to use higher-ranked lifetime bounds on a “base trait” that would implement the iterator-generation functions. In the code below Foo is the main trait, FooInterfaceGen is the iterator-generator trait that has its lifetime “hidden” through for <'a> when assumed as a super-trait of Foo. The FooInterface generated by FooInterfaceGen would be the trait for an appropriate type of iterator when modified to that application of the idea. However, it seems impossible to make additional trait bounds on the specific implementation FooInterfaceGen::Interface. The code below works, but when you uncomment the Asdf trait bound in the function footest, the compiler complains that
the trait `for<'a> Asdf` is not implemented for `<_ as FooInterfaceGen<'a>>::Interface
But I have implemented Asdf! It's as if the compiler is ignoring the 'a in the expression <T as FooInterfaceGen<'a>> and just applying for<'a> to the right-hand-side. Any ideas if this is a compiler bug, a known restriction, or of any ways around it?
trait FooInterface<'a> {
fn foo(&self) -> u32;
}
trait FooInterfaceGen<'a> {
type Interface : FooInterface<'a>;
fn gen(&'a self) -> Self::Interface;
}
trait Foo : for<'a> FooInterfaceGen<'a> { }
struct S2;
struct S1(S2);
impl<'a> FooInterfaceGen<'a> for S1 {
type Interface = &'a S2;
fn gen(&'a self) -> Self::Interface { &self.0 }
}
impl Foo for S1 { }
impl<'a> FooInterface<'a> for &'a S2 {
fn foo(&self) -> u32 { 42 }
}
trait Asdf {}
impl<'a> Asdf for &'a S2 {}
fn footest<T : Foo>(a : &T) -> u32
/* where for<'a> <T as FooInterfaceGen<'a>>::Interface : Asdf */ {
a.gen().foo()
}
fn main() {
let q = S1(S2);
println!("{}", footest(&q));
}
(Regarding some alternative implementations, maybe there's a technical reason for it, but otherwise I really don't understand the reason behind the significant trait bound bloat that Rust code easily introduces. Assuming a trait should in any reasonable situation automatically assume all the trait bound as well, also in generic code, not just specific code, without having to copy-paste an increasing number of where-clauses all over the code.)
The error seems to be a known compiler bug: https://github.com/rust-lang/rust/issues/89196
If I have a trait, and a function that accepts a generic type constrained to that type, everything works fine. If I try to pass in a reference to that type, I get a compilation error.
trait Trait {
fn hello(&self) -> u32;
}
struct Struct(u32);
impl Trait for Struct {
fn hello(&self) -> u32 {
self.0
}
}
fn runner<T: Trait>(t: T) {
println!("{}", t.hello())
}
fn main() {
let s = Struct(42);
// Works
runner(s);
// Doesn't work
runner(&s);
}
error[E0277]: the trait bound `&Struct: Trait` is not satisfied
--> src/main.rs:24:5
|
24 | runner(&s);
| ^^^^^^ the trait `Trait` is not implemented for `&Struct`
|
= help: the following implementations were found:
<Struct as Trait>
note: required by `runner`
--> src/main.rs:13:1
|
13 | fn runner<T: Trait>(t: T) {
| ^^^^^^^^^^^^^^^^^^^^^^^^^
I can fix the issue by implementing the trait for any reference to a type that implements the trait:
impl<'a, T> Trait for &'a T
where
T: Trait,
{
fn hello(&self) -> u32 {
(*self).hello()
}
}
The piece of information that I'm missing is when shouldn't I implement this? Asked another way, why doesn't the compiler automatically implement this for me? Since it currently doesn't, I assume there must be cases where having this implementation would be disadvantageous.
when shouldn't I implement this? Asked another way, why doesn't the compiler automatically implement this for me? Since it currently doesn't, I assume there must be cases where having this implementation would be disadvantageous.
As an example, the Default trait immediately came to mind.
pub trait Default {
fn default() -> Self;
}
I could implement it for T, but there is no way to automatically implement it for &T.
The particular trait you are writing here only takes self by reference, and that is the only reason it is possible to write the additional implementation you did.
For this reason, taking the parameter to runner() by value is probably undesirable; you should instead be taking it by reference. This guideline can apply generally: if it is possible to implement the trait for a reference then rather than wondering “should I implement it?” you should wonder “why would I implement it?” for the only cases where you would use it should probably be altered to take the object by reference in the first place.