Skip to content
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

permit negative impls for non-auto traits #68004

Merged
merged 14 commits into from
Mar 26, 2020

Conversation

nikomatsakis
Copy link
Contributor

@nikomatsakis nikomatsakis commented Jan 8, 2020

This is a prototype impl that extends impl !Trait beyond auto traits. It is not integrated with coherence or anything else, and hence only serves to prevent downstream impls (but not to allow downstream crates to rely on the absence of such impls for coherence purposes).

Fixes #66544

TODO:

@rust-highfive
Copy link
Collaborator

Some changes occurred in diagnostic error codes

cc @GuillaumeGomez

@rust-highfive
Copy link
Collaborator

r? @varkor

(rust_highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jan 8, 2020
@rust-highfive

This comment has been minimized.

@Aaron1011
Copy link
Member

@nikomatsakis: How does this relate to reservation impls?

@rust-highfive

This comment has been minimized.

@nikomatsakis
Copy link
Contributor Author

A negative impl is a semver commitment never to implement the given trait for the given type. It should eventually mean that you can rely on the impl not existing for the purposes of negative reasoning in coherence, though this PR doesn't implement that. What this PR does is simply require that no negative and positive impls (for the same trait) can overlap. This means that you can rely on an impl not existing for the purpose of proving soundness, and in particular for proving Pin sound.

A reservation impl is...something harder to express. It is considered a kind of "ambiguous" impl -- it doesn't exist yet, but it might exist in the future. This prevents people from assuming negatively that it would never exist. But it doesn't prevent you from writing overlapping impls.

@rust-highfive

This comment has been minimized.

@nikomatsakis
Copy link
Contributor Author

@comex do you think you could provide me with "clean, minimized versions" of your exploits? The code in this playground is rather complex .. I'd prefer to have three or four simple tests I can add for regression tests. They don't have to be fully weaponized necessarily, either -- something like what @withoutboats did would be perfect.

(In particular, I believe we need a negative Clone impl for &mut T, at least, before this particular PR is done. I guess we also need to update the CoerceUnsized trait to be unsafe for us to fully fix the "rogue impl" problem? That feels like maybe a separate PR, but maybe I'll do it together.)

@withoutboats
Copy link
Contributor

@nikomatsakis I can provide minimal examples for both DerefMut and Clone. Here they are:

DerefMut for shared reference: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=7d0c6cef76960efecd8e9afd3a851443

Clone for mutable reference: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018&gist=55430b595a04fa05c52fb6abe024d5e8

(You'll notice these work almost exactly the same way.)

For CoerceUnsized I don't have a sample ready, but I think fixing CoerceUnsized should be tracked separately, possibly even opening a separate issue from #66544

@nikomatsakis
Copy link
Contributor Author

@withoutboats

For CoerceUnsized I don't have a sample ready, but I think fixing CoerceUnsized should be tracked separately, possibly even opening a separate issue from #66544

I was thinking that might be a good idea as well, as the description of #66544 doesn't seem to match.

@withoutboats
Copy link
Contributor

Yea I think it'd be better to track the coerceunsized problem as "we added an unchecked invariant to implementing coerceunsized but didnt mark the trait unsafe," just separate from this coherence hole issue.

@rust-highfive

This comment has been minimized.

@bors

This comment has been minimized.

@nikomatsakis nikomatsakis force-pushed the negative-impls branch 3 times, most recently from fa21734 to a10769a Compare January 8, 2020 16:58
@nikomatsakis nikomatsakis changed the title [WIP] permit negative impls for non-auto traits permit negative impls for non-auto traits Jan 8, 2020
@nikomatsakis
Copy link
Contributor Author

I've removed the WIP, I think this PR is roughly ready to land, though I think it merits an FCP and a more detailed write-up of

(a) the semantics of what is happening
(b) the motivation for this change around Pin

I can try to get to that in a bit.

Copy link
Member

@varkor varkor left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The implementation looks good. The diagnostics around negative trait bounds in general could be improved, but that can be left as a follow up.

@varkor
Copy link
Member

varkor commented Jan 8, 2020

It might also be worth putting negative impls for non-auto traits behind a separate feature flag to optin_builtin_traits, as they're really distinct features.

@nikomatsakis
Copy link
Contributor Author

Ah yeah, I meant to add "new feature flag" to the checklist

@Lokathor
Copy link
Contributor

Lokathor commented Jan 8, 2020

The "stable" version number should be 1.41 or whenever this actually gets to stable. This might sound silly to say but sometimes version strings like this have gone unnoticed so I thought i'd just throw in a reminder.

@Aaron1011
Copy link
Member

Aaron1011 commented Jan 8, 2020

Do we want to do a crater run for this? On one hand, I would be shocked if anyone ever wrote this kind of bizarre impl in real code. On the other hand, if someone did write such an impl, it would be good to know that there exists code in the wild that will be permanently broken by this.

@nikomatsakis
Copy link
Contributor Author

@bors r=varkor

@bors
Copy link
Contributor

bors commented Mar 26, 2020

📌 Commit 0d07026 has been approved by varkor

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-author Status: This is awaiting some action (such as code changes or more information) from the author. labels Mar 26, 2020
@bors
Copy link
Contributor

bors commented Mar 26, 2020

⌛ Testing commit 0d07026 with merge 8599f89a0f86493bfe6d12bc1a1f0a09d86818eb...

@Centril
Copy link
Contributor

Centril commented Mar 26, 2020

@bors retry

bors added a commit to rust-lang-ci/rust that referenced this pull request Mar 26, 2020
Rollup of 5 pull requests

Successful merges:

 - rust-lang#68004 (permit negative impls for non-auto traits)
 - rust-lang#70385 (Miri nits: comment and var name improvement)
 - rust-lang#70411 (Fix for rust-lang#62691: use the largest niche across all fields)
 - rust-lang#70417 (parser: recover on `...` as a pattern, suggesting `..`)
 - rust-lang#70424 (simplify match stmt)

Failed merges:

r? @ghost
@bors
Copy link
Contributor

bors commented Mar 26, 2020

⌛ Testing commit 0d07026 with merge 2fbb075...

@bors bors merged commit b0a63cb into rust-lang:master Mar 26, 2020
Comment on lines -1 to -12
#![feature(optin_builtin_traits)]

struct TestType;

trait TestTrait {
fn dummy(&self) { }
}

impl !TestTrait for TestType {}
//~^ ERROR invalid negative impl

fn main() {}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't a test for this without the feature flag remain?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
disposition-merge This issue / PR is in PFCP or FCP with a disposition to merge it. F-negative_impls #![feature(negative_impls)] finished-final-comment-period The final comment period is finished for this PR / Issue. S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. T-lang Relevant to the language team, which will review and decide on the PR/issue.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Pin is unsound due to rogue Deref/DerefMut implementations