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

Implicit lifetimes of type parameters does not work #75252

Open
canova opened this issue Aug 7, 2020 · 3 comments
Open

Implicit lifetimes of type parameters does not work #75252

canova opened this issue Aug 7, 2020 · 3 comments
Labels
A-implied-bounds Area: Implied bounds / inferred outlives-bounds C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.

Comments

@canova
Copy link
Contributor

canova commented Aug 7, 2020

This code should work:

use std::collections::{BTreeMap, HashMap};

fn foo<'a, K, V, I: 'a + IntoIterator<Item = (&'a K, &'a V)>>(i: I) {}

fn main() {
    let map = HashMap::<u32, u32>::new();
    foo(&map);
    
    let map = BTreeMap::<u32, u32>::new();
    foo(&map);
}

(Playground)

Because, even though we don't assign 'a lifetime to K and V, since we have &'a K &'a V in the signature, that lifetime should be implicitly assigned to them instead. Currently that does not compile and we get this error below:

  Compiling playground v0.0.1 (/playground)
error[E0309]: the parameter type `K` may not live long enough
 --> src/main.rs:3:39
  |
3 | fn foo<'a, K, V, I: 'a + IntoIterator<Item = (&'a K, &'a V)>>(i: I) {}
  |            -                          ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a K` does not outlive the data it points at
  |            |
  |            help: consider adding an explicit lifetime bound...: `K: 'a`

error[E0309]: the parameter type `V` may not live long enough
 --> src/main.rs:3:39
  |
3 | fn foo<'a, K, V, I: 'a + IntoIterator<Item = (&'a K, &'a V)>>(i: I) {}
  |               -                       ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a V` does not outlive the data it points at
  |               |
  |               help: consider adding an explicit lifetime bound...: `V: 'a`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0309`.
error: could not compile `playground`.

Despite the example, this doesn't seem like a problem for IntoIterator only. It looks like there is a fundamental problem instead. This was separated from the example in #74034 and thanks @nbdd0121 for pointing that out in #75203.

Meta

rustc --version --verbose:

rustc 1.45.0 (5c1f21c3b 2020-07-13)
binary: rustc
commit-hash: 5c1f21c3b82297671ad3ae1e8c942d2ca92e84f2
commit-date: 2020-07-13
host: x86_64-unknown-linux-gnu
release: 1.45.0
LLVM version: 10.0
@jonas-schievink
Copy link
Contributor

I don't think this is supposed to work, implied bounds only work on impls

@nbdd0121
Copy link
Contributor

nbdd0121 commented Aug 7, 2020

Actually I tested that example again and found that it does not work for both HashMap and BTreeMap, so that example is actually not a MCVE. So I created this MCVE from the original example:

struct A<T>(T);
struct B<T>(T);

trait C {
    type Item;
}

impl<'a, T> C for &'a A<T> {
    type Item = &'a T;
}

impl<'a, T: 'a> C for &'a B<T> {
    type Item = &'a T;
}

trait Foo where for<'a> &'a Self: C<Item = &'a Self::Item> {
    type Item;
}

// Doesn't compile: suggest `T: 'a` is needed.
// fn foo<'a, T, I: 'a + C<Item = &'a T>>(i: I) {}

// Compiles
impl<T> Foo for A<T> {
    type Item = T;
}

// Doesn't compile: suggest `T: 'a` is needed???
// impl<T> Foo for B<T> {
//     type Item = T;
// }

A and B are identical, except that impl<'a, T> C for &'a A<T> does not have T: 'a. But for &'a A<T> to be well-formed, T: 'a must be implied. So they should perform the same?

@canova
Copy link
Contributor Author

canova commented Aug 8, 2020

I don't think this is supposed to work, implied bounds only work on impls

Ah, interesting. Was that intentional, or just not implemented yet?
Then we can use the case @nbdd0121 provided, although it's a bit different than what first comment explains.

@fmease fmease added T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue. A-implied-bounds Area: Implied bounds / inferred outlives-bounds and removed needs-triage-legacy labels Sep 6, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-implied-bounds Area: Implied bounds / inferred outlives-bounds C-bug Category: This is a bug. T-compiler Relevant to the compiler team, which will review and decide on the PR/issue. T-types Relevant to the types team, which will review and decide on the PR/issue.
Projects
None yet
Development

No branches or pull requests

5 participants