-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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
Adding impl Add<char> for String
breaks code (adding an impl leads to breakage due to deref coercions)
#51916
Comments
This is a misreading of the RFC. Practically all changes have the potential to stop existing code from compiling. The section that says implementing a non-fundamental trait is a minor change even explicitly spells out that "technically implementing any existing trait is a breaking change". What the RFC defines as "minor change" doesn't imply no breakage is possible, it's a middle ground between freezing the entire standard library forever and breaking the stability promise. It achives this balance by the policy that:
In this case the local disambiguration is not relying on Deref coercion (or doing other changes that force the Deref coercion to kick on even if the impl is added, e.g. The RFC goes on to say the following, which addresses your point about breaking a bunch of crates in practice:
Whether a given minor-but-breaking change is accepted is decided by the relevant team, based on considerations such as: how widespread the breakage is, how desirable the change is, how easily the broken crates can be updated, etc. |
I think part of the solution here should be implementing |
@rkruppe Sure, I'm fully aware that technically, everything can be a breaking change. And sorry if my initial comment sounded somewhat aggressive -- that was not intended! It's just that to me this was really unexpected. Maybe it's just me, but I wouldn't have guessed that adding such a harmless looking impl might cause breakage in harmless looking code.
This works for the I just don't understand why deref coercion is not done in this case. Is there a good reason why? I thought that maybe deref coercion could lead to ambiguity when multiple impls are available. But for one, some kind of ambiguity already exists which is resolved by using the first type that works (meaning, the working result with the fewest Then I thought: maybe when there two impls which expect So yeah again: why doesn't it happen for |
This currently doesn't build! This is discussed in rust-lang#51916
This happens outside the standard library too. For example, in jonhoo/fantoccini#196, a user reported that their code stopped compiling simply by virtue of adding a |
@jonhoo Do you know if there is tracking issue for this behavior? Possibility of library to break the code that uses this library sounds very bad. I've found mentioning of something related in https://std-dev-guide.rust-lang.org/breaking-changes/new-trait-impls.html#deref-coercion-breaks-when-a-new-impl-is-introduced, but this is std library dev guide, and they mentioning it as precaution in developing std library, not any regular crate. |
@UnkwUsr Unfortunately no, I don't know of one. |
I just prepared a PR to fix #38784. I wanted to add
Add<char>
andAddAssign<char>
impls for String. However, this breaks the following code:(Playground)
Apparently, without
Add<char>
, deref coercion is used to turn&String
into&str
. With the additional impl, deref coercion is no more and thus it results in:This is unexpected, because RFC 1105 says that adding an implementing for a non-fundamental trait is a minor change and thus should not require a major version bump. But if I were to submit a PR which adds
Add<char> for String
, it would probably not be merged, because it breaks a bunch of crates.a + &b
fora
andb
beingString
is widely used.I would have expected that either deref coercion wouldn't happen in cases where it influences the trait selection (in order to avoid this breakage) or that deref coercion would still happen if there is more than one
impl
. Since the former is not possible anymore, I think the latter is the solution to this problem.The third option (I can see) would be to change RFC 1105 and amend a section about this special case.
The text was updated successfully, but these errors were encountered: