Why can I specify a late bound lifetime parameter in one case but not the other?
Asked Answered
D

1

8

Consider the following rust program:

fn f<'a>(x: &'a i32) {
    unimplemented!();
}

fn main() {
    f::<'static>;
}

When compiling it, the following compilation error is outputed:

error: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
 --> src/main.rs:6:9
  |
6 |     f::<'static>;
  |         ^^^^^^^
  |
note: the late bound lifetime parameter is introduced here
 --> src/main.rs:1:6
  |
1 | fn f<'a>(x: &'a i32) {
  |      ^^

Lets modify the program like this:

fn f<'a, 'b>(x: &'a i32) -> &'b i32 {
    unimplemented!();
}

fn main() {
    f::<'static>;
}

For some strange reason this compiles now without any compilation errors. Why is this? If the lifetime parameter 'a in the first program was late bound, why shouldn't it also be late bound in the second program? Note that the only change I did between the first and the second program was to add another lifetime parameter and a return type that depends on this new lifetime parameter.

Digamma answered 21/2, 2021 at 12:57 Comment(4)
I will award the first good answer with a bounty.Digamma
The second example isn't exactly out of the weeds, the compiler emits a warning that it won't be accepted in the future.Analogy
@kmdreko: Thanks! That warning explains it! After they make it a hard error the behaviour will be consistent. I missed that warning because I had disabled warnings globally to do a workaround for a problem with using virtualbox shared filesystem. I can give you the bounty if you write that comment as an answer.Digamma
Lifetimes involved in return values are early-bound for some obscure reason that can be probably clarified by folks over at rust-internals. I was unable to find / intuitively understand why it is so.Darceldarcey
C
0

As written in one of the comments, the second program with f<'a, 'b> and f::<'static> currently produces a warning (Rust 1.80):

warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
 --> src/main.rs:6:9
  |
1 | fn f<'a, 'b>(x: &'a i32) -> &'b i32 {
  |      -- the late bound lifetime parameter is introduced here
...
6 |     f::<'static>;
  |         ^^^^^^^
  |
  = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
  = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
  = note: `#[warn(late_bound_lifetime_arguments)]` on by default

As of why it happens, this is explained in the GitHub issue linked in the warning:

It's reported as a lint only in cases where making it a hard error would cause breakage back in 2017. The intent is to produce an error, in general, the lint is only a way to give people some time to fix code.

So, in short, this is sometimes a warning in cases where giving an error would break existing Rust code.

Chore answered 18/8 at 21:37 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.