-
Notifications
You must be signed in to change notification settings - Fork 138
Duplicate implementations with same name #211
Comments
I think this is a bug in the failure api and we should do something before stabilizing this. Not sure what yet but this shows the issue in isolation quite well: http://play.rust-lang.org/?gist=ae67b7566aca902a3e2dcf4c80533d7c&version=stable&mode=debug |
They both appear to have the same implementation as well? I agree that this looks like a bug to me unless I'm missing something. |
The main difference is that one can in theory be overridden by traits but I don't think that's useful. The only one that really is callable in the environments I encountered it is the |
Why isn't the inherent method overriding the trait method? I think this might've been a mistake originally, but the advantage of it (if it worked properly) is that you could call the method without importing the |
Here is the most minimal reproduction: https://play.rust-lang.org/?gist=cba966edf46fa867f820dd46628ba083&version=stable&mode=debug trait Foo {
fn f(&self) { }
}
impl Foo {
fn f(&self) { }
}
impl Foo for i32 {}
fn main() {
let x: &Foo = &42i32;
x.f();
} This is surprising! I expect this to call the inherent method on the EDIT: Expanded example to show that this works as expected for non trait object types: https://play.rust-lang.org/?gist=bea9908fa056c5620b939f2a487ba726&version=stable&mode=debug |
So what we only that method stays and the one on the trait itself goes away? That also removes the Sized restriction. The current behavior is really problematic. |
@mitsuhiko I agree the current behavior is problematic. I think the right immediate solution is to remove the However, it looks like method resolution for trait object types is also not behaving correctly, and that's a compiler bug that should be fixed, after which this method could (conceivably at least) be added back to the trait object without causing any error. |
I've opened a Rust issue to track fixing the underlying bug this has exposed: rust-lang/rust/issues/51402 |
@withoutboats yeah. it looks like the removal of the bound would be very helpful here. I do not think anyone implements either of those methods so it should be fairly safe to do. This however will mean that 0.1 also breaks backwards compat given the current crate setup. |
@mitsuhiko Urgh, you're right. The only breakage is if anyone is calling |
According to Niko, the issue isn't that inherent methods aren't getting precedent, but trait methods are treated as inherent methods on the trait object type. Surprising, possibly a mistake, but pretty much impossible to change now. Fortunately for us, I think that means it is backward compatible to remove the causes from To wit: mod foo {
pub trait Foo {
fn f(&self) { }
}
impl Foo for i32 { }
pub fn foo(x: &i32) -> &Foo { x }
}
fn main() {
let x = foo::foo(&0);
x.f();
} https://play.rust-lang.org/?gist=6440c2939ee8960b9c5928541531dd23&version=stable&mode=debug So I believe that removing the bound and the inherent method would fix this bug without being a breaking change 🎉 |
It does not look like we can remove the
However it's possible to just remove the trait methods and leave them on |
Oh right, I did have a good reason for the current set up after all (I just didn't know method resolution would behave so poorly). This is frustrating! |
Also when it's removed on the trait, then it no longer exists on |
Yes, you'd have to explicitly cast that into This is a place where trait objects just aren't working correctly and we need some design work to have an improved solution. |
I still think it makes sense to keep the |
What if we implemented It would be very unusual in my opinion to have this only on the trait object type. I think most people make this work using an impl like this. |
I am currently thinking of just removing the duplicates on the trait itself and break the ecosystem slightly. I do not see any reasonable workarounds. |
The main effect of that would be that some calls that previously permitted |
Another option would be to just rename the methods and deprecate the old ones.
|
I keep running into confusing issues because a few methods are implemented twice. For instance there is
Fail::causes
as default impl and then onimpl Fail
. This is making for ridiculous situations where I have this:But I think rust has no syntax to disambiguate the call. The only proposed thing is
Fail::causes(x)
which is picking theSelf: Sized
one which is the one I do not want. For the other impl there does not seem to be a syntax? In any case this is confusing and I wonder why we need these two implementations at all.The text was updated successfully, but these errors were encountered: