Open djc opened 4 years ago
The error is correct, I think. You happen to call foo with a static value, but you don't put that in the type signature, so someone else is free to call it with a shorter lifetime. If you want to enforce only static lifetimes for foo, you can use a: &'static
.
Oh wait, I missed that the return type of bar doesn't (or at least, shouldn't) depends on a. Yeah this does seem like a bug then.
This appears to be #42940, fixing which might depend on
type-alias-impl-trait
(although so far that's only a workaround, not really a fix?).
As cramertj wrote there, the current behavior is by design of the RPIT RFC ("Assumption 2"), because it was expected that type-alias-impl-trait
would resolve it ("Assumption 1") correctly.
Based on the RFC I think it's correct that this wouldn't compile. However, I am curious why adding a 'static
bound to the return type of bar
doesn't fix it:
fn bar<T>(_: T) -> impl Stream<Item = Result<Vec<u8>, io::Error>> + 'static {
That ought to remove any doubt that the return type is tied to the lifetime of T
.
Also, this still fails to compile when foo
is not async, but prints a more concise error message:
error[E0621]: explicit lifetime required in the type of `a`
--> src/lib.rs:7:5
|
6 | fn foo(a: &str) {
| ---- help: add explicit lifetime `'static` to the type of `a`: `&'static str`
7 | assert_static(bar(a.split(',')));
| ^^^^^^^^^^^^^ lifetime `'static` required
@tmandry from https://github.com/rust-lang/rust/issues/42940#issuecomment-335390296
From some experimentation, it seems to be because
fn foo<T>(_: T) -> impl Bar
compiles to something likefn foo<T>(_: T) -> impl Bar + 't
, where't
is the lifetime ofT
. (I don't think this relationship can be expressed in regular Rust code, though Ralith on IRC suggested one could consider the anonymous type to containPhantomData<T>
)Thus in the original code
fn post<'a, B>(&'a self, _body: &B) -> impl Future + 'a
effectively forces the return type to be bounded byB
's lifetime in addition to'a
. This is why changing_body: &B
to_body: B
does not change anything, nor does annotating the parameter as_body: &'b B
for an unconstrained'b
(emphasis mine)
So when adding an explicit lifetime bound, it's in addition to the implicit one, not instead of. And since 'static
is the widest lifetime it has no effect. I tried the same thing when I hit the issue, with the same results, before I found #42940 :/
Current output:
error[[E0521]](https://doc.rust-lang.org/stable/error_codes/E0521.html): borrowed data escapes outside of function
--> src/lib.rs:7:5
|
6 | async fn foo(a: &str) {
| - - let's call the lifetime of this reference `'1`
| |
| `a` is a reference that is only valid in the function body
7 | assert_static(bar(a.split(',')));
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
| |
| `a` escapes the function body here
| argument requires that `'1` must outlive `'static`
For more information about this error, try `rustc --explain E0521`.
error: could not compile `playground` due to previous error
I tried this code:
I expected to see this happen: compiles correctly.
Instead, this happened:
Meta
rustc 1.47.0. This appears to be https://github.com/rust-lang/rust/issues/42940, fixing which might depend on
type-alias-impl-trait
(although so far that's only a workaround, not really a fix?). It would be nice to have more specific diagnostics here.