[This proposal is withdrawn.]
Following the discussions about RFC PR 210, I propose that we introduce marker traits
InferredLt, instead of
QuietDrop, and we implement a variant of RFC PR 210.
This does not strictly follow the RFC format.
I think we can have a more flexible and easier to understand variant of RFC PR 210.
ScopedLt, “Scoped Lifetime”, is for types whose lifetimes we care about a lot. We must make sure that they are dropped/made unavailable exactly at certain places, and we want to clearly see the drop points. Often, that is because the drops have side effects.
InferredLt, “Inferred Lifetime”, is for types whose lifetimes we don’t quite care about. They can be dropped/made unavailable as soon as possible, or at scope boundaries, or anywhere in-between, without changing program semantics. The only observable difference should be performance.
ScopedLt object semantics:
When stored in local variables, or used as temporaries, their lifetimes are guaranteed by the compiler to be exactly as long as the enclosing scope dictates.
When owned by owning containers (Box, Vec, etc), they make the containers themselves to have
When owned by structs/enum variants, the structs/enums would have
ScopedLt, even when other members have
They cannot be pointed to by Rc/Arc/Gc.
(We care too much about their lifetimes to allow them to be put into Rc/Arc/Gc.)
InferredLt object semantics:
When stored in local variables, or used as temporaries, their lifetime are guaranteed by the compiler to be at most as long as the enclosing scope dictates.
When owned by owning containers, they make the containers themselves to have
Struct/enums would have
InferredLt iff. all their fields have
When pointed to by Rc/Arc/Gc, their lifetimes are “dynamically inferred” following Rc/Arc/Gc’s semantics.
Rc/Arc/Gc pointers themselves have
InferredLt don’t require the type to have
Drop. Every type in Rust will have either
Variation to RFC PR 210:
In my variant of RFC PR 210, when the compiler determines that it cannot fulfill the drop obligations with “explicit scope boundary drops”, it can insert implicit drops when the offenders are
InferredLt objects, but must report compile errors for
And in a function with unsafe blocks, all objects are considered to have scoped lifetimes, because the compiler almost cannot make any guarantee about what the unsafe code would do. That means the programmer must deal with drop obligation unfulfillment completely manually there.
#[lifetime(scoped)] attribute can be used to “pin”
InferredLt objects to the scoped lifetimes, on a per-object/function/module/crate basis. (Is this possible?)
#[lifetime(inferred)] attribute does the opposite to
ScopedLt objects. (Hope I know what I am proposing.)
QuietDropconcepts to non-
Dropobjects, and make it possible to unify lifetime handling of references and non-reference objects in the future. (We are implementing non-lexical reference lifetimes now, right?)
With the guarantees that the compiler makes for
InferredLtobjects, it is possible to support very aggressive early dropping behavior (maybe as an optional optimization, all
InferredLtobjects get dropped ASAP), or revert to “out-of-band drop flags” easily in the future.
InferredLtnames are more “direct” and “objective” than
We issue compile errors.
Why do we want an early drop of
NoisyDrop objects to be “noisy”? Because we think that this early drop may have unexpected behavior, and making it happen at scope boundary can make the intention clear.
If so, why don’t we force the programmer to do it, instead of just a warning?
I suspect there are not many types that should have
ScopedLt after all. But I may well be wrong.
We issue compile errors.
- Go with RFC PR 210 unaltered (but the part about
unsafeshould still be considered).
- Use the new names (
unsafetreatments, but otherwise go with RFC PR 210.
If this get accepted, I hope the design would be merged into RFC PR 210.
EDIT: Grammar and clarification.