Skip to content

Commit 4967f1a

Browse files
committed
document the diverges flag etc
1 parent a6e6be5 commit 4967f1a

File tree

1 file changed

+37
-6
lines changed
  • src/librustc_typeck/check

1 file changed

+37
-6
lines changed

src/librustc_typeck/check/mod.rs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -360,11 +360,12 @@ impl UnsafetyState {
360360
}
361361
}
362362

363-
/// Whether a node ever exits normally or not.
364-
/// Tracked semi-automatically (through type variables
365-
/// marked as diverging), with some manual adjustments
366-
/// for control-flow primitives (approximating a CFG).
367-
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
363+
/// Tracks whether executing a node may exit normally (versus
364+
/// return/break/panic, which "diverge", leaving dead code in their
365+
/// wake). Tracked semi-automatically (through type variables marked
366+
/// as diverging), with some manual adjustments for control-flow
367+
/// primitives (approximating a CFG).
368+
#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
368369
enum Diverges {
369370
/// Potentially unknown, some cases converge,
370371
/// others require a CFG to determine them.
@@ -452,7 +453,37 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
452453

453454
ps: RefCell<UnsafetyState>,
454455

455-
/// Whether the last checked node can ever exit.
456+
/// Whether the last checked node generates a divergence (e.g.,
457+
/// `return` will set this to Always). In general, this is
458+
/// typically set to *Maybe* on the way **down** the tree, and
459+
/// then values are propagated **up** the tree. In a block, we
460+
/// combine the results from statements and propagate the
461+
/// end-result up.
462+
///
463+
/// We use this flag for two purposes:
464+
///
465+
/// - To warn about unreachable code: if, after processing a
466+
/// sub-expression but before we have applied the effects of the
467+
/// current node, we see that the flag is set to `Always`, we
468+
/// can issue a warning. This corresponds to something like
469+
/// `foo(return)`; we warn on the `foo()` expression. (We then
470+
/// update the flag to `WarnedAlways` to suppress duplicate
471+
/// reports.) Similarly, if we traverse to a fresh statement (or
472+
/// tail expression) from a `Always` setting, we will isssue a
473+
/// warning. This corresponds to something like `{return;
474+
/// foo();}` or `{return; 22}`, where we would warn on the
475+
/// `foo()` or `22`.
476+
///
477+
/// - To permit assignment into a local variable or other lvalue
478+
/// (including the "return slot") of type `!`. This is allowed
479+
/// if **either** the type of value being assigned is `!`, which
480+
/// means the current code is dead, **or** the expression's
481+
/// divering flag is true, which means that a divering value was
482+
/// wrapped (e.g., `let x: ! = foo(return)`).
483+
///
484+
/// To repeat the last point: an expression represents dead-code
485+
/// if, after checking it, **either** its type is `!` OR the
486+
/// diverges flag is set to something other than `Maybe`.
456487
diverges: Cell<Diverges>,
457488

458489
/// Whether any child nodes have any type errors.

0 commit comments

Comments
 (0)