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

Failure to determine impls with higher-ranked lifetimes involved #32600

Closed
withoutboats opened this issue Mar 30, 2016 · 7 comments
Closed

Failure to determine impls with higher-ranked lifetimes involved #32600

withoutboats opened this issue Mar 30, 2016 · 7 comments
Labels
A-typesystem Area: The type system

Comments

@withoutboats
Copy link
Contributor

This does not work:

trait Foo<T> {
    fn process(&mut self, T);
}

impl<T, F> Foo<T> for F where F: FnMut(T) {
    fn process(&mut self, data: T) {
        self(data)
    }
}

fn bar<F: for<'a> Foo<&'a str>>(mut foo: F) {
    foo.process("foobar");
}

fn main() {
    bar(|x| println!("{}", x));
}

This does work:

trait Foo<T> {
    fn process(&mut self, T);
}

struct Bar;

impl<'a> Foo<&'a str> for Bar {
    fn process(&mut self, data: &'a str) {
        println!("{}", data);
    }
}

fn bar<F: for<'a> Foo<&'a str>>(mut foo: F) {
    foo.process("foobar");
}

fn main() {
    bar(Bar);
}

So does this:

fn bar<F: for<'a> FnMut(&'a str)>(mut foo: F) {
    foo("foobar");
}

fn main() {
    bar(|x| println!("{}", x));
}

Perhaps I am mistaken, but I believe that FnMut(T): Foo<T> implies for<'a> FnMut(&'a str): for<'a> Foo<&'a str>. rustc seems unable to make the determination that this is true.

@Aatch
Copy link
Contributor

Aatch commented Mar 31, 2016

This is an inference thing. I'm not sure if it's expected or not, but the fact that this works:

trait Foo<T> {
    fn process(&mut self, T);
}

impl<T, F> Foo<T> for F where F: FnMut(T) {
    fn process(&mut self, data: T) {
        self(data)
    }
}

fn bar<F: for<'a> Foo<&'a str>>(mut foo: F) {
    foo.process("foobar");
}

fn main() {
    bar(|x:&str| println!("{}", x));
}

is evidence that it's probably more to do with inference than anything else. Interesting though is that this:

trait Foo<T> {
    fn process(&mut self, T);
}

impl<T, F> Foo<T> for F where F: FnMut(T) {
    fn process(&mut self, data: T) {
        self(data)
    }
}

fn bar<F: Foo<String>>(mut foo: F) {
    foo.process("foobar".into());
}

fn main() {
    bar(|x| println!("{}", x));
}

works, so the lifetimes are probably a factor.

@Aatch Aatch added the A-typesystem Area: The type system label Mar 31, 2016
@withoutboats
Copy link
Contributor Author

It also compiles with bar(|x:&_| println!("{}", x)), further pointing to the lifetimes.

@withoutboats
Copy link
Contributor Author

This also works (using the static lifetime):

trait Foo<T> {
    fn process(&mut self, T);
}

impl<T, F> Foo<T> for F where F: FnMut(T) {
    fn process(&mut self, data: T) {
        self(data)
    }
}

fn bar<F: Foo<&'static str>>(mut foo: F) {
    foo.process("foobar");
}

fn main() {
    bar(|x| println!("{}", x));
}

This does not (using a specific method of str, instead of the generic println! macro)

trait Foo<T> {
    fn process(&mut self, T);
}

impl<T, F> Foo<T> for F where F: FnMut(T) {
    fn process(&mut self, data: T) {
        self(data)
    }
}

fn bar<F: for<'a> Foo<&'a str>>(mut foo: F) {
    foo.process("foobar");
}

fn main() {
    bar(|x| str::len(x));
}

@withoutboats
Copy link
Contributor Author

I also haven't posted the error message, its:

type mismatch resolving `for<'a> <[closure@<anon>:16:9: 16:30] as core::ops::FnOnce<(&'a str,)>>::Output == ()`:
 expected bound lifetime parameter 'a,
    found concrete lifetime

@jonhoo
Copy link
Contributor

jonhoo commented Apr 29, 2016

I believe this is another instance of the same issue:

fn foo<F1, X, F2>(f1: F1, f2: F2)
    where F1: FnOnce() -> X,
          F2: Fn(&mut X)
{
    let mut x = f1();
    f2(&mut x);
}

fn main() {
    let a = || 0 as u32;
    let b = |_| {};
    foo(a, b);
}

Yields:

test.rs:12:5: 12:8 error: type mismatch resolving `for<'r> <[closure@test.rs:11:13: 11:19] as core::ops::FnOnce<(&'r mut u32,)>>::Output == ()`:
 expected bound lifetime parameter ,
    found concrete lifetime [E0271]
test.rs:12     foo(a, b);
             ^~~
test.rs:12:5: 12:8 help: run `rustc --explain E0271` to see a detailed explanation
test.rs:12:5: 12:8 note: required by `foo`
test.rs:12:5: 12:8 error: type mismatch: the type `[closure@test.rs:11:13: 11:19]` implements the trait `core::ops::Fn<(_,)>`, but the trait `for<'r> core::ops::Fn<(&'r mut u32,)>` is required (expected concrete lifetime, found bound lifetime parameter ) [E0281]
test.rs:12     foo(a, b);
             ^~~
test.rs:12:5: 12:8 help: run `rustc --explain E0281` to see a detailed explanation
test.rs:12:5: 12:8 note: required by `foo`
error: aborting due to 2 previous errors

@withoutboats
Copy link
Contributor Author

withoutboats commented Apr 29, 2016

I think you're right. Again it can be fixed by changing let b = |_| {}; to let b = |_: &mut _| {};

@Mark-Simulacrum
Copy link
Member

Closing in favor of #41078.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-typesystem Area: The type system
Projects
None yet
Development

No branches or pull requests

4 participants