Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign upRFC: inherent trait implementation #2375
Conversation
This comment has been minimized.
This comment has been minimized.
|
cc @nikomatsakis, @aturon This RFC assumes that rust-lang/rust#48444 will be treated as a feature and not as a bug. |
This comment has been minimized.
This comment has been minimized.
|
To clarify: #2309 was postponed until we figure out the story for delegation. While you talk about it a bit in this new RFC, it's not clear what in this proposal changes the situation compared to when the lang team previous took up this question. Can you expand on your thinking here? |
This comment has been minimized.
This comment has been minimized.
|
I was under impression that the previous RFC was closed due to the lack of reaction from @Diggsey to add requested changes, and not postponed. (ctrl+f "postpone" yields zero results) While I agree that delegation RFC and inherent traits should be discussed together, in my opinion RFCs have orthogonal scopes and similar only in the end effect. As was shown in the text, delegation can be nicely composed with Yes, the new delegation RFC draft mentions inherent trait impls as a possible future extension, but I don't think that using |
This comment has been minimized.
This comment has been minimized.
|
@newpavlov I don't think that's an accurate assessment. The RFC was closed because:
ie. the lang team wanted a more general solution |
scottmcm
added
the
T-lang
label
Mar 28, 2018
This comment has been minimized.
This comment has been minimized.
|
@Diggsey @aturon |
This comment has been minimized.
This comment has been minimized.
|
@newpavlov Sorry for the delay, was out on vacation. Yes, I think it should probably be closed for the time being, especially since there's now a delegation RFC. Would be good to revisit after Rust 2018 ships! |
newpavlov
closed this
Apr 19, 2018
This comment has been minimized.
This comment has been minimized.
|
Where's the delegation RFC? My searches failed to find anything. |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
|
@aturon |
newpavlov
reopened this
Feb 14, 2019
cramertj
added
the
A-ergonomics
label
Feb 14, 2019
Centril
added
A-traits
A-attributes
A-resolve
labels
Feb 14, 2019
Manishearth
reviewed
Mar 28, 2019
|
|
||
| - Increased complexity of the language. | ||
| - Hides use of traits from users. | ||
|
|
This comment has been minimized.
This comment has been minimized.
Manishearth
Mar 28, 2019
Member
The older RFC was closed because it may be preferable to do a general purpose delegation RFC. This should be mentioned and preferably addressed.
This comment has been minimized.
This comment has been minimized.
newpavlov
Apr 2, 2019
Author
Firstly, I think that delegation and inherent impls are orthogonal to each other. Secondly, IIRC the functionality which may remove the need for inherent impls is listed as potential future extension of delegation RFC, i.e. the current delegation RFC does not solve the target issue of this proposal. And thirdly, I believe both proposals should be reviewed in parallel and pros and cons of both proposals should be weighted and compared, so I don't think "it may be preferable" is a good argument for closing competing proposals.
This comment has been minimized.
This comment has been minimized.
burdges
Apr 3, 2019
•
I do like inherent trait impls, but they are only a very minor paper cut, while delegation is extremely important, after say ATCs and const generics. Inherent trait impls are simply not worth risks of complicating delegation, so maybe the previous postponement should stand until the delegation conversation happens.
As an aside, I'd worry far more about the state of doc comments on trait impls than about inherent trait impls, as poorly documented impls create more headaches. I donno if rust-lang/rust#18701 ever got fixed, but if so then this may only be cultural now.
| ``` | ||
|
|
||
| Any questions regarding coherence, visibility or syntax can be resolved by | ||
| comparing against this expansion, although the feature need not be implemented |
This comment has been minimized.
This comment has been minimized.
Manishearth
Mar 28, 2019
Member
I think this should be explicitly specced out, especially since this expansion actually introduces an ambiguity in method calls.
|
|
||
| # Reference-level explanation | ||
| [reference-level-explanation]: #reference-level-explanation | ||
|
|
This comment has been minimized.
This comment has been minimized.
Manishearth
Mar 28, 2019
Member
This should be fleshed out, including:
- What impl blocks it can be applied to (can the trait be foreign?)
- Whether it works with
#[fundamental] - Does it error if you have an inherent method with the same name?
This comment has been minimized.
This comment has been minimized.
burdges
Mar 28, 2019
I'd think it should error if you have an inherent method with the same name, like if you had two inherent methods with the same name.
This comment has been minimized.
This comment has been minimized.
newpavlov
Apr 1, 2019
Author
What impl blocks it can be applied to (can the trait be foreign?)
Yes, it can. One of the main use-cases for inherent trait implementations is implementation of crates defined in external crates.
Whether it works with #[fundamental]
I am not sure why it should not, though I can't say I fully understand #[fundamental] semantics.
Does it error if you have an inherent method with the same name?
Initially I though it should error, but as I wrote below probably it may be better to issue a warning and shadow inherent trait methods by true inherent methods.
I will try to update the text based on your review! Thanks!
| [drawbacks]: #drawbacks | ||
|
|
||
| - Increased complexity of the language. | ||
| - Hides use of traits from users. |
This comment has been minimized.
This comment has been minimized.
Manishearth
Mar 28, 2019
Member
If this works the way I think it does, this actually changes our trait stability story, and that's a major drawback.
Currently, adding a defaulted method to a trait is not a major breaking change, at worst it will cause ambiguity errors, so it's considered minor.
Now, a dependency can add a method to a trait you #[inherent] impl, which can clash with a method of your own, causing your build to fail in a way that requires you to change your API to fix. We're largely okay with builds failing due to new ambiguities (clashing method names across traits, adding something to a module that's glob imported, etc) and such things are categorized as minor, which basically means it's fine to do as long as the fallout isn't too much. With this RFC, adding a defaulted method has the potential to break a library user in a way that requires them to rename a method in their public API, causing a breaking change for them.
This should be explored and addressed in this RFC, and as a bare minimum should be called out in this section.
(One "fix" is to only allow local traits)
This comment has been minimized.
This comment has been minimized.
Havvy
Mar 28, 2019
Contributor
Another fix is to list out the method names that are inherent, although that becomes quite a burden for e.g. iterator methods.
This comment has been minimized.
This comment has been minimized.
burdges
Mar 28, 2019
I'm unsure if the existing situation should be classified as so minor because you interact with many types almost exclusively through their traits. As an example, there are definitely traits with a new() method that defies the convention of being inherent new(), so those traits adding new() created exactly the same breakage you describe here.
As a fix, I'd suggest #[inherent] being a method attribute for items inside an impl, so
impl TraitWIthBadMethodNames for MyType {
fn new() -> Self { .. } // Not inherent
#[inherent]
fn new_plus() -> Self; // Inherent but default body used
#[inherent]
fn foo() { .. } // Inherent with body supplied here
}
And #[inherent] applied to the impl is equivalent to it being applied to all methods and associated types and constants.
This comment has been minimized.
This comment has been minimized.
Manishearth
Mar 28, 2019
•
Member
As an example, there are definitely traits with a new() method that defies the convention of being inherent new(), so those traits adding new() created exactly the same breakage you describe here.
Yes, but this breakage is easily fixed by using UFCS. This is not true for breakage caused in the world of #[inherent].
The "minor" terminology comes from the API evolution RFC, such changes may cause crates to stop compiling, however:
- This can be fixed with a trivial change local to the crate
- The fix does not break upstream crates
Without this notion of "minor" being allowed, crates wouldn't be able to add anything new (types, traits, functions, or methods) without it being considered a breaking change.
Furthermore, the API evolution RFC mentions in the trait method case that you should check to ensure the fallout isn't too great; which is where your new() example falls short: a trait adding a new() method would probably have lots of fallout.
In other words, when I use the term "minor" here, I'm using a precisely defined term from another RFC. Whether or not it is actually "minor" is irrelevant, I'm talking about what we do and don't consider breaking, which we have specced in terms of this major/minor categorization.
This comment has been minimized.
This comment has been minimized.
newpavlov
Apr 1, 2019
•
Author
Will it be possible to implement shadowing of inherent trait methods by true inherent methods? Compiler will warn on clashing inherent names while building crate which uses #[inherent], but will use true inherent method by default and for trait method you will have to use explicit Trait::foo(value). This way we will avoid code breakage on "minor" upstream changes.
Though I think in practice such collisions should be extremely rare.
This comment has been minimized.
This comment has been minimized.
burdges
commented
Mar 28, 2019
|
How are polymorphic traits handled? I'd presume
works roughly like
Yet, how should separate
We'd likely want roughly
|
This comment has been minimized.
This comment has been minimized.
|
@burdges |
newpavlov commentedMar 27, 2018
•
edited
Continuation of #2309.
Fixes: #1880,#1971
This RFC allows us to write the following code:
Which allows methods from
Bartrait to be used onFooinstances without havingBarin the scope.Rendered