Skip to content

Embrace infinite loops #35

@Ericson2314

Description

@Ericson2314

In https://github.com/nikomatsakis/nll-rfc/blob/master/0000-nonlexical-lifetimes.md#layer-2-avoiding-infinite-loops we have

let scope = Scope::new();
let mut foo = 22;

unsafe {
  // dtor joins the thread
  let _guard = scope.spawn(&mut foo);
  loop {
    foo += 1;
  }
  // drop of `_guard` joins the thread
}

in which, without "unwind" edges, _guard is not considered live because its destructor isn't run, so the code type checks. I think this methodology overly embraces the "destructors may not be run approach" we adopted after the Rc issue.

At least in unsafe code, it would be friendlier to have the rule "lvalues with Drop types are live from initialization until the destructor is run". Then _guard is considered live for all outgoing control flow, in which case the code doesn't type check. [As an optimization, we could reclaim the stack slot, but it's important not to adjust the duration of the borrow.]

Philosophically I don't like distinguishing between the lifetime of a value and the lifetime of a reference. I say all things are live until they are dropped, but if dropping is unobservable we are free to move the drop around in the CFG to get more code to type check. Shortening the like _guard, since it's drop is observable, is therefore only possible with a conceptually by adding a mem::forget call, which I consider unsavory.

CC @RalfJung @xfix

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions