-
Notifications
You must be signed in to change notification settings - Fork 1.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Named impls #2251
Comments
Rust used to have named impls. (Ancient history; I'm having trouble even finding a proper record of when they were removed.) My memory is that they were removed, at least in part, because one could express such functionality via traits: instead of naming an impl and exporting it, you would instead define a trait, impl it, and export the trait (and then clients who wanted that implementation code would import the trait). You yourself even note that "this is similar to how traits currently work." Can you elaborate on what the advantage(s) are of your proposal over the status quo of using traits to express this? |
When crate A defines struct X, crate B defines trait Y, crate C defines impl Z as X for Y, you can use Z if you don't wanna make your own newtype struct and impl and so on. They're contextual impls, just like traits are contextual. |
@SoniEx2 Can't one run into coherence issues then? I.e. you have crate C adding its own named impl (of trait) Y for (struct) X, but then crate D can add its own conflicting impl of that same trait for the same struct? A typical example of where incoherence like that can cause a problem: Hashtables. Lets say the trait is Hash. If two different crates implement Hash in different ways for the same type, then passing a hashtable around between the two crates is going to cause them to use inconsistent hash-values when attempting to lookup entries for the same key. |
To be clear: I do not want to shoot down new ideas. I am just trying to remember, and document, the reasons for why this feature was removed in the first place, which is what is pushing me to construct examples such as the aforementioned incoherent hashtable... |
The named impl is part of the (generic) type. HashMap<usize(X)> is different from HashMap<usize(Y)>. It's similar to newtype structs in that aspect. |
This seems some kind of anonymous newtypes like proposal. I think its best solved via delegation of implementation instead: #1406 |
Keep in mind you'd be able to
|
btw: it's |
Will this allow something like this:
Did I understand it correctly? |
eh maybe we should just go for |
@pnkfelix isn't the idea with named impls that coherence issues all go away because you choose which impls to |
I think there should be an explicit syntax for choosing named impls? It should be implicit by default, except when you |
@durka I don't know how to answer your question, because @SoniEx2 is adding information to their presentation of named impls that does not match my mental model of them. E.g. as soon as the choice of named impl for Except that @SoniEx2 later claimed that one isn't juggling types. So I'm just going to say "I don't understand this proposal" and not attempt to suggest further interpretations of it. |
You know how you can have Well I'm proposing something along the lines of But the This means using the type in generic contexts carries additional information. In other words:
These 2 simple rules make the following code work as expected: mod a {
use ::something::SomeHash;
use ::something::SomeType;
pub fn do_thing(x: &SomeType) {
// may use x.hash() here.
}
}
mod b {
use ::something::SomeType;
use ::a::do_thing;
pub fn do_things() {
do_thing(SomeType::new());
}
} While still avoiding incoherence. (I'm trying to come up with a case where these 2 rules lead to incoherence, but it seems astronomically difficult.) |
I think it's harder to spec out than you think - but perhaps not impossible.
|
I think it's easier to spec out than you think. The only confusion seems to be the fact that we're talking about Adding new (default) impls for an existing type would be a breaking change. (Then again, adding new types is currently also a breaking change, so I don't see why this would be an issue.) I'll try to answer your questions anyway, reworded for less confusion:
|
Dupe of #493 I think. |
As of right now all impls are anonymous and public. I propose named impls and named public impls:
impl X as Y for Z
for a private implpub impl X as Y for Z
for a public implThis is similar to how traits currently work: you need to import them to use them.
With a non-pub impl, you can use it within your module. With a pub impl, you can use it outside your module. In any case, you need to explicitly import it with
use
. You can also import them from an external crate, but it follows the same rules - only available where youuse
them.Later we could also add
!pub impl Y for Z
if we want crate-wide, anonymous impls. (Sadly, since they're already public by default, we can't haveimpl Y for Z
andpub impl Y for Z
, except maybe in Rust 2.0.)The text was updated successfully, but these errors were encountered: