[Withdrawn] Introduce `ScopedLt` and `InferredLt` (A variant of RFC PR 210)


#1

[This proposal is withdrawn.]

Summary:

Following the discussions about RFC PR 210, I propose that we introduce marker traits ScopedLt and InferredLt, instead of NoisyDrop and QuietDrop, and we implement a variant of RFC PR 210.

This does not strictly follow the RFC format.

Motivation:

I think we can have a more flexible and easier to understand variant of RFC PR 210.

“Detailed” Design:

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 ScopedLt. When owned by structs/enum variants, the structs/enums would have ScopedLt, even when other members have InferredLt. 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 InferredLt. Struct/enums would have InferredLt iff. all their fields have InferredLt. 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.

Note: ScopedLt and InferredLt don’t require the type to have Drop. Every type in Rust will have either ScopedLt or InferredLt.

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 ScopedLt objects.

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 Pinning:

A#[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?)

A #[lifetime(inferred)] attribute does the opposite to ScopedLt objects. (Hope I know what I am proposing.)

Advantages:

  1. Generalizes the NoisyDrop/QuietDrop concepts to non-Drop objects, 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?)

  2. With the guarantees that the compiler makes for InferredLt objects, it is possible to support very aggressive early dropping behavior (maybe as an optional optimization, all InferredLt objects get dropped ASAP), or revert to “out-of-band drop flags” easily in the future.

  3. I think ScopedLt/InferredLt names are more “direct” and “objective” than NoisyDrop/QuietDrop.

  4. 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 NoisyDrop/ScopedLt after all. But I may well be wrong.

Drawbacks:

We issue compile errors.

Alternatives:

  1. Go with RFC PR 210 unaltered (but the part about unsafe should still be considered).
  2. Use the new names (ScopedLt for NoisyDrop, InferredLt for QuietDrop), and unsafe treatments, but otherwise go with RFC PR 210.

Note:

If this get accepted, I hope the design would be merged into RFC PR 210.

EDIT: Grammar and clarification.