I'm coming from C++ and I'm running into issues with generic trait implemntations.
I'm trying to build a geometry library that does some operation on both polygons and open paths, but behaves slightly different for each case. Ideally I want one implementation of a geometry operation as a method which can query the object it's operating on for a flag.
I also want this library to work on any object that can look like a polygon or open path, not just my data types, so I want traits for PolygonLike and OpenPathLike that can be implemented on any type. I have code that looks like this:
trait Clipable {
fn closed() -> bool;
fn geom_func(&self) {
if Self::closed() {
println!("closed");
} else {
println!("open");
}
}
}
trait PolygonLike {}
trait OpenPathLike {}
struct Point(f64, f64);
type PointVec = Vec<Point>;
struct Poly(PointVec);
struct Path(PointVec);
impl PolygonLike for Poly {}
impl OpenPathLike for PointVec {}
impl<T> Clipable for T
where
T: PolygonLike,
{
fn closed() -> bool {
true
}
}
impl<T> Clipable for T
where
T: OpenPathLike,
{
fn closed() -> bool {
false
}
}
fn main() {
let pg = Poly(PointVec::new());
let op = Path(PointVec::new());
pg.geom_func();
op.geom_func();
}
The code fails to compile with:
error[E0119]: conflicting implementations of trait `Clipable`:
--> src/main.rs:28:1
|
24 | impl<T> Clipable for T where T: PolygonLike {
| ------------------------------------------- first implementation here
...
28 | impl<T> Clipable for T where T: OpenPathLike {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
I have read elsewhere that the where clause isn't used by the conflict checker, even though no type implements both PolygonLike and OpenPathLike.
I get that this is because a consumer could just implement both those traits and break the library. What I don't get is how I can work around this.
I have seen other posts where people have used newtypes to limit generic implementations, but I can't figure out how to make that work for my scenario.