@@ -360,11 +360,12 @@ impl UnsafetyState {
360
360
}
361
361
}
362
362
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 ) ]
368
369
enum Diverges {
369
370
/// Potentially unknown, some cases converge,
370
371
/// others require a CFG to determine them.
@@ -452,7 +453,37 @@ pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
452
453
453
454
ps : RefCell < UnsafetyState > ,
454
455
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`.
456
487
diverges : Cell < Diverges > ,
457
488
458
489
/// Whether any child nodes have any type errors.
0 commit comments