Skip to content

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

New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

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-type-system Area: 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-type-system Area: 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.

# for free to join this conversation on GitHub. Already have an account? # to comment
Labels
A-type-system Area: Type system
Projects
None yet
Development

No branches or pull requests

4 participants