Notice how bar2 has a &'a str where 'a: 'static and it can be happily passed to bar.
Of course in T: 'static you're subtyping a type and in 'a: 'static you're subtyping a lifetime (which implicitly subtypes the type that it's applied on)... but the ": 'static" part means exactly the same: "the left part of this bound can live up to the end of the application". Whether it's a lifetime, a borrowed type or an owned type does not matter.
> It is what it is I guess... just confusing as to why it was decided to use the same syntax for these things, instead of something different.
Because they are the same.
We could of course separate them into 'noref, 'yesrefbutstatic, 'staticref, etc. But then we'd have a needlessly restrictive std:.thread::spawn that would accept only Owned, or only Owned<'static> or only &'static Referenced. The implications are the same, hence they're the same. We wouldn't gain anything and we'd be needlessly restricted.
A simpler way to put it: owned values have an implicit 'static lifetime.
What you say makes sense... but I struggle to reconcile it with reality.
If "the left part of this bound can live up to the end of the application" then why is &a not 'a where 'a: 'static? a can live up to the end of the application. &a can live up to the end of the application.
Why is the result "argument requires that `a` is borrowed for `'static`"
fn foo<'a: 'static>(a: &'a str) { println!("{}", a) }
pub fn main() {
let a = "hello world".to_string();
foo(&a);
}
So I guess I'm going to have to just agree to disagree on this one and bow out of this conversation thread I'm afraid.
If you do 'a: 'static, then you just said 'a is at least as long as 'static.
When you borrow the String, you just created a lifetime that is not as long as 'static. Variables are dropped (and hence unborrowed) in reverse order. So 'a will necessarily be dropped before its owner, hence it's shorter than 'static.
As you can see it complains that it's dropped at the end of main() even though it should be borrowed for 'static. If this was an owned value it would NOT be dropped at main() since it would be moved into the function on call.
Nothing surprising here.
> &a can live up to the end of the application
Nope. Imagine spawning a thread and passing &a but keeping 'a' in your main thread.
> a can live up to the end of the application. &a can live up to the end of the application.
Nope, a reference to a stack frame can't live up to the end of the application. The stack frame gets deallocated and the referent ceases to exist; therefore the reference you're creating in your linked example doesn't outlive 'static. `main` is not an exception to this in Rust.
T: 'static would happily typecheck with &'a str if 'a: 'static.
T: 'static typechecks:
- OwnedValue
- OwnedValueWithReferences<'a> where 'a: 'static
- &'a ReferencedValue where 'a: 'static /// &'static ReferencedValue
- Foo<&'a Bar> where 'a: 'static /// Foo<&'static Bar>
...and more.
See the example here: https://play.rust-lang.org/?version=stable&mode=debug&editio...
Notice how bar2 has a &'a str where 'a: 'static and it can be happily passed to bar.
Of course in T: 'static you're subtyping a type and in 'a: 'static you're subtyping a lifetime (which implicitly subtypes the type that it's applied on)... but the ": 'static" part means exactly the same: "the left part of this bound can live up to the end of the application". Whether it's a lifetime, a borrowed type or an owned type does not matter.
> It is what it is I guess... just confusing as to why it was decided to use the same syntax for these things, instead of something different.
Because they are the same.
We could of course separate them into 'noref, 'yesrefbutstatic, 'staticref, etc. But then we'd have a needlessly restrictive std:.thread::spawn that would accept only Owned, or only Owned<'static> or only &'static Referenced. The implications are the same, hence they're the same. We wouldn't gain anything and we'd be needlessly restricted.
A simpler way to put it: owned values have an implicit 'static lifetime.