rustc shows downstream crates may implement trait - rust

pub mod traits {
pub trait Foo<T> {}
pub trait Bar<T> {}
impl<T, U: Foo<T>> Bar<T> for U {}
}
pub struct Test {}
impl<T> traits::Bar<T> for Test {}
fn main() {}
rust playground
it shows :
Compiling playground v0.0.1 (/playground)
error[E0119]: conflicting implementations of trait `traits::Bar<_>` for type `Test`
--> src/main.rs:8:1
|
5 | impl<T, U: Foo<T>> Bar<T> for U {}
| ------------------------------- first implementation here
...
8 | impl<T> traits::Bar<T> for Test {}
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Test`
|
= note: downstream crates may implement trait `traits::Foo<_>` for type `Test`
For more information about this error, try `rustc --explain E0119`.
error: could not compile `playground` due to previous error
is that a feature or a bug?

There is a potential collision:
impl<T, U: Foo<T>> Bar<T> for U {}
This means that all types that implement Foo also implement Bar.
This, however:
impl<T> traits::Bar<T> for Test {}
means that Test implements Bar. The problem here is that Test could implement Foo for T types not yet known in this crate.
Like, if another crate defines a type MyStruct, and implements Foo<MyStruct>:
struct MyStruct {}
impl Foo<MyStruct> for Test {}
that's perfectly fine from the standpoint of the other crate. It creates the ambiguity, though, that the compiler now doesn't know which implementation of Bar<MyStruct> should use:
impl<MyStruct, U: Foo<MyStruct>> Bar<MyStruct> for U {} with U being Test
impl<T> traits::Bar<T> for Test {} with T being MyStruct
To avoid this ambiguity, the compiler disallows you from writing that code in the first place.

Related

Why does MyEnum<T> requires T to implement the Clone trait to derive the Clone trait when T is never cloned? [duplicate]

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.

Impl for type with parameter that can be From<&'a str> and FromStr

Consider following piece of rust code:
use std::str::FromStr;
use std::convert::From;
trait Bar {
fn baz();
}
struct Foo<A> {
v: A
}
impl<A: FromStr> Bar for Foo<A> {
fn baz() {
todo!()
// code that somewhat handles conversion error possibly generated by parse()
}
}
impl<'a, A: From<&'a str>> Bar for Foo<A> {
fn baz() {
todo!()
// code that doesn't have to worry about conversion errors, since from() cannot fail
}
}
It produces error about conflicting declarations. Namely:
error[E0119]: conflicting implementations of trait `Bar` for type `Foo<_>`
--> src/lib.rs:19:1
|
12 | impl<A: FromStr> Bar for Foo<A> {
| ------------------------------- first implementation here
...
19 | impl<'a, A: From<&'a str>> Bar for Foo<A> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Foo<_>`
For more information about this error, try `rustc --explain E0119`.
error: could not compile `playground` due to previous error
What I want to do is described in comments. For As that can be created from &str without error I want different behaviour than for ones that require error handling. But somewhat rustc considers these declarations conflicting. Is it possible to achieve what I am looking for in current rust? If so, how?
link to playground with above code

Error when trying to implement a function declared in a supertrait

I'm trying to implement a trait that has a supertrait, like so:
trait A {
fn do_a(&self);
}
trait B: A {
fn do_b(&self);
}
struct S {}
impl B for S {
fn do_a(&self) {}
fn do_b(&self) {}
}
When I run cargo build I get these compiler errors:
error[E0407]: method `do_a` is not a member of trait `B`
--> src/example.rs:12:5
|
12 | fn do_a(&self) {}
| ^^^^^^^^^^^^^^^^^ not a member of trait `B`
error[E0277]: the trait bound `example::S: example::A` is not satisfied
--> src/example.rs:11:6
|
5 | trait B: A {
| - required by this bound in `example::B`
...
11 | impl B for S {
| ^ the trait `example::A` is not implemented for `example::S`
I keep re-reading about supertraits, but I'm having trouble understanding this error.
The first error seems to contradict what trait B: A is telling the program to do.
The second error seems to contradict that the implementation of do_a(&self) {} satisfies A.
What am I missing here? Is my mental model wrong, or is my code missing some necessary boilerplate, or both?
I believe that the syntax is more about bounding the type (e.g. a type T that implements B must necessarily implement A) than inheritance in the object-oriented sense. If you write out the impls separately it compiles fine:
trait A {
fn do_a(&self);
}
trait B: A {
fn do_b(&self);
}
struct S {}
impl A for S {
fn do_a(&self) {}
}
impl B for S {
fn do_b(&self) {}
}
Playground
N.B. that if you remove the impl for A the code no longer compiles, the constraint that an impl of B must also impl A is no longer satisfied.

Shouldn't Arc<T> implement Clone for any T?

On the code below, you can see that I'm trying to clone a: A where A derives Clone
use std::sync::Arc;
pub trait S{}
struct B{
}
impl S for B{
}
#[derive(Clone)]
struct A<T: ?Sized>{
a: Arc<Box<T>>
}
fn main() {
let a: A<dyn S> = A{
a: Arc::new(Box::new(B{}))
};
a.clone();
}
Playground
However I get this error:
Error:
Compiling playground v0.0.1 (/playground)
error[E0599]: the method `clone` exists for struct `A<dyn S>`, but its trait bounds were not satisfied
--> src/main.rs:22:7
|
3 | pub trait S{}
| ----------- doesn't satisfy `dyn S: Clone`
...
13 | struct A<T: ?Sized>{
| -------------------
| |
| method `clone` not found for this
| doesn't satisfy `A<dyn S>: Clone`
...
22 | a.clone();
| ^^^^^ method cannot be called on `A<dyn S>` due to unsatisfied trait bounds
|
= note: the following trait bounds were not satisfied:
`dyn S: Clone`
which is required by `A<dyn S>: 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`
Shouldn't A implement Clone for any T, since the clone on A would simply call A {a: old_a.clone()} which since it's an Arc it always implement clone?
Shouldn't it be guaranteed that A implements Clone because of #[derive(Clone)]?
This is an issue with the implementation of the derive macro for Clone. It doesn't work with structs containing generic types that don't implement clone themselves: https://github.com/rust-lang/rust/issues/41481
In that case you'll have to implement Clone manually, which is, as you say, pretty easy.
impl<T> Clone for A<T> {
fn clone(&self) -> A<T> {
A { a: self.a.clone() }
}
}

Can not implement io::Read for a custom trait

I want to implement the std::io::Read trait for my custom trait. This is my try:-
use std::io::Read;
trait Bar {
fn foo(&self);
}
impl<T: Bar> Read for T {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
Ok(0)
}
}
Playground
Error:-
Compiling playground v0.0.1 (/playground)
error[E0119]: conflicting implementations of trait `std::io::Read` for type `&mut _`:
--> src/lib.rs:7:1
|
7 | impl<T: Bar> Read for T {
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `std`:
- impl<R> std::io::Read for &mut R
where R: std::io::Read, R: ?Sized;
= note: downstream crates may implement trait `Bar` for type `&mut _`
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
--> src/lib.rs:7:6
|
7 | impl<T: Bar> Read for T {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
error: aborting due to 2 previous errors
This is currently not allowed, as explained in the note:
= note: downstream crates may implement trait `Bar` for type `&mut _`
You are trying to implement Read for all types that implement Bar, but you can't guarantee that all implementations of Bar (present or future) don't - or won't - implement Read already. For example, a user of your crate might implement Bar for one of their own types.
Another problem is explained in the second error:
= note: implementing a foreign trait is only possible if at least one of the types for which is it implemented is local
= note: only traits defined in the current crate can be implemented for a type parameter
You are only allowed to implement a trait if either the trait is defined in your crate (Read is not) or if the type that you are implementing it for is defined in your crate. That means you can't implement Read for T, because T is literally any type, including arbitrary types from other crates.
A workaround for this would be to add a function that exposes a Read implementation from an arbitrary T: Bar:
use std::io::Read;
trait Bar {
fn foo(&self);
fn as_reader(&self) -> BarRead<&Self> {
BarRead(self)
}
}
pub struct BarRead<T>(T);
impl<T: Bar> Read for BarRead<T> {
fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
Ok(0)
}
}

Resources