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

Compilation error for lifetimes in associated type used by async-fn-in-trait #102681

Closed
bryangarza opened this issue Oct 4, 2022 · 3 comments
Closed
Assignees
Labels
C-bug Category: This is a bug. F-async_fn_in_trait Static async fn in traits

Comments

@bryangarza
Copy link
Contributor

bryangarza commented Oct 4, 2022

The following UI test (async-associated-types.rs from #102642) currently does not compile

// edition: 2021

#![feature(async_fn_in_trait)]
#![allow(incomplete_features)]

use std::fmt::Debug;

trait MyTrait<'a, 'b, T> where Self: 'a, T: Debug + Sized + 'b {
    type MyAssoc;

    async fn foo(&'a self, key: &'b T) -> Self::MyAssoc;
}

impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
    type MyAssoc = (&'a U, &'b T);

    async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
        (self, key)
    }
}
//~^^^^ ERROR cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
//~| ERROR cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements

fn main() {}

I expected to see this happen: successful compilation

Instead, this happened:

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
  --> $DIR/async-associated-types.rs:17:43
   |
LL |     async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
   |                                           ^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
  --> $DIR/async-associated-types.rs:14:6
   |
LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
   |      ^^
note: ...so that the types are compatible
  --> $DIR/async-associated-types.rs:17:43
   |
LL |     async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
   |                                           ^^^^^^^^^^^^^^
   = note: expected `(&'a U, &'b T)`
              found `(&U, &T)`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
  --> $DIR/async-associated-types.rs:17:43
   |
LL |     async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
   |                                           ^^^^^^^^^^^^^^
   = note: expected `MyTrait<'static, 'static, T>`
              found `MyTrait<'_, '_, T>`

error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'b` due to conflicting requirements
  --> $DIR/async-associated-types.rs:17:43
   |
LL |     async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
   |                                           ^^^^^^^^^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'b` as defined here...
  --> $DIR/async-associated-types.rs:14:10
   |
LL | impl<'a, 'b, T: Debug + Sized + 'b, U: 'a> MyTrait<'a, 'b, T> for U {
   |          ^^
note: ...so that the types are compatible
  --> $DIR/async-associated-types.rs:17:43
   |
LL |     async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
   |                                           ^^^^^^^^^^^^^^
   = note: expected `(&'a U, &'b T)`
              found `(&U, &T)`
   = note: but, the lifetime must be valid for the static lifetime...
note: ...so that the types are compatible
  --> $DIR/async-associated-types.rs:17:43
   |
LL |     async fn foo(&'a self, key: &'b T) -> (&'a U, &'b T) {
   |                                           ^^^^^^^^^^^^^^
   = note: expected `MyTrait<'static, 'static, T>`
              found `MyTrait<'_, '_, T>`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0495`.

Meta

rustc --version --verbose:

rustc 1.66.0-nightly (092255976 2022-10-03)
binary: rustc
commit-hash: 092255976862c1f0121bb4446acd38336a860c4f
commit-date: 2022-10-03
host: x86_64-unknown-linux-gnu
release: 1.66.0-nightly
LLVM version: 15.0.2
@bryangarza
Copy link
Contributor Author

Dupe of #102682

@compiler-errors
Copy link
Member

I looked into this a bit more. We should probably be denying associated types in AFITs for now. See the corresponding non-AFIT code:

#![feature(inherent_associated_types)]

struct Foo<'a>(&'a ());

trait Trait<'a> {
    type Assoc;
}

impl<'a> Trait<'a> for Foo<'a> {
    type Assoc = ();
}

impl<'a> Foo<'a> {
    async fn foo() -> <Self as Trait<'a>>::Assoc {}
}

Which errors like:

error[[E0760]](https://doc.rust-lang.org/nightly/error-index.html#E0760): `async fn` return type cannot contain a projection or `Self` that references lifetimes from a parent scope
  --> src/lib.rs:12:23
   |
12 |     async fn foo() -> <Self as Trait<'a>>::Assoc {}
   |                       ^----^^^^^^^^^^^^^^^^^^^^^
   |                        |
   |                        help: consider spelling out the type instead: `Foo<'a>`

error: lifetime may not live long enough
  --> src/lib.rs:12:50
   |
11 | impl<'a> Foo<'a> {
   |      -- lifetime `'a` defined here
12 |     async fn foo() -> <Self as Trait<'a>>::Assoc {}
   |                                                  ^^ returning this value requires that `'a` must outlive `'static`

For more information about this error, try `rustc --explain E0760`.

This error exists because of a 'static type hack. #103491 goes into more detail and potentially fixes this, or at least provides a route to fixing this more easily.

chrysn added a commit to chrysn-pull-requests/embedded-nal that referenced this issue Nov 18, 2022
This removes the lifetimes from the Connect associated types; leaving
them would cause errors (possibly related to [12681]), but I think that
stacks whose sockets are not 'static can work around this by
implementing the stack traits on a &'short stack instead.

[12681]: rust-lang/rust#102681
@cjgillot
Copy link
Contributor

The code is now accepted, and the test has been updated.

chrysn added a commit to chrysn-pull-requests/embedded-nal that referenced this issue Dec 2, 2022
This removes the lifetimes from the Connect associated types; leaving
them would cause errors (possibly related to [12681]), but I think that
stacks whose sockets are not 'static can work around this by
implementing the stack traits on a &'short stack instead.

[12681]: rust-lang/rust#102681
eldruin pushed a commit to rust-embedded-community/embedded-nal that referenced this issue Jan 17, 2023
* gitignore: Also ignore target inside nested crate

* async: Add UDP traits

Closes: #71

* async UDP: Simplify to 2 rather than 3 traits

* async UDP: Documentation fixes; receive_into consistency

One trait's receive_into still used the old receive name.

* async UDP: Make accessible through lib.rs

* async UDP: Fix lifetimes of send and receive functions

Elided lifetimes would have asked too little of the data / buffer
references.

* async UDP: Better names for bound sockets

* UDP: use async-fn-in-trait instead of associated types that are Future

This removes the lifetimes from the Connect associated types; leaving
them would cause errors (possibly related to [12681]), but I think that
stacks whose sockets are not 'static can work around this by
implementing the stack traits on a &'short stack instead.

[12681]: rust-lang/rust#102681

* async/UDP: Remove connect_default helper

The connect method can now be provided properly.

* async/CHANGELOG: Add UDP

* async/UDP: rustfmt

* async/UDP: Tie socket's error types to stack's
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-bug Category: This is a bug. F-async_fn_in_trait Static async fn in traits
Projects
None yet
Development

No branches or pull requests

3 participants