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

defaulted traits ought to be have more restrictive coherence rules #22978

Closed
nikomatsakis opened this issue Mar 2, 2015 · 4 comments · Fixed by #23038
Closed

defaulted traits ought to be have more restrictive coherence rules #22978

nikomatsakis opened this issue Mar 2, 2015 · 4 comments · Fixed by #23038
Assignees

Comments

@nikomatsakis
Copy link
Contributor

We initially had some rules that prevented explicit impls for defaulted traits for anything except for nominal types. In other words, if (in crate A) I have:

trait Foo { }
impl Foo for .. { }

then it was illegal to do (in any crate) struct SomeType { } impl Foo for (SomeType,) { }. However, that seemed too strict, because one wants to be able to do things like impl !Foo for *mut A { }, and since (currently) positive and negative impls basically follow the same rules, it seemed strange to permit one and not the other. So we removed this logic.

But we got it wrong. The current rules do not guarantee coherence well enough to avoid inconsistent conclusions. In particular, I can define in crate A a generic fn like:

fn test<X:Foo,Y:Foo>() {
    // in here, we can conclude that (X,Y) : Foo
}

This function can conclude that (X,Y) : Foo because it applies the default rule for the tuple and the components implement Foo.

But now in crate B I can do:

struct A { }
struct B { }
impl Foo for A { }
impl Foo for B { }
impl !Send for (A, B) { }

In other words, A and B are Foo, but not the pair (A,B). Uh oh!

I think what the rules ought to be is that, outside the crate where the trait was defined, we can only define an impl for a defaulted trait if the self-type is a ty_struct or ty_enum and the type itself was defined in the current crate.

cc @flaper87

@nikomatsakis
Copy link
Contributor Author

triage: P-backcompat-lang (1.0 Beta)

@nikomatsakis nikomatsakis changed the title defaulted traits ought to be more restrictive defaulted traits ought to be have more restrictive coherence rules Mar 2, 2015
@flaper87 flaper87 self-assigned this Mar 2, 2015
bors added a commit that referenced this issue Mar 9, 2015
@AlisdairO
Copy link
Contributor

@nikomatsakis Apologies for dredging up a very old issue, but I'm looking into writing diagnostics in this area and I wanted to check to be certain: in your example:

struct A { }
struct B { }
impl Foo for A { }
impl Foo for B { }
impl !Send for (A, B) { }

Should the final line be impl !Foo rather than impl !Send? If not, any chance you could clarify why impling !Send implies that (A, B) is !Foo? Thanks!

@nikomatsakis
Copy link
Contributor Author

Yes, that is a typo. It should be Foo not Send.

Niko

-------- Original message --------
From: Alisdair Owens notifications@github.com
Date:09/04/2015 14:26 (GMT-05:00)
To: rust-lang/rust rust@noreply.github.com
Cc: Niko Matsakis niko@alum.mit.edu
Subject: Re: [rust] defaulted traits ought to be have more restrictive coherence rules (#22978)
@nikomatsakis Apologies for dredging up a very old issue, but I'm looking into writing diagnostics in this area and I wanted to check to be certain: in your example:

struct A { }
struct B { }
impl Foo for A { }
impl Foo for B { }
impl !Send for (A, B) { }
Should the final line be impl !Foo rather than impl !Send? If not, any chance you could clarify why impling !Send implies that (A, B) is !Foo? Thanks!


Reply to this email directly or view it on GitHub.

@AlisdairO
Copy link
Contributor

Fab, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants