Consider these structs:
struct Promise1<T, Err> {
on_resolve:Option<|promised:T|: Send>,
on_reject:Option<|failed:Err|: Send>,
}
struct Promise2<T, Err> {
on_resolve:Option<|promised:T|: 'static>,
on_reject:Option<|failed:Err|: 'static>,
}
struct Promise3<'a, T, Err> {
on_resolve:Option<|promised:T|: 'a>,
on_reject:Option<|failed:Err|: 'a>,
}
Tangibly, what is the difference between them?
What is 'Send' as a bound, and why when providing Send, do I no longer have to provide a lifetime? What is this implicit lifetime that Send is generating?
Specifically, what is the difference between Send and 'static as closure bounds.
For example, this works:
let k:|int|:Send = |i:int| {};
let p:|int|:Send = |i:int| {};
Promise1 {
on_resolve:Some(k),
on_reject:Some(p)
};
But this does not:
let k = |i:int| {};
let p = |i:int| {};
Promise1 {
on_resolve:Some(k),
on_reject:Some(p)
};
Error:
error: mismatched types: expected `core::option::Option<'static |_|:Send>`, found
`core::option::Option<|int|>` (expected bounds `Send`, found no bounds)
...however, this works fine using Promise2 or Promise3 with 'static and 'a respectively.
Send
is a 'kind' http://doc.rust-lang.org/reference.html#built-in-traits
send : Able to be sent across task boundaries.
'static
is a lifetime that's special: a lifetime that lasts for the entire program.
The reference also contains another illuminating section on Send
: (we haven't gotten an optimal layout for the reference yet) http://doc.rust-lang.org/reference.html#type-kinds
Send : Types of this kind can be safely sent between tasks. This kind includes scalars, boxes, procs, and structural types containing only other owned types. All Send types are 'static.
So that's why you can use them interchangeably in certain situations.
Why are we talking about a lifetime?
A closure embeds an environment, which may or not contain references to the current thread stack. This environment has a lifetime bound, which indicates the maximum duration for which it is viable and corresponds to the shortest lifetime of any embedded reference, which you indicate with the appropriate notation.
'static
is the upper bound, since it gives no restriction, and therefore 'static
is used to indicate the absence of any lifetime constraint. It neatly avoid a special case: there is always a lifetime bound, it is just that sometimes it's "infinite".
What does
Send
mean?
The Send
kind is applied to an object to indicate it can be sent to another thread safely, for example via a channel. It implies, thus, that said object carries no reference to the current thread stack, as otherwise should the stack unwind the object would contain dangling references!
Why does
Send
seem to imply'static
?
'static
Send
implies that an object has no reference to the current stack It is trivial, therefore, that Send
implies the lifetime bound of the object is 'static
.
But...
There are actually safe ways to refer to another stack's reference, for example in fork-join parallelism where the thread being referred to ensures it outlives the threads borrowing references. It was touched on here , and seem to require different kinds than Send
to precisely specify how the data can be safely shared.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.