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

Incorrect inference of lifetime bound for existential type #55099

Closed
jonhoo opened this issue Oct 15, 2018 · 3 comments
Closed

Incorrect inference of lifetime bound for existential type #55099

jonhoo opened this issue Oct 15, 2018 · 3 comments

Comments

@jonhoo
Copy link
Contributor

@jonhoo jonhoo commented Oct 15, 2018

Consider the following code (playground):

fn reply<'a, I: 'a>(_: I) -> impl Future<Item = (), Error = ()> + 'static {
    // do something with argument
    // then build future that does not borrow I
    futures::future::ok(())
}

fn foo(foo: String) -> Box<Future<Item = String, Error = ()>> {
    Box::new(reply(&foo).map(move |_| foo))
}

This code doesn't compile because impl Trait assumes that all type parameters are in scope for the concrete type. This may get fixed eventually, but for the time being, we can work around it using existential type (rust-lang/rfcs#2071; playground):

#![feature(existential_type)]
existential type Reply: Future<Item = (), Error = ()>;

fn reply<'a, I: 'a>(_: I) -> Reply { futures::future::ok(()) }

fn foo(foo: String) -> Box<Future<Item = String, Error = ()>> {
    Box::new(reply(&foo).map(move |_| foo))
}

However, this pattern does not compose. This example fails to compile (playground):

#![feature(existential_type)]

struct Foo<'a> {
    x: &'a mut (),
}

existential type F1: Future<Item = (), Error = ()>;
existential type F2: Future<Item = (), Error = ()>;

impl<'a> Foo<'a> {
    fn foobar(&mut self) -> F1 {
        futures::future::ok(())
    }

    fn reply<I>(&mut self, _: I) -> F2 {
        self.foobar().and_then(move |_| futures::future::ok(()))
    }
}

with the error

error: non-defining existential type use in defining scope
  --> src/lib.rs:19:40
   |
19 |       fn reply<I>(&mut self, _: I) -> F2 {
   |  ________________________________________^
20 | |         self.foobar().and_then(move |_| futures::future::ok(()))
21 | |     }
   | |_____^ lifetime `'a` is part of concrete type but not used in parameter list of existential type

error: type parameter `I` is part of concrete type but not used in parameter list for existential type
  --> src/lib.rs:19:40
   |
19 |       fn reply<I>(&mut self, _: I) -> F2 {
   |  ________________________________________^
20 | |         self.foobar().and_then(move |_| futures::future::ok(()))
21 | |     }
   | |_____^

I'm not entirely sure why this fails, but it seems like the code should be accepted?

/cc @Nemo157

@jonhoo
Copy link
Contributor Author

@jonhoo jonhoo commented Oct 15, 2018

Or a somewhat simpler example with just a single existential (playground):

#![feature(existential_type)]

struct Foo<'a> {
    x: &'a mut (),
}

existential type F: Future<Item = (), Error = ()>;

impl<'a> Foo<'a> {
    fn foobar(&mut self) -> Result<(), ()> {
        Ok(())
    }

    fn reply<I>(&mut self, _: I) -> F {
        self.foobar().into_future().and_then(move |_| futures::future::ok(()))
    }
}
jonhoo added a commit to jonhoo/msql-srv that referenced this issue Oct 15, 2018
@jonhoo
Copy link
Contributor Author

@jonhoo jonhoo commented Nov 14, 2018

@estebank Maybe also tag with A-impl-trait since it's related to existentials? And possibly T-compiler (or is this T-lang terretority?)

jonhoo added a commit to jonhoo/msql-srv that referenced this issue Dec 4, 2018
@Arnavion
Copy link

@Arnavion Arnavion commented Jan 29, 2019

Smaller repro without futures dependency:

#![feature(existential_type)]

trait Future {
}

struct AndThen<F>(F);

impl<F> Future for AndThen<F> {
}

struct Foo<'a> {
    x: &'a mut (),
}

existential type F: Future;

impl<'a> Foo<'a> {
    fn reply(&mut self) -> F {
        AndThen(|| ())
    }
}

Replacing AndThen(|| ()) with AndThen(()) compiles fine.

Dylan-DPC added a commit to Dylan-DPC/rust that referenced this issue Mar 19, 2020
…ikomatsakis

Add regression test for TAIT lifetime inference (issue rust-lang#55099)

Fixes rust-lang#55099

The minimized reproducer in issue rust-lang#55099 now compiles successfully.
This commit adds a regression test for it.
bors added a commit to rust-lang-ci/rust that referenced this issue Mar 20, 2020
Rollup of 9 pull requests

Successful merges:

 - rust-lang#67888 (Prefetch some queries used by the metadata encoder)
 - rust-lang#69618 (Clarify the relationship between `forget()` and `ManuallyDrop`.)
 - rust-lang#70103 (Clean up E0437 explanation)
 - rust-lang#70111 (BTreeMap: remove shared root)
 - rust-lang#70131 (Add regression test for TAIT lifetime inference (issue rust-lang#55099))
 - rust-lang#70133 (remove unused imports)
 - rust-lang#70145 (doc: Add quote to .init_array)
 - rust-lang#70146 (Clean up e0438 explanation)
 - rust-lang#70150 (triagebot.toml: accept cleanup-crew)

Failed merges:

r? @ghost
JohnTitor added a commit to JohnTitor/rust that referenced this issue Mar 20, 2020
…ikomatsakis

Add regression test for TAIT lifetime inference (issue rust-lang#55099)

Fixes rust-lang#55099

The minimized reproducer in issue rust-lang#55099 now compiles successfully.
This commit adds a regression test for it.
bors added a commit to rust-lang-ci/rust that referenced this issue Mar 20, 2020
Rollup of 9 pull requests

Successful merges:

 - rust-lang#69618 (Clarify the relationship between `forget()` and `ManuallyDrop`.)
 - rust-lang#69768 (Compute the correct layout for variants of uninhabited enums)
 - rust-lang#69935 (codegen/mir: support polymorphic `InstanceDef`s)
 - rust-lang#70103 (Clean up E0437 explanation)
 - rust-lang#70131 (Add regression test for TAIT lifetime inference (issue rust-lang#55099))
 - rust-lang#70133 (remove unused imports)
 - rust-lang#70145 (doc: Add quote to .init_array)
 - rust-lang#70146 (Clean up e0438 explanation)
 - rust-lang#70150 (triagebot.toml: accept cleanup-crew)

Failed merges:

r? @ghost
bors added a commit to rust-lang-ci/rust that referenced this issue Mar 20, 2020
Rollup of 9 pull requests

Successful merges:

 - rust-lang#69618 (Clarify the relationship between `forget()` and `ManuallyDrop`.)
 - rust-lang#69768 (Compute the correct layout for variants of uninhabited enums)
 - rust-lang#69935 (codegen/mir: support polymorphic `InstanceDef`s)
 - rust-lang#70103 (Clean up E0437 explanation)
 - rust-lang#70131 (Add regression test for TAIT lifetime inference (issue rust-lang#55099))
 - rust-lang#70133 (remove unused imports)
 - rust-lang#70145 (doc: Add quote to .init_array)
 - rust-lang#70146 (Clean up e0438 explanation)
 - rust-lang#70150 (triagebot.toml: accept cleanup-crew)

Failed merges:

r? @ghost
bors added a commit to rust-lang-ci/rust that referenced this issue Mar 20, 2020
Rollup of 9 pull requests

Successful merges:

 - rust-lang#69618 (Clarify the relationship between `forget()` and `ManuallyDrop`.)
 - rust-lang#69768 (Compute the correct layout for variants of uninhabited enums)
 - rust-lang#69935 (codegen/mir: support polymorphic `InstanceDef`s)
 - rust-lang#70103 (Clean up E0437 explanation)
 - rust-lang#70131 (Add regression test for TAIT lifetime inference (issue rust-lang#55099))
 - rust-lang#70133 (remove unused imports)
 - rust-lang#70145 (doc: Add quote to .init_array)
 - rust-lang#70146 (Clean up e0438 explanation)
 - rust-lang#70150 (triagebot.toml: accept cleanup-crew)

Failed merges:

r? @ghost
bors added a commit to rust-lang-ci/rust that referenced this issue Mar 20, 2020
Rollup of 9 pull requests

Successful merges:

 - rust-lang#69618 (Clarify the relationship between `forget()` and `ManuallyDrop`.)
 - rust-lang#69768 (Compute the correct layout for variants of uninhabited enums)
 - rust-lang#69935 (codegen/mir: support polymorphic `InstanceDef`s)
 - rust-lang#70103 (Clean up E0437 explanation)
 - rust-lang#70131 (Add regression test for TAIT lifetime inference (issue rust-lang#55099))
 - rust-lang#70133 (remove unused imports)
 - rust-lang#70145 (doc: Add quote to .init_array)
 - rust-lang#70146 (Clean up e0438 explanation)
 - rust-lang#70150 (triagebot.toml: accept cleanup-crew)

Failed merges:

r? @ghost
@bors bors closed this in fda913b Mar 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

4 participants