Conflicting implementation error with single implementation - rust

In the following program, PartialOrd and PartialEq are implemented for all types that have the trait Area. This way, when defining Rectangle, I only need to implement Area to have < operator working.
trait Area {
fn get_area(&self) -> i32;
}
impl<T: Area> PartialOrd for T {
fn partial_cmp(&self, other: &T) -> Option<std::cmp::Ordering> {
self.get_area().partial_cmp(&other.get_area())
}
}
impl<T: Area> PartialEq for T {
fn eq(&self, other: &T) -> bool {
self.get_area() == other.get_area()
}
}
struct Rectangle {
width: i32,
height: i32
}
impl Area for Rectangle {
fn get_area(&self) -> i32 {
self.width * self.height
}
}
fn main() {
let r1 = Rectangle { width:10, height:10 };
let r2 = Rectangle { width:11, height:9 };
if r1 > r2 {
println!("r1 is bigger.")
} else {
println!("r2 is bigger.")
}
}
However, I am getter the following error:
error[E0119]: conflicting implementations of trait `std::cmp::PartialOrd<&_>` for type `&_`:
--> src/main.rs:23:1
|
17 | impl<T: Area> PartialOrd<T> for T {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: conflicting implementation in crate `core`:
- impl<A, B> std::cmp::PartialEq<&B> for &A
where A: std::cmp::PartialEq<B>, A: ?Sized, B: ?Sized;
= note: downstream crates may implement trait `Area` for type `&_`
The documentation for E0119 gives an example where the author writes two implementations that overlap. But there is only one implementation is this case. Even the format of the error message is strange, as it starts an enumeration of implementations (with a dash) that has only one entry. What does it mean?
I am also getting this other error:
error[E0210]: type parameter `T` must be used as the type parameter for some local type (e.g., `MyStruct<T>`)
--> src/main.rs:23:6
|
23 | impl<T: Area> PartialEq<T> for T {
| ^ type parameter `T` must be used as the type parameter for some local type
|
= note: only traits defined in the current crate can be implemented for a type parameter
Again, the documentation for E0210 gives examples where the type parameter is not covered by a local type, but T is limited to Area everywhere in this case. What does it mean?

There is indeed more than one implementation in this case as pointed out in the compiler error message:
impl<A, B> std::cmp::PartialEq<&B> for &A
where A: std::cmp::PartialEq<B>, A: ?Sized, B: ?Sized;
Your impl is bound to Area. But the core library's implementation is more generic and can cover any &A including those which &A: Area.
Basically you shouldn't implement a trait foreign to your crate such as PartialOrd for any type that could be potentially foreign to your crate. Even when you are bounding them to Area they can still be defined in other crates (foreign to yours) using your crate.
It seems to me that you want to say any type which implements Area can/must implement PartialOrd and PartialEq as well and there would be a default implementation of those functions. The following solution forces the implementation of those traits and provides the default functions. Though the implementors would need to select and use the provided functions as an additional local step:
struct Rectangle {
width: i32,
height: i32
}
trait Area: PartialOrd+PartialEq {
fn get_area(&self) -> i32;
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
self.get_area().partial_cmp(&other.get_area())
}
fn eq(&self, other: &Self) -> bool {
self.get_area().eq(&other.get_area())
}
}
impl Area for Rectangle {
fn get_area(&self) -> i32 {
self.width * self.height
}
}
impl PartialOrd for Rectangle {
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
<Self as Area>::partial_cmp(self, other)
}
}
impl PartialEq for Rectangle {
fn eq(&self, other: &Self) -> bool {
<Self as Area>::eq(self, other)
}
}
fn main() {
let r1 = Rectangle { width:10, height:10 };
let r2 = Rectangle { width:11, height:9 };
if r1 > r2 {
println!("r1 is bigger.")
} else {
println!("r2 is bigger.")
}
}

The rust compiler can't guarantee that another crate won't implement Area on a & type. This would cause a conflicting PartialOrd implementation. Even though in this particular example it might be impossible, the compiler can't make that judgement.
You can only implement foreign traits on concrete local types. Constraining a generic type to implement a local trait doesn't guarantee that the local trait can only be implemented on local types. If Area is later implemented on foreign type Foo, that would cause your crate to implement foreign trait PartialOrd on foreign type Foo. The common workaround for this is something like:
struct LocalArea<T: Area> {
value: T,
}
impl<T: Area, U: Area> PartialEq<LocalArea<T>> for LocalArea<U> {
...
}
This syntax of using a local struct that contains a generic T is commonly referred to as the Newtype Pattern.

Related

Weird conflicting implementation in rust

I'm making a tiny GUI library in Rust for practice. Minimal reproducible example of my problem is as follows:
/// Trait for rendering engines
pub trait Renderer { /* ... */ }
pub trait Element<Win: Renderer> {
fn paint(&self);
fn width(&self) -> u32;
fn height(&self) -> u32;
}
/// "Composed" element is element, that consists of multiple sub-elements, eg. button consists of frame and laconveniences a covinience trait, because implementing `Element` directly might be cumbersome.
pub trait ElComposed<Win: Renderer> {
/// Returns the top-level subelement of self
fn main_el(&self) -> Box<dyn Element<Win>>;
}
impl<T: ElComposed<Win>, Win: Renderer> Element<Win> for T {
fn paint(&self) { self.main_el().paint() }
fn width(&self) -> u32 { self.main_el().width() }
fn height(&self) -> u32 { self.main_el().height() }
}
/// Element displaying just a circle
pub struct Circle;
/// Implementing `Element` trait directly on `Circle`
impl<Win: Renderer> Element<Win> for Circle {
fn paint(&self) { todo!() }
fn width(&self) -> u32 { todo!() }
fn height(&self) -> u32 { todo!() }
}
Link to playground
Because Element trait contains quite a few methods, it may be time-consuming to implement directly, so, as you can see in the code, I added the ElComposed convenience trait to make it easier to implement for elements consisting of multiple sub-elements (eg. button consists of a frame and label).
But now, when I implement the Element trait directly (impl<Win: Renderer> Element<Win> for Circle in the code above), the code doesn't compile:
error[E0119]: conflicting implementations of trait `Element<_>` for type `Circle`
|
21 | impl<T: ElComposed<Win>, Win: Renderer> Element<Win> for T {
| ---------------------------------------------------------- first implementation here
...
31 | impl<Win: Renderer> Element<Win> for Circle {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Circle`
|
= note: downstream crates may implement trait `ElComposed<_>` for type `Circle`
But downstream crates cannot implement trait ElComposed for Circle, because both traits are in my crate. So why does this error occur and how can I fix it?

Is it possible to implement `PartialEq` for a trait reference that returns `true` for implementations instances that have the same inner content? [duplicate]

Editor's note: This code example is from a version of Rust prior to 1.0 and is not syntactically valid Rust 1.0 code. Updated versions of this code produce different errors, but the answers still contain valuable information.
It seems like we cannot test for equality in the following case. Why is this? Is there a workaround? (I am using Rust 0.11).
trait A: PartialEq {}
#[deriving(PartialEq)]
enum T {Ta, Tb}
impl A for T {}
fn main() {
assert!(Ta == Ta);
assert!(Ta != Tb);
assert!(some_fn(&Ta, &Ta));
assert!(!some_fn(&Ta, &Tb));
}
fn some_fn(an_a: &A, another_a: &A) -> bool {
an_a == another_a
// ERROR ^~~~~~~~~~~~ binary operation `==` cannot be applied to type `&A`
}
fn another_fn(an_a: &A + PartialEq, another_a: &A + PartialEq) -> bool {
// ERROR: ^~~~~~~~~ only the builtin traits can be used as closure or object bounds
an_a == another_a
}
With help from Vladimir Matveev, I figured out how to use Any to downcast my trait to a concrete type and test the resulting value for equality:
// `Any` allows us to do dynamic typecasting.
use std::any::Any;
trait A {
// An &Any can be cast to a reference to a concrete type.
fn as_any(&self) -> &dyn Any;
// Perform the test.
fn equals_a(&self, _: &dyn A) -> bool;
}
#[derive(Debug, PartialEq)]
enum T {
Ta,
Tb,
}
// Implement A for all 'static types implementing PartialEq.
impl<S: 'static + PartialEq> A for S {
fn as_any(&self) -> &dyn Any {
self
}
fn equals_a(&self, other: &dyn A) -> bool {
// Do a type-safe casting. If the types are different,
// return false, otherwise test the values for equality.
other
.as_any()
.downcast_ref::<S>()
.map_or(false, |a| self == a)
}
}
fn main() {
assert_eq!(T::Ta, T::Ta);
assert_ne!(T::Ta, T::Tb);
assert!(some_fn(&T::Ta, &T::Ta));
assert!(!some_fn(&T::Ta, &T::Tb));
}
fn some_fn(an_a: &dyn A, another_a: &dyn A) -> bool {
// It works!
an_a.equals_a(another_a)
}
Here is the definition of the PartialEq trait:
pub trait PartialEq<Rhs = Self>
where
Rhs: ?Sized,
{
fn eq(&self, other: &Rhs) -> bool;
fn ne(&self, other: &Rhs) -> bool { ... }
}
Note the Self parameter type. This means that eq() and ne() methods accept a parameter of the same type as implementor. For example:
impl PartialEq for i32 {
fn eq(&self, other: &i32) -> bool { ... }
}
impl PartialEq for String {
fn eq(&self, other: &String) -> bool { ... }
}
Note how type of other changes to reflect the type PartialEq is implemented for.
This is the problem. In trait objects, the actual type is erased and unavailable at runtime. This means that it is impossible to obtain a reference to a concrete type from a trait object; in particular, you can't go from &A to &T in your example.
This means that it is impossible to call methods accepting or returning the Self type on trait objects. Indeed, these methods always require a concrete type, but if you have only a trait object, there is no concrete type, and there is no way such method could work in any sensible way.
In certain cases of trait objects, you wish to compare them based on some properties exposed via the trait. You can achieve this by implementing methods on the trait type itself:
trait A {
fn id(&self) -> i32;
}
impl PartialEq for dyn A + '_ {
fn eq(&self, other: &Self) -> bool {
self.id() == other.id()
}
}
impl Eq for dyn A + '_ {}
fn some_fn(an_a: &dyn A, another_a: &dyn A) -> bool {
an_a == another_a
}
This doesn't directly address the original case which wants to delegate back to the implementation of PartialEq of the underlying type, but you can combine the existing solution:
impl PartialEq for dyn A + '_ {
fn eq(&self, other: &Self) -> bool {
self.equals_a(other)
}
}
See also:
Why would I implement methods on a trait instead of as part of the trait?

Create a generic struct with Option<T> without specifying T when instantiating with None

I have a
struct Foo<T>
where
T: // ... some complex trait bound ...
{
a: Bar,
b: Option<T>,
}
When attempting to instantiate the struct with a b: None the compiler complains that it cannot infer the type and requires a type hint e.g. via the turbofish syntax. That is onerous on the caller because they will have to find a type that fulfills the trait bounds and import it despite not caring about that optional functionality.
I think what I am looking for would be a bottom type that automatically fulfills any trait bounds but cannot be instantiated so that None::<Bottom> could be used, but I have not found such a type in the documentation.
There's a feature in the works that allows specifying the never type as !. This is not present in stable Rust, so you need to use a nightly and a feature flag:
#![feature(never_type)]
fn thing<T>() -> Option<T> {
None
}
fn main() {
thing::<!>();
}
However, this doesn't work for your case yet (this is part of the reason that it's unstable):
#![feature(never_type)]
trait NothingImplementsMe {}
fn thing<T>() -> Option<T>
where T: NothingImplementsMe,
{
None
}
fn main() {
thing::<!>();
}
error[E0277]: the trait bound `!: NothingImplementsMe` is not satisfied
--> src/main.rs:12:5
|
12 | thing::<!>();
| ^^^^^^^^^^ the trait `NothingImplementsMe` is not implemented for `!`
|
= note: required by `thing`
The very first unresolved question on the tracking issue is:
What traits should we implement for !?
Since this feature is both unstable and doesn't do what you want, you may want to consider creating your own bespoke "bottom" type:
trait AlmostNothingImplementsMe {
fn foo();
}
struct Nope;
impl AlmostNothingImplementsMe for Nope {
fn foo() { unimplemented!() }
}
fn thing<T>() -> Option<T>
where T: AlmostNothingImplementsMe,
{
None
}
fn main() {
thing::<Nope>();
}
To improve the UX of this, I'd suggest creating a builder of some type that starts you off with the faux-bottom type:
mod nested {
pub trait AlmostNothingImplementsMe {
fn foo();
}
pub struct Nope;
impl AlmostNothingImplementsMe for Nope {
fn foo() { unimplemented!() }
}
pub fn with_value<T>(t: T) -> Option<T>
where T: AlmostNothingImplementsMe,
{
Some(t)
}
pub fn without_value() -> Option<Nope> {
None
}
}
fn main() {
nested::without_value();
}
You can see this similar pattern in crates like Hyper, although it boxes the concrete type so you don't see it from the outside.
One option to avoid the need to the turbofish operator is to have a type alias:
trait MyTrait {}
impl MyTrait for () {}
struct Foo<T: MyTrait> {
i: isize,
o: Option<T>,
}
type Bar = Foo<()>;
fn main() {
let foo_default = Bar { i: 1, o: None };
}
I used () as the default for simplicity, but ! (when available) or your own bottom type as in #Shepmaster's answer may be better.
A constructor function could also work if you don't mind Foo::new_default(i) or similar.

Is there a way to implement a trait on top of another trait? [duplicate]

This question already has answers here:
I implemented a trait for another trait but cannot call methods from both traits
(3 answers)
Closed 5 years ago.
I am trying to create a base trait that will implement other operator traits (Add, Subtract, Multiply, Divide, etc...) for me.
This fails to compile, it looks like an issued with Sized, but even when Measurement is set to require Sized it does not work. Is this even possible?
use std::ops::Add;
#[derive(Copy, Clone, Debug)]
struct Unit {
value: f64,
}
impl Unit {
fn new(value: f64) -> Unit {
Unit { value: value }
}
}
trait Measurement: Sized {
fn get_value(&self) -> f64;
fn from_value(value: f64) -> Self;
}
impl Measurement for Unit {
fn get_value(&self) -> f64 {
self.value
}
fn from_value(value: f64) -> Self {
Unit::new(value)
}
}
// This explicit implementation works
/*
impl Add for Unit {
type Output = Unit;
fn add(self, rhs: Unit) -> Unit {
let a = self.get_value();
let b = rhs.get_value();
Unit::from_value(a + b)
}
}
*/
// This trait implementation does not
impl Add for Measurement {
type Output = Self;
fn add(self, rhs: Self) -> Self {
let a = self.get_value();
let b = rhs.get_value();
Self::from_value(a + b)
}
}
fn main() {
let a = Unit::new(1.5);
let b = Unit::new(2.0);
let c = a + b;
println!("{}", c.get_value());
}
(playground)
error[E0277]: the trait bound `Measurement + 'static: std::marker::Sized` is not satisfied
--> src/main.rs:42:6
|
42 | impl Add for Measurement {
| ^^^ `Measurement + 'static` does not have a constant size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `Measurement + 'static`
error[E0038]: the trait `Measurement` cannot be made into an object
--> src/main.rs:42:6
|
42 | impl Add for Measurement {
| ^^^ the trait `Measurement` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
error[E0038]: the trait `Measurement` cannot be made into an object
--> src/main.rs:43:5
|
43 | type Output = Self;
| ^^^^^^^^^^^^^^^^^^^ the trait `Measurement` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
error[E0038]: the trait `Measurement` cannot be made into an object
--> src/main.rs:45:5
|
45 | fn add(self, rhs: Self) -> Self {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Measurement` cannot be made into an object
|
= note: the trait cannot require that `Self : Sized`
The issue is not with Sized. The syntax you're looking for is:
impl<T: Measurement> Add for T { ... }
instead of:
impl Add for Measurement { ... }
Because the right-hand side of the for must be an object, not a trait, however a type parameter constrained to a trait (i.e. a T required to be Measurement) is valid.
Now your code still won't compile. You will get the following:
error: type parameter T must be used as the type parameter for some
local type (e.g. MyStruct<T>); only traits defined in the current
crate can be implemented for a type parameter [E0210]
The issue here is of a totally different kind. I'm not sure it's related to the question any more but I'll still explain what's going on. When you write an impl for Add to any T which is Measurement, you open the possibility that a type would already implement Add on its own, and would also implement Measurement elsewhere. Imagine if you wanted to implement Measurement on u8 (which is silly but possible): which impl should Rust choose for Add? The original std impl or your Measurement impl? (in-depth discussion about this issue)
Right now Rust plainly forbids an impl if it is not at least 1) your own trait or 2) your own type (where "own" formally means, in the crate you're writing your impl). This is why you can write impl Add for Unit: because you own Unit.
The easiest solution would be to give up and implement Add independently for each type you're planning to make Unit. Say your crate defines Inches and Centimeter, each one would have its own Add impl. If the code is insultingly similar, and you feel you broke DRY, leverage macros. Here is how the std crate does it:
macro_rules! add_impl {
($($t:ty)*) => ($(
#[stable(feature = "rust1", since = "1.0.0")]
impl Add for $t {
type Output = $t;
#[inline]
fn add(self, other: $t) -> $t { self + other }
}
forward_ref_binop! { impl Add, add for $t, $t }
)*)
}
You cannot implement a trait for a trait, you implement a trait only for types.
But you can implement a trait for a generic type that implement a certain traits (trait bounds).
Something like this:
impl<T : Measurement> Add<T> for T {
type Output = T;
fn add(self, rhs: Self) -> T {
let a = self.get_value();
let b = rhs.get_value();
T::from_value(a + b)
}
}
Unfortunately you can do this only for traits defined in your crate (its called coherence), so you cannot do that for the std Add trait because it's defined in the std crate, not in yours.
I think you might need to define some macros to do what you want to do.
Here's a working version with macros, as suggested:
use std::ops::Add;
#[derive(Copy, Clone, Debug)]
struct Unit {
value: f64,
}
impl Unit {
fn new(value: f64) -> Unit {
Unit { value: value }
}
}
trait Measurement: Sized {
fn get_value(&self) -> f64;
fn from_value(value: f64) -> Self;
}
impl Measurement for Unit {
fn get_value(&self) -> f64 {
self.value
}
fn from_value(value: f64) -> Self {
Unit::new(value)
}
}
macro_rules! add_impl {
($($t:ty)*) => ($(
impl Add for $t {
type Output = $t;
fn add(self, other: $t) -> $t {
let a = self.get_value();
let b = other.get_value();
let r = a + b;
Self::from_value(r)
}
}
)*)
}
add_impl! { Unit }
fn main() {
let a = Unit::new(1.5);
let b = Unit::new(2.0);
let c = a + b;
println!("{}", c.get_value());
}

Enforce Eq check on trait

Suppose the following objects:
pub struct MyStruct<T>{
items: Vec<T>
}
pub impl<T> MyStruct<T> {
pub fn new() -> MyStruct {
MyStruct{ items::new(); }
}
pub fn add(&mut self, item: T) where T : Eq {
self.items.push(item);
}
}
pub trait C {}
pub struct Another {
mystruct: MyStruct<Box<C>>
}
pub impl Another {
pub fn exec<C>(&mut self, c: C) where C: Eq + C {
self.mystruct.add(c);
}
}
On exec I'm enforcing that C also is Eq, but I'm receiving the following error:
error: the trait `core::cmp::Eq` is not implemented for the type `C`
I had to make
pub impl<T> MyStruct<T>
instead of
pub impl<T : Eq> MyStruct<T>
because since C is a trait I cant enforce Eq when using MyStruct::new, so I left the check for the type guard on the function. What's happening here?
Let’s look at the relevant definitions for Eq:
pub trait Eq: PartialEq<Self> {
…
}
pub trait PartialEq<Rhs: ?Sized = Self> {
fn eq(&self, other: &Rhs) -> bool;
…
}
Now consider MyStruct<Box<C>>: the type that it wants to implement Eq is Box<C>, a boxed trait object. To implement Eq, Box<C> must first implement PartialEq<Box<C>>, like this:
impl PartialEq for Box<C> {
fn eq(&self, other: &Box<C>) -> bool;
}
impl Eq for Box<C> { }
That is, you must be able to compare an arbitrary Box<C> with any other arbitrary Box<C>. The boxed trait objects that you are comparing could be of different concrete types, here. Thus you need to write this implementation manually. In such cases, you will typically want the trait to include some way of normalising the form of the object into a concrete, comparable type; for some types this is obvious; if AsRef<T> was to have a PartialEq implementation added, the implementation to add would be fairly obvious:
impl<T: PartialEq> PartialEq for AsRef<T> {
fn eq(&self, other: &AsRef<T>) -> bool {
self.as_ref() == other.as_ref()
}
}
(Note also that if C implements PartialEq, Box<C> does, so such implementations as we’re discussing should go on the unboxed trait object, not on the boxed trait object.)
Quite often, however, there is not an obvious and simple implementation. There are a few approaches you could take:
Convert the objects (potentially expensively, though ideally cheaply) into some base type, e.g. a String which can then be compared;
Give up;
Constrain C to 'static types and use some fancy Any magic to make it so that it uses the base type’s PartialEq implementation, returning false if the two trait objects are not of the same concrete type. This one is a fairly useful one, so I’ll give some code for it:
#![feature(core)]
use std::any::{Any, TypeId};
use std::mem;
fn main() { }
trait PartialEqFromC {
fn eq_c(&self, other: &C) -> bool;
}
impl<T: PartialEq + Any + C> PartialEqFromC for T {
fn eq_c(&self, other: &C) -> bool {
if other.get_type_id() == TypeId::of::<Self>() {
self == unsafe { *mem::transmute::<&&C, &&Self>(&other) }
} else {
false
}
}
}
trait C: Any + PartialEqFromC {
}
impl PartialEq for C {
fn eq(&self, other: &C) -> bool {
self.eq_c(other)
}
}
Note that this example depends on the unstable feature core for Any.get_type_id and is thus tied to nightly only; this can be worked around by duplicating that definition from the Any trait into a new supertrait of C and could also be simplified by mopafying the C trait.

Resources