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

The new coherence rules disable very useful patterns #20974

Closed
reem opened this issue Jan 12, 2015 · 10 comments · Fixed by #21792
Closed

The new coherence rules disable very useful patterns #20974

reem opened this issue Jan 12, 2015 · 10 comments · Fixed by #21792
Labels
A-trait-system Area: Trait system

Comments

@reem
Copy link
Contributor

reem commented Jan 12, 2015

Specifically that input parameters cannot be used as proof of coherence, i.e. impl ExternTrait<LocalType> for ExternType, is no longer allowed.

I've hit this in Iron pretty hard, with this simplified example:

Crate 1: (rust-modifier)

trait Modifier<M> { .. }

Crate 2: (hyper)

pub enum Status { .. }

Crate 3: (iron)

struct Response { .. }

// None of these impls are legal anymore, which is a massive ergonomic
// regression, since it will require a series of wrapper types instead.

impl Modifier<Response> for Status { .. }
impl<'a> Modifier<Response> for &'a str { .. }
impl Modifier<Response> for String { .. }
impl Modifier<Response> for Vec<u8> { .. }
impl Modifier<Response> for Box<Reader + Send> { .. }
@reem
Copy link
Contributor Author

reem commented Jan 12, 2015

One possible transformation of this would be to instead change the trait Modifier to Modifiable, changing the order of type parameters such that the impls are impl Modifiable<Status> for Response { .. }.

However, this just moves the problem elsewhere, as it becomes impossible to define modifiers for Response outside of Iron, which is a primary use case for using Modifiers instead of regular methods. As a result, this is not a satisfactory transformation.

@ghost
Copy link

ghost commented Jan 12, 2015

@reem Leaving aside the issue of coherence, I describe a pattern here that I think might adapted for this situation. It's not very pretty, although as I mention in that thread it could be cleaned up a bit once equality constraints land.

@Aatch Aatch added the A-trait-system Area: Trait system label Jan 12, 2015
@reem
Copy link
Contributor Author

reem commented Jan 12, 2015

@darinmorrison Ugh, I guess that works but it is certainly not pretty and not something I could really readily adopt for a framework like Iron where implementing modifiers is going to be an extremely common task.


FWIW this blocks building Iron on nightly/1.0-alpha.

@nikomatsakis
Copy link
Contributor

cc me

@nikomatsakis
Copy link
Contributor

@reem and I had a discussion about this on IRC today that covered much of the justification for the current rules (in brief, anyway) as well as some ideas for how to resolve it.. I'll try to write up my current thinking into a blog post or something, since reading IRC logs is a pain.

@Ogeon
Copy link

Ogeon commented Jan 13, 2015

This is a different situation, but still... I noticed that it's not possible to implement a local trait for something implementing Fn with a generic type, like the handlers in rustful:

impl<C: Cache, F: Fn(Context<C>, Response)> Handler for F {
    type Cache = C;

    fn handle_request(&self, context: Context<C>, response: Response) {
        (*self)(context, response);
    }
}

Cache, Context Response and Handler are local. I can imagine that it has something to to with C being generic, since it works if I substitutes it for &Cache, but what I find interesting is that this seems to be fine:

impl<C: Cache> Handler for fn(Context<C>, Response) {
    type Cache = C;

    fn handle_request(&self, context: Context<C>, response: Response) {
        (*self)(context, response);
    }
}

@nikomatsakis
Copy link
Contributor

@aidancully
Copy link
Contributor

If I understand the issue, I'm not sure the Iron code can work with the coherence model rust seems to want? Consider this (which is not what Iron does, I know, but for the sake of argument):

// crate 1
pub enum Status { .. };
// crate 2
trait Modifier<M>;
impl<T> Modifier<T> for Status { .. } // ***
// crate 3
struct Response { };
impl Modifier<Response> for Status { .. }

It seems like, under any proposed coherence scheme, crate 2 would always have the option of adding the marked implementation (if the library author decides to do so at some point in the future), which would then become incoherent with crate 3. Is that right? Is that something the coherence rules are intended to prevent?

@reem
Copy link
Contributor Author

reem commented Jan 16, 2015

The above case will fail with a conflicting implementation (different than
a lack of coherence, since crate 2 defines the trait) when crate 3 tries to
add its impl. This is fine, since adding an implementation like that is
(and is intended to be) a breaking change of crate 2.
On Fri, Jan 16, 2015 at 7:17 PM Aidan Cully [email protected]
wrote:

If I understand the issue, I'm not sure the Iron code can work with the
coherence model rust seems to want? Consider this (which is not what Iron
does, I know, but for the sake of argument):

// crate 1pub enum Status { .. };// crate 2trait Modifier;impl Modifier for Status { .. } // ***// crate 3struct Response { };impl Modifier for Status { .. }

It seems like, under any proposed coherence scheme, crate 2 would always
have the option of adding the marked implementation (if the library author
decides to do so at some point in the future), which would then become
incoherent with crate 3. Is that right? Is that something the coherence
rules are intended to prevent?


Reply to this email directly or view it on GitHub
#20974 (comment).

@aidancully
Copy link
Contributor

OK, got it. Thanks.

bors added a commit that referenced this issue Feb 1, 2015
Update the coherence rules to "covered first" -- the first type parameter to contain either a local type or a type parameter must contain only covered type parameters.

cc #19470.
Fixes #20974.
Fixes #20749.

r? @aturon
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-trait-system Area: Trait system
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants