Open
Description
When or-patterns are present in a pattern, the drop order for its bindings depends on the particular language construct used. To see it in action, see this test (#142193), but in short:
let pat;
treats the bindings inpat
as being in the order they first appear in the pattern, and drops them in reverse order. This is the behavior I would expect.
// Drops are right-to-left: `z`, `y`, `x`.
let (x, Ok(y) | Err(y), z);
// The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
let ((true, x, y) | (false, y, x));
let pat = expr;
,if let
, andlet
-else
see bindings in or-patterns as being after other bindings, thus they're dropped first. i.e.
// Drops are right-to-left, treating `y` as rightmost: `y`, `z`, `x`.
let (x, Ok(y) | Err(y), z) = expr;
// The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
let ((true, x, y) | (false, y, x)) = expr;
match
arms see bindings in or-patterns as being after other bindings, and use the final or-pattern alternative's binding order, rather than the first. i.e.
// Drops are right-to-left, treating `y` as rightmost: `y`, `z`, `x`.
match expr { (x, Ok(y) | Err(y), z) => {} }
// The last or-pattern alternative determines the bindings' drop order: `x`, `y`.
match expr { (true, x, y) | (false, y, x) => {} }
- Function parameters are dropped in the usual right-to-left order, but the bindings within a parameter's pattern see bindings in or-patterns as being rightmost. i.e.
// Among separate params, the drop order is right-to-left: `z`, `y`, `x`.
(|x, (Ok(y) | Err(y)), z| {})(expr1, expr2, expr3);
// Within a param's pattern, or-patterns are treated as rightmost: `y`, `z`, `x`.
(|(x, Ok(y) | Err(y), z)| {})(expr);
// The first or-pattern alternative determines the bindings' drop order: `y`, `x`.
(|((true, x, y) | (false, y, x))| {})(expr);
Implementation-wise, this is due to differences in how pattern bindings are lowered to MIR.
- For
let pat;
, we traverse the pattern in a natural order and schedule drops for bindings here. - For anything that involves pattern-matching, we use the ordering of bindings seen by match lowering, which tests or-patterns last.
match
using the final or-pattern alternative's binding order is a detail of how match guards are currently implemented here. - Function parameters' patterns are lowered left-to-right, using the usual pattern-matching lowering for each individual parameter with a non-trivial pattern here.
If this should change, I imagine it will need a T-lang decision on what the correct behavior should be, so cc @rust-lang/lang
@rustbot label: +T-compiler +T-lang +A-MIR +A-patterns +A-destructors
Metadata
Metadata
Assignees
Labels
Area: Mid-level IR (MIR) - https://blog.rust-lang.org/2016/04/19/MIR.htmlArea: Destructors (`Drop`, …)Relating to patterns and pattern matchingCategory: This is a bug.Nominated for discussion during a lang team meeting.Lang team prioritization drag level 1. https://rust-lang.zulipchat.com/#narrow/channel/410516-t-langRelevant to the compiler team, which will review and decide on the PR/issue.Relevant to the language team