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

where clause seems ignored when attached to narrower scope than binding point #17086

Closed
pnkfelix opened this issue Sep 7, 2014 · 4 comments
Closed

Comments

@pnkfelix
Copy link
Member

pnkfelix commented Sep 7, 2014

Consider the following code (example 1):

trait Foo { fn foo(&self) -> int; }
struct B<X>;
impl<X> B<X> {
    fn bar(&self, _x: X) -> int where X : Foo {
        // _x.foo()
        16
    }
    fn baz(&self) -> int {
        17
    }
}

// impl Foo for int { fn foo(&self) -> int { *self } }

fn main() {
    let b = B::<int>;
    let i = b.bar(3i);
    let j = b.baz();
    println!("Hello, world! {:d} {:d}", i, j)
}

Note that the impl of Foo for int is commented out. The where clause is meant to bound X for the method bar; we are not achieving that goal. I believe this is a bug, and a backwards-compatibility hazard for us to take note of (see further explanation below).


If I move the where-clause up so that its attached to the whole impl block, then we see the code get rejected, as expected. Illustrated here (example 2):

trait Foo { fn foo(&self) -> int; }
struct B<X>;
impl<X> B<X> where X : Foo {
    fn bar(&self, _x: X) -> int {
        // _x.foo()
        16
    }
    fn baz(&self) -> int {
        17
    }
}

// impl Foo for int { fn foo(&self) -> int { *self } }

fn main() {
    let b = B::<int>;
    let i = b.bar(3i);
    let j = b.baz();
    println!("Hello, world! {:d} {:d}", i, j)
}

(This is not an illustration of a bug. I just wanted to show that the code overall should indeed be rejected if the where clause is not ignored.)


Finally, we also need to make sure that we use the information from the where clause when checking the bodies of methods to which the where-clause is attached. This is also failing for us, causing a compile-failure that should be succeeding, as shown below (example 3):

trait Foo { fn foo(&self) -> int; }
struct B<X>;
impl<X> B<X> {
    fn bar(&self, _x: X) -> int where X : Foo {
        _x.foo()
    }
    fn baz(&self) -> int {
        17
    }
}

impl Foo for int { fn foo(&self) -> int { *self } }

fn main() {
    let b = B::<int>;
    let i = b.bar(3i);
    let j = b.baz();
    println!("Hello, world! {:d} {:d}", i, j)
}

Note that I have made several modifications in this example; mostly importantly, I have uncommented the impl of Foo for int and then used foo within the method bar. This currently causes the following compiler error:

<anon>:5:12: 5:17 error: type `X` does not implement any method in scope named `foo`
<anon>:5         _x.foo()
                    ^~~~~
error: aborting due to previous error
playpen: application terminated with error code 101
Program ended.

As noted in example 1, the ignoring of where clauses is a backwards compatibility hazard. While one might expect code that is using where clauses would also have code that is using methods of those triats (as in example 3), and thus would hit compilation failures before code could come to rely on the where clauses being ignored, example 1 is meant to concretely illustrate code that is building now but absolutely should be rejected.

@pnkfelix
Copy link
Member Author

pnkfelix commented Sep 8, 2014

The short term "fix" for the problem would be to issue an error on any where clause that refers to a variable that was bound at a higher scope than the point where the where clause appears.

Then we can fix that (i.e. put in the right semantics and remove the error) at our leisure.

But maybe it would be easy to just put in the right semantics instead.

@nikomatsakis
Copy link
Contributor

I'll tackle this. I think it's easier to just get the right semantics.

@jroesch
Copy link
Member

jroesch commented Dec 23, 2014

This appears to be fixed after the landing of #20002. The third test works just fine on the nightly. I believe we have appropriate tests for this but if not I will be happy to submit a wrap up PR. This should also fix the problems detailed in #18906. @nikomatsakis @pnkfelix @aturon.

@alexcrichton
Copy link
Member

Awesome, thanks @jroesch!

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

No branches or pull requests

4 participants