• F
    Ensure dataflow of a proc never looks at blocks from closed-over context. · 263a433f
    Felix S. Klock II 提交于
    Details: in a program like:
    ```
    type T = proc(int) -> int; /* 4 */
    
    pub fn outer(captured /* pat 16 */: T) -> T {
        (proc(x /* pat 23 */) {
            ((captured /* 29 */).foo((x /* 30 */)) /* 28 */)
        } /* block 27 */ /* 20 */)
    } /* block 19 */ /* 12 */
    ```
    the `captured` arg is moved from the outer fn into the inner proc (id=20).
    
    The old dataflow analysis for flowed_move_data_moves, when looking at
    the inner proc, would attempt to add a kill bit for `captured` at the
    end of its scope; the problem is that it thought the end of the
    `captured` arg's scope was the outer fn (id=12), even though at that
    point in the analysis, the `captured` arg's scope should now be
    restricted to the proc itself (id=20).
    
    This patch fixes handling of upvars so that dataflow of a fn/proc
    should never attempts to add a gen or kill bit to any NodeId outside
    of the current fn/proc.  It accomplishes this by adding an `LpUpvar`
    variant to `borrowck::LoanPath`, so for cases like `captured` above
    will carry both their original `var_id`, as before, as well as the
    `NodeId` for the closure that is capturing them.
    
    As a drive-by fix to another occurrence of a similar bug that
    nikomatsakis pointed out to me earlier, this also fixes
    `gather_loans::compute_kill_scope` so that it computes the kill scope
    of the `captured` arg to be block 27; that is, the block for the proc
    itself (id=20).
    
    (This is an updated version that generalizes the new loan path variant
    to cover all upvars, and thus renamed the variant from `LpCopiedUpvar`
    to just `LpUpvar`.)
    263a433f
dataflow.rs 21.6 KB