document the diverges flag etc

This commit is contained in:
Niko Matsakis 2017-03-17 11:10:12 -04:00
parent a6e6be5f88
commit 4967f1ae57

View File

@ -360,11 +360,12 @@ impl UnsafetyState {
}
}
/// Whether a node ever exits normally or not.
/// Tracked semi-automatically (through type variables
/// marked as diverging), with some manual adjustments
/// for control-flow primitives (approximating a CFG).
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
/// Tracks whether executing a node may exit normally (versus
/// return/break/panic, which "diverge", leaving dead code in their
/// wake). Tracked semi-automatically (through type variables marked
/// as diverging), with some manual adjustments for control-flow
/// primitives (approximating a CFG).
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
enum Diverges {
/// Potentially unknown, some cases converge,
/// others require a CFG to determine them.
@ -452,7 +453,37 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
ps: RefCell<UnsafetyState>,
/// Whether the last checked node can ever exit.
/// Whether the last checked node generates a divergence (e.g.,
/// `return` will set this to Always). In general, this is
/// typically set to *Maybe* on the way **down** the tree, and
/// then values are propagated **up** the tree. In a block, we
/// combine the results from statements and propagate the
/// end-result up.
///
/// We use this flag for two purposes:
///
/// - To warn about unreachable code: if, after processing a
/// sub-expression but before we have applied the effects of the
/// current node, we see that the flag is set to `Always`, we
/// can issue a warning. This corresponds to something like
/// `foo(return)`; we warn on the `foo()` expression. (We then
/// update the flag to `WarnedAlways` to suppress duplicate
/// reports.) Similarly, if we traverse to a fresh statement (or
/// tail expression) from a `Always` setting, we will isssue a
/// warning. This corresponds to something like `{return;
/// foo();}` or `{return; 22}`, where we would warn on the
/// `foo()` or `22`.
///
/// - To permit assignment into a local variable or other lvalue
/// (including the "return slot") of type `!`. This is allowed
/// if **either** the type of value being assigned is `!`, which
/// means the current code is dead, **or** the expression's
/// divering flag is true, which means that a divering value was
/// wrapped (e.g., `let x: ! = foo(return)`).
///
/// To repeat the last point: an expression represents dead-code
/// if, after checking it, **either** its type is `!` OR the
/// diverges flag is set to something other than `Maybe`.
diverges: Cell<Diverges>,
/// Whether any child nodes have any type errors.