From bd1180818722de7d1f3b6f75d23a8c1c678116a1 Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 29 Jul 2025 15:33:50 -0700 Subject: [PATCH 1/2] Specify relative drop order of pattern bindings Edited-by: TC --- src/destructors.md | 46 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 43 insertions(+), 3 deletions(-) diff --git a/src/destructors.md b/src/destructors.md index 276f354c7..ff52f07f6 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -185,9 +185,48 @@ let declared_first = PrintOnDrop("Dropped last in outer scope"); let declared_last = PrintOnDrop("Dropped first in outer scope"); ``` -r[destructors.scope.bindings.match-pattern-order] -If multiple patterns are used in the same arm for a `match` expression, then an -unspecified pattern will be used to determine the drop order. +r[destructors.scope.bindings.pattern-drop-order] +If a pattern binds multiple variables, they are dropped in reverse order of declaration. + +```rust +# struct PrintOnDrop(&'static str); +# impl Drop for PrintOnDrop { +# fn drop(&mut self) { +# println!("drop({})", self.0); +# } +# } +let (declared_first, declared_last) = ( + PrintOnDrop("Dropped last"), + PrintOnDrop("Dropped first"), +); +``` + +r[destructors.scope.bindings.or-pattern-declaration-order] +For the purpose of drop order, [or-patterns] declare their bindings in the order given by their first sub-pattern. + +```rust +# struct PrintOnDrop(&'static str); +# impl Drop for PrintOnDrop { +# fn drop(&mut self) { +# println!("drop({})", self.0); +# } +# } +// Drops `declared_last`, then `declared_first`. +fn fixed_variable_drop_order( + (Ok([declared_first, declared_last]) + | Err([declared_last, declared_first])): Result<[T; 2], [T; 2]> +) {} + +fixed_variable_drop_order(Ok([ + PrintOnDrop("Dropped last"), + PrintOnDrop("Dropped first"), +])); + +fixed_variable_drop_order(Err([ + PrintOnDrop("Dropped first"), + PrintOnDrop("Dropped last"), +])); +``` r[destructors.scope.temporary] ### Temporary scopes @@ -473,6 +512,7 @@ There is one additional case to be aware of: when a panic reaches a [non-unwindi [Trait objects]: types/trait-object.md [tuple]: types/tuple.md +[or-patterns]: patterns.md#or-patterns [slice pattern]: patterns.md#slice-patterns [struct pattern]: patterns.md#struct-patterns [tuple pattern]: patterns.md#tuple-patterns From f153d01a1203586556e4e2b28871bd9a50bc6e32 Mon Sep 17 00:00:00 2001 From: Travis Cross Date: Tue, 5 Aug 2025 19:43:59 +0000 Subject: [PATCH 2/2] Revise editorially --- src/destructors.md | 39 +++++++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/src/destructors.md b/src/destructors.md index ff52f07f6..36e0fe1ed 100644 --- a/src/destructors.md +++ b/src/destructors.md @@ -185,8 +185,8 @@ let declared_first = PrintOnDrop("Dropped last in outer scope"); let declared_last = PrintOnDrop("Dropped first in outer scope"); ``` -r[destructors.scope.bindings.pattern-drop-order] -If a pattern binds multiple variables, they are dropped in reverse order of declaration. +r[destructors.scope.bindings.patterns] +Variables in patterns are dropped in reverse order of declaration within the pattern. ```rust # struct PrintOnDrop(&'static str); @@ -201,8 +201,8 @@ let (declared_first, declared_last) = ( ); ``` -r[destructors.scope.bindings.or-pattern-declaration-order] -For the purpose of drop order, [or-patterns] declare their bindings in the order given by their first sub-pattern. +r[destructors.scope.bindings.or-patterns] +For the purpose of drop order, [or-patterns] declare bindings in the order given by the first subpattern. ```rust # struct PrintOnDrop(&'static str); @@ -211,20 +211,31 @@ For the purpose of drop order, [or-patterns] declare their bindings in the order # println!("drop({})", self.0); # } # } -// Drops `declared_last`, then `declared_first`. -fn fixed_variable_drop_order( - (Ok([declared_first, declared_last]) - | Err([declared_last, declared_first])): Result<[T; 2], [T; 2]> +// Drops `x` before `y`. +fn or_pattern_drop_order( + (Ok([x, y]) | Err([y, x])): Result<[T; 2], [T; 2]> +// ^^^^^^^^^^ ^^^^^^^^^^^ This is the second subpattern. +// | +// This is the first subpattern. +// +// In the first subpattern, `x` is declared before `y`. Since it is +// the first subpattern, that is the order used even if the second +// subpattern, where the bindings are declared in the opposite +// order, is matched. ) {} -fixed_variable_drop_order(Ok([ - PrintOnDrop("Dropped last"), - PrintOnDrop("Dropped first"), +// Here we match the first subpattern, and the drops happen according +// to the declaration order in the first subpattern. +or_pattern_drop_order(Ok([ + PrintOnDrop("Declared first, dropped last"), + PrintOnDrop("Declared last, dropped first"), ])); -fixed_variable_drop_order(Err([ - PrintOnDrop("Dropped first"), - PrintOnDrop("Dropped last"), +// Here we match the second subpattern, and the drops still happen +// according to the declaration order in the first subpattern. +or_pattern_drop_order(Err([ + PrintOnDrop("Declared last, dropped first"), + PrintOnDrop("Declared first, dropped last"), ])); ```