From 1abbf0cfc957ff7f7bfa8ed0de22015613a375aa Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 14 Apr 2020 17:18:40 +0100 Subject: [PATCH 01/29] Initial draft of `destructuring_assignments` RFC --- text/0000-destructuring-assignment.md | 215 ++++++++++++++++++++++++++ 1 file changed, 215 insertions(+) create mode 100644 text/0000-destructuring-assignment.md diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md new file mode 100644 index 00000000000..ee2af9d7321 --- /dev/null +++ b/text/0000-destructuring-assignment.md @@ -0,0 +1,215 @@ +- Feature Name: `destructuring_assignment` +- Start Date: 2020-04-17 +- RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) +- Rust Issue: [rust-lang/rust#71126](https://github.com/rust-lang/rust/issues/71126) + +# Summary +[summary]: #summary + +We allow destructuring on assignment, as in `let` declarations. For instance, the following are now +accepted: + +```rust +(a, b) = (0, 1); +(x, y, .., z) = (1.0, 2.0, 3.0, 4.0, 5.0); +[_, f] = foo(); +Struct { c: d, d: c } = bar(); +``` + +This brings assignment in line with `let` declaration, in which destructuring is permitted. This +will simplify and improve idiomatic code involving mutability. + +# Motivation +[motivation]: #motivation + +Destructuring assignment increases the consistency of the language, in which assignment is typically +expected to behave similarly to variable declations. The aim is that this feature will increase the +clarity and concision of idiomatic Rust, primarily in code that makes use of mutability. This +feature is +[highly desired among Rust developers](https://github.com/rust-lang/rfcs/issues/372). + +# Guide-level explanation +[guide-level-explanation]: #guide-level-explanation + +You may destructure a value when making an assignment, just as when you declare variables. See the +[Summary](#Summary) for examples. + +# Reference-level explanation +[reference-level-explanation]: #reference-level-explanation + +The feature as described here has been implemented as a proof-of-concept. It follows essentially the +[suggestions of @Kimundi](https://github.com/rust-lang/rfcs/issues/372#issuecomment-214022963) and +[of @drunwald](https://github.com/rust-lang/rfcs/issues/372#issuecomment-262519146). + +The Rust compiler already parses complex expressions on the left-hand side of an assignment, but +does not handle them other than emitting an error later in compilation. We propose to add +special-casing for several classes of expressions on the left-hand side of an assignment, which act +in accordance with destructuring assignment: i.e. as if the left-hand side were actually a pattern. +Actually supporting patterns directly on the left-hand side of an assignment significantly +complicates Rust's grammar and it is not clear that it is even technically feasible. Conversely, +handling some classes of expressions is much simpler, and is indistinguishable to users, who will +receive pattern-oriented diagnostics due to the desugaring of expressions into patterns. + +The general idea is that we will desugar the following complex assignments as demonstrated. + +```rust +(a, b) = (3, 4); + +[a, b] = [3, 4]; + +Struct { x: a, y: b } = Struct { x: 3, y: 4}; + +// desugars to: + +{ + let (_a, _b) = (3, 4); + a = _a; + b = _b; +} + +{ + let [_a, _b] = [3, 4]; + a = _a; + b = _b; +} + +{ + let Struct { x: _a, y: _b } = Struct { x: 3, y: 4}; + a = _a; + b = _b; +} +``` + +We support the following classes of expressions: + +- Tuples. +- Slices. +- (Tuple) structs. + +In the desugaring, we convert the expression `(a, b)` into an analogous pattern `(_a, _b)` (whose +identifiers are fresh and thus do not conflict with existing variables). A nice side-effect is that +we inherit the diagnostics for normal pattern-matching, so users benefit from existing diagnostics for destructuring declarations. + +## Underscores and ellipses + +In patterns, we may use `_` and `..` to ignore certain values, without binding them. While range +patterns already have analogues in terms of range expressions, the underscore wildcard pattern +currently has no analogous expression. We thus add one, which is only permitted in the left-hand side +of an assignment: any other use results in the same "reserved identifier" error that currently +occurs for invalid uses of `_` as an expression. A consequence is that the following becomes valid: + +```rust +_ = 5; +``` + +Functional record update syntax (i.e. `..x`) is forbidden in destructuring assignment, as we believe +there is no sensible and clear semantics for it in this setting. This restriction could be relaxed +in the future if a use-case is found. + +## Compound destructuring assignment + +We forbid destructuring compound assignment, i.e. destructuring for operators like `+=`, `*=` and so +on. This is both for the sake of simplicity and since there are relevant design questions that do not have obvious answers, +e.g. how this could interact with custom implementations of the operators. + +## Order-of-assignment + +In a declaration, each identifier may be bound at most once. That is, the following is invalid: + +```rust +let (a, a) = (1, 2); +``` + +For destructuring assignments, we currently permit assignments containing identical identifiers, with assignments performed left-to-right. However, these trigger an "unused assignment" +warning. Assignments are performed left-to-right. + +```rust +(a, a) = (1, 2); // warning: value assigned to `a` is never read +assert_eq!(a, 2); +``` + +We could try to explicitly forbid this. However, the chosen behaviour is justified in two ways: +- A destructuring +assignment can always be written as a series of assignments, so this behaviour matches its +expansion. +- In general, we are not able to tell when overlapping +assignments are made, so the error would be fallible. This is illustrated by the following example: + +```rust +fn foo<'a>(x: &'a mut u32) -> &'a mut u32 { + x +} + +fn main() { + let mut x: u32 = 10; + // We cannot tell that the same variable is being assigned to + // in this instance. + (*foo(&mut x), *foo(&mut x)) = (5, 6); + assert_eq!(x, 6); +} +``` + +We thus feel that a lint is more appropriate. + +# Drawbacks +[drawbacks]: #drawbacks + +We find no convincing reason not to allow this. Though technically this increases the complexity of +the compiler, it does so minimally: the desugaring is noninvasive and simple. On the other hand, for +users, this change makes the language feel more consistent and decreases surprise, as evidenced by the discussion in [the open issue](https://github.com/rust-lang/rfcs/issues/372) for this feature. + +# Rationale and alternatives +[rationale-and-alternatives]: #rationale-and-alternatives + +As we argue above, we believe this change increases the perceived consistency of Rust and improves +idiomatic code in the presence of mutability, and that the +implementation is simple and intuitive. + +One potential alternative that has been put forth in the past is to allow arbitrary patterns on the left-hand side of an assignment, +but as discussed above and [extensively in this +thread](https://github.com/rust-lang/rfcs/issues/372), it is difficult to see how this could work in +practice (especially with complex left-hand sides that do not simply involve identifiers) and it is not clear that this would have any advantages. + +# Prior art +[prior-art]: #prior-art + +The most persuasive prior art is Rust itself, which already permits destructuring +declarations. Intuitively, a declaration is an assignment that also introduces a new binding. +Therefore, it seems clear that assignments should act similarly to declarations where possible. +However, it is also the case that destructuring assignments are present in many languages that permit destructuring +declarations. + +- JavaScript +[supports destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment). +- Python [supports destructuring assignment](https://blog.tecladocode.com/destructuring-in-python/). +- Perl +[supports destructuring assignment](https://perl6advent.wordpress.com/2017/12/05/day-5-destructure-your-arguments-with-perl-6-signatures/). +- And so on... + +It is a general pattern that languages support destructuring assignment when they support +destructuring declarations. + +# Unresolved questions +[unresolved-questions]: #unresolved-questions + +None. + +# Future possibilities +[future-possibilities]: #future-possibilities + +- The implementation already supports destructuring of every class of expressions that currently make +sense in Rust. This feature naturally should be extended to any new class of expressions for which +it makes sense. +- It could make sense to permit +[destructuring compound assignments](#Compound-destructuring-assignment) in the future, though we +defer this question for later discussions. +- It [has been suggested](https://github.com/rust-lang/rfcs/issues/372#issuecomment-365606878) that +mixed declarations and assignments could be permitted, as in the following: + +```rust +let a; +(a, let b) = (1, 2); +assert_eq!((a, b), (1, 2)); +``` + +We do not pursue this here, but note that it would be compatible with our desugaring. From 49e9b8022587095f796ad53739e9dcf67715c298 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 14 Apr 2020 20:57:08 +0100 Subject: [PATCH 02/29] Be explicit about pattern diagnostics --- text/0000-destructuring-assignment.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index ee2af9d7321..72f10de2a06 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -90,6 +90,15 @@ In the desugaring, we convert the expression `(a, b)` into an analogous pattern identifiers are fresh and thus do not conflict with existing variables). A nice side-effect is that we inherit the diagnostics for normal pattern-matching, so users benefit from existing diagnostics for destructuring declarations. +## Diagnostics + +It is worth being explicit that in with implementation, the diagnostics that are reported are +pattern diagnostics: that is, because the desugaring occurs regardless, the messages will imply that +the left-hand side of an assignment is a true pattern (the one the expression has been converted +to). We think that this results in a better user experience, as intuitively the left-hand side of a +destructuring assignment acts like a pattern "in spirit", but this is technically false: we should +be careful that this does not result in misleading diagnostics. + ## Underscores and ellipses In patterns, we may use `_` and `..` to ignore certain values, without binding them. While range From e2ea3c1824e835630873b95145501f532b0e14d0 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 14 Apr 2020 20:57:41 +0100 Subject: [PATCH 03/29] Alpha-rename --- text/0000-destructuring-assignment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 72f10de2a06..d6e4415a710 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -13,7 +13,7 @@ accepted: (a, b) = (0, 1); (x, y, .., z) = (1.0, 2.0, 3.0, 4.0, 5.0); [_, f] = foo(); -Struct { c: d, d: c } = bar(); +Struct { x: a, y: b } = bar(); ``` This brings assignment in line with `let` declaration, in which destructuring is permitted. This From 9d5cb89e7ae7aa7283e81a74d30ebac343bf55c7 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 14 Apr 2020 21:02:31 +0100 Subject: [PATCH 04/29] Explain desugaring for `_` and `..` --- text/0000-destructuring-assignment.md | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index d6e4415a710..2c81772f63b 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -115,6 +115,26 @@ Functional record update syntax (i.e. `..x`) is forbidden in destructuring assig there is no sensible and clear semantics for it in this setting. This restriction could be relaxed in the future if a use-case is found. +The desugaring treats the `_` expression as an `_` pattern and the fully empty range `..` as a `..` pattern. No corresponding assignments are generated. For example: + +```rust +let mut a; +(a, _) = (3, 4); +(.., a) = (1, 2, 3, 4); + +// desugars to: + +{ + let (_a, _) = (3, 4); + a = _a; +} + +{ + let (.., _a) = (1, 2, 3, 4); + a = _a; +} +``` + ## Compound destructuring assignment We forbid destructuring compound assignment, i.e. destructuring for operators like `+=`, `*=` and so From 6d4afd56b4d4293f9d7a6592382c70ccba12dcf8 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 14 Apr 2020 21:04:34 +0100 Subject: [PATCH 05/29] Give examples in guide-level explanation --- text/0000-destructuring-assignment.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 2c81772f63b..fa6f6e8b6b6 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -32,7 +32,13 @@ feature is [guide-level-explanation]: #guide-level-explanation You may destructure a value when making an assignment, just as when you declare variables. See the -[Summary](#Summary) for examples. +[Summary](#Summary) for examples. The following structures may be destructured: + +- Tuples. +- Slices. +- (Tuple) structs. + +You may use `_` and `..` as in a normal declaration pattern to ignore certain values. # Reference-level explanation [reference-level-explanation]: #reference-level-explanation From 24404a37de9d199ebb07ad1f97a5f06261fa637b Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 14 Apr 2020 21:10:48 +0100 Subject: [PATCH 06/29] Clarify order-of-execution --- text/0000-destructuring-assignment.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index fa6f6e8b6b6..19aabefce23 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -149,14 +149,16 @@ e.g. how this could interact with custom implementations of the operators. ## Order-of-assignment +The right-hand side of the assignment is always performed first. Then, assignments are performed left-to-right. Note that component expressions in the left-hand side may be complex, not simply identifiers, and may require execution to resolve to lvalues. + In a declaration, each identifier may be bound at most once. That is, the following is invalid: ```rust let (a, a) = (1, 2); ``` -For destructuring assignments, we currently permit assignments containing identical identifiers, with assignments performed left-to-right. However, these trigger an "unused assignment" -warning. Assignments are performed left-to-right. +For destructuring assignments, we currently permit assignments containing identical identifiers. However, these trigger an "unused assignment" +warning. ```rust (a, a) = (1, 2); // warning: value assigned to `a` is never read From 7f3edecda970655ef80e4c61b8ec66ee8e38fbff Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 14 Apr 2020 21:40:19 +0100 Subject: [PATCH 07/29] Tweak the order-of-assignment text --- text/0000-destructuring-assignment.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 19aabefce23..8326a0c05a4 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -101,7 +101,14 @@ we inherit the diagnostics for normal pattern-matching, so users benefit from ex It is worth being explicit that in with implementation, the diagnostics that are reported are pattern diagnostics: that is, because the desugaring occurs regardless, the messages will imply that the left-hand side of an assignment is a true pattern (the one the expression has been converted -to). We think that this results in a better user experience, as intuitively the left-hand side of a +to). For example: + +```rust +[*a] = [1, 2]; // error: pattern requires 1 element but array has 2 +``` + +Whilst `[*a]` is not strictly speaking a pattern, it behaves similarly to one in this context. We +think that this results in a better user experience, as intuitively the left-hand side of a destructuring assignment acts like a pattern "in spirit", but this is technically false: we should be careful that this does not result in misleading diagnostics. @@ -149,7 +156,9 @@ e.g. how this could interact with custom implementations of the operators. ## Order-of-assignment -The right-hand side of the assignment is always performed first. Then, assignments are performed left-to-right. Note that component expressions in the left-hand side may be complex, not simply identifiers, and may require execution to resolve to lvalues. +The right-hand side of the assignment is always evaluated first. Then, assignments are performed +left-to-right. Note that component expressions in the left-hand side may be complex, and not simply +identifiers. In a declaration, each identifier may be bound at most once. That is, the following is invalid: From eab6125d6eb3a9aba9fd2fc7f3af7f602e73bab5 Mon Sep 17 00:00:00 2001 From: varkor Date: Tue, 14 Apr 2020 22:01:06 +0100 Subject: [PATCH 08/29] Add actual drawbacks --- text/0000-destructuring-assignment.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 8326a0c05a4..aca99fce20c 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -200,9 +200,8 @@ We thus feel that a lint is more appropriate. # Drawbacks [drawbacks]: #drawbacks -We find no convincing reason not to allow this. Though technically this increases the complexity of -the compiler, it does so minimally: the desugaring is noninvasive and simple. On the other hand, for -users, this change makes the language feel more consistent and decreases surprise, as evidenced by the discussion in [the open issue](https://github.com/rust-lang/rfcs/issues/372) for this feature. +- It could be argued that this feature increases the surface area of the language and thus complexity. However, we feel that by decreasing surprise, it actually makes the language less complex for users. +- It is possible that these changes could result in some confusing diagnostics. However, we have not found any during testing, and these could in any case be ironed out before stabilisation. # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives From 111b63011b2f150db3b5897eadbeedb35ee11e22 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 15 Apr 2020 00:19:21 +0100 Subject: [PATCH 09/29] Add link to implementation PoC --- text/0000-destructuring-assignment.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index aca99fce20c..0e4ad320957 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -2,6 +2,7 @@ - Start Date: 2020-04-17 - RFC PR: [rust-lang/rfcs#0000](https://github.com/rust-lang/rfcs/pull/0000) - Rust Issue: [rust-lang/rust#71126](https://github.com/rust-lang/rust/issues/71126) +- Proof-of-concept: [rust-lang/rust#71156](https://github.com/rust-lang/rust/pull/71156) # Summary [summary]: #summary @@ -43,7 +44,7 @@ You may use `_` and `..` as in a normal declaration pattern to ignore certain va # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -The feature as described here has been implemented as a proof-of-concept. It follows essentially the +The feature as described here has been implemented as a proof-of-concept (https://github.com/rust-lang/rust/pull/71156). It follows essentially the [suggestions of @Kimundi](https://github.com/rust-lang/rfcs/issues/372#issuecomment-214022963) and [of @drunwald](https://github.com/rust-lang/rfcs/issues/372#issuecomment-262519146). From c773c5041fbf27af3d7ff7932263a430652ab30a Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 15 Apr 2020 12:19:10 +0100 Subject: [PATCH 10/29] Add note about `ref` and `&` --- text/0000-destructuring-assignment.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 0e4ad320957..c4a5316c5cd 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -99,7 +99,7 @@ we inherit the diagnostics for normal pattern-matching, so users benefit from ex ## Diagnostics -It is worth being explicit that in with implementation, the diagnostics that are reported are +It is worth being explicit that, in the implementation, the diagnostics that are reported are pattern diagnostics: that is, because the desugaring occurs regardless, the messages will imply that the left-hand side of an assignment is a true pattern (the one the expression has been converted to). For example: @@ -149,6 +149,23 @@ let mut a; } ``` +## Unsupported patterns + +We do not support the following "patterns" in destructuring assignment: + +- `&x = foo();`. +- `&mut x = foo();`. +- `ref x = foo();`. + +This is primarily for learnability: the behaviour of `&` can already be slightly confusing to +newcomers, as it has different meanings depending on whether it is used in an expression or pattern. +In destructuring assignment, the left-hand side of an assignment consists of sub*expressions*, but +which act intuitively like patterns, so it is not clear what `&` and friends should mean. We feel it is more +confusing than helpful to allow these cases. Conversely, destructuring tuples, slices or structs is +very natural and we do not foresee confusion with allowing these. + +Our implementation is forwards-compatible with allowing these patterns in destructuring assigmnent, in any case, so we lose nothing by not allowing them from the start. + ## Compound destructuring assignment We forbid destructuring compound assignment, i.e. destructuring for operators like `+=`, `*=` and so @@ -249,6 +266,7 @@ it makes sense. - It could make sense to permit [destructuring compound assignments](#Compound-destructuring-assignment) in the future, though we defer this question for later discussions. +- It could make sense to permit [`ref` and `&`](#Unsupported-patterns) in the future. - It [has been suggested](https://github.com/rust-lang/rfcs/issues/372#issuecomment-365606878) that mixed declarations and assignments could be permitted, as in the following: From d7e5e61ec54683d60dffc330ae06f2ac20abf62b Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 15 Apr 2020 12:23:00 +0100 Subject: [PATCH 11/29] Add slice `..` example --- text/0000-destructuring-assignment.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index c4a5316c5cd..862717b234b 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -14,6 +14,7 @@ accepted: (a, b) = (0, 1); (x, y, .., z) = (1.0, 2.0, 3.0, 4.0, 5.0); [_, f] = foo(); +[g, _, h, ..] = ['a', 'w', 'e', 's', 'o', 'm', 'e', '!']; Struct { x: a, y: b } = bar(); ``` @@ -149,6 +150,8 @@ let mut a; } ``` +and similarly for slices and structs. + ## Unsupported patterns We do not support the following "patterns" in destructuring assignment: From cd0845231c6d0a5dffa70210ebe890f10ccee4da Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 20:53:21 +0100 Subject: [PATCH 12/29] Fix typo and make clarification --- text/0000-destructuring-assignment.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 862717b234b..c52962a5f24 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -25,10 +25,9 @@ will simplify and improve idiomatic code involving mutability. [motivation]: #motivation Destructuring assignment increases the consistency of the language, in which assignment is typically -expected to behave similarly to variable declations. The aim is that this feature will increase the -clarity and concision of idiomatic Rust, primarily in code that makes use of mutability. This -feature is -[highly desired among Rust developers](https://github.com/rust-lang/rfcs/issues/372). +expected to behave similarly to variable declarations. The aim is that this feature will increase +the clarity and concision of idiomatic Rust, primarily in code that makes use of mutability. This +feature is [highly desired among Rust developers](https://github.com/rust-lang/rfcs/issues/372). # Guide-level explanation [guide-level-explanation]: #guide-level-explanation @@ -38,7 +37,7 @@ You may destructure a value when making an assignment, just as when you declare - Tuples. - Slices. -- (Tuple) structs. +- Structs (inclduing unit and tuple structs). You may use `_` and `..` as in a normal declaration pattern to ignore certain values. @@ -92,7 +91,7 @@ We support the following classes of expressions: - Tuples. - Slices. -- (Tuple) structs. +- Structs (inclduing unit and tuple structs). In the desugaring, we convert the expression `(a, b)` into an analogous pattern `(_a, _b)` (whose identifiers are fresh and thus do not conflict with existing variables). A nice side-effect is that From 612bbbe945a5b37fb81e5add303378353033d775 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 20:53:31 +0100 Subject: [PATCH 13/29] Clarify that nested structures may be destructured --- text/0000-destructuring-assignment.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index c52962a5f24..efb617ab847 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -95,7 +95,25 @@ We support the following classes of expressions: In the desugaring, we convert the expression `(a, b)` into an analogous pattern `(_a, _b)` (whose identifiers are fresh and thus do not conflict with existing variables). A nice side-effect is that -we inherit the diagnostics for normal pattern-matching, so users benefit from existing diagnostics for destructuring declarations. +we inherit the diagnostics for normal pattern-matching, so users benefit from existing diagnostics +for destructuring declarations. + +Nested structures are destructured appropriately, for instance: + +```rust +let (a, b, c); +((a, b), c) = ((1, 2), 3); + +// desugars to: + +let (a, b, c); +{ + let ((_a, _b), _c) = ((1, 2), 3); + a = _a; + b = _b; + c = _c; +}; +``` ## Diagnostics From 27f032e7e8f113aad34959a29bd7520e978e9848 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 20:56:09 +0100 Subject: [PATCH 14/29] Add a nested assignment to the first example --- text/0000-destructuring-assignment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index efb617ab847..3df2acc5400 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -11,7 +11,7 @@ We allow destructuring on assignment, as in `let` declarations. For instance, th accepted: ```rust -(a, b) = (0, 1); +(a, (b, c)) = (0, (1, 2)); (x, y, .., z) = (1.0, 2.0, 3.0, 4.0, 5.0); [_, f] = foo(); [g, _, h, ..] = ['a', 'w', 'e', 's', 'o', 'm', 'e', '!']; From f0d822481b25f4317029c9ed01010983b1e0d6f9 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 21:04:08 +0100 Subject: [PATCH 15/29] Add note about single-variant enums and `#[non_exhaustive]` --- text/0000-destructuring-assignment.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 3df2acc5400..e01dbce519f 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -38,6 +38,7 @@ You may destructure a value when making an assignment, just as when you declare - Tuples. - Slices. - Structs (inclduing unit and tuple structs). +- Unique variants of enums. You may use `_` and `..` as in a normal declaration pattern to ignore certain values. @@ -92,6 +93,7 @@ We support the following classes of expressions: - Tuples. - Slices. - Structs (inclduing unit and tuple structs). +- Unique variants of enums. In the desugaring, we convert the expression `(a, b)` into an analogous pattern `(_a, _b)` (whose identifiers are fresh and thus do not conflict with existing variables). A nice side-effect is that @@ -115,6 +117,10 @@ let (a, b, c); }; ``` +Note that `#[non_exhaustive]` must be taken into account properly: enums marked `#[non_exhaustive]` +may not have their variants destructured, and structs marked `#[non_exhaustive]` may only be +destructured using `..`. + ## Diagnostics It is worth being explicit that, in the implementation, the diagnostics that are reported are From 7aa1e9697b94e628c6ddd885bbb7d43156d787d0 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 21:10:49 +0100 Subject: [PATCH 16/29] Add note about parentheses --- text/0000-destructuring-assignment.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index e01dbce519f..9014860905f 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -117,6 +117,9 @@ let (a, b, c); }; ``` +We also allow arbitrary parenthesisation, as with patterns, although unnecessary parentheses will +trigger the `unused_parens` lint. + Note that `#[non_exhaustive]` must be taken into account properly: enums marked `#[non_exhaustive]` may not have their variants destructured, and structs marked `#[non_exhaustive]` may only be destructured using `..`. From b599f3eb9191d601dc3bb880de387693d9d4573e Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 21:11:02 +0100 Subject: [PATCH 17/29] Extend list of unsupported patterns for comprehensiveness --- text/0000-destructuring-assignment.md | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 9014860905f..dd2e613a2da 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -156,7 +156,8 @@ Functional record update syntax (i.e. `..x`) is forbidden in destructuring assig there is no sensible and clear semantics for it in this setting. This restriction could be relaxed in the future if a use-case is found. -The desugaring treats the `_` expression as an `_` pattern and the fully empty range `..` as a `..` pattern. No corresponding assignments are generated. For example: +The desugaring treats the `_` expression as an `_` pattern and the fully empty range `..` as a `..` +pattern. No corresponding assignments are generated. For example: ```rust let mut a; @@ -185,15 +186,24 @@ We do not support the following "patterns" in destructuring assignment: - `&x = foo();`. - `&mut x = foo();`. - `ref x = foo();`. +- (`box` patterns, which are deprecated.) This is primarily for learnability: the behaviour of `&` can already be slightly confusing to newcomers, as it has different meanings depending on whether it is used in an expression or pattern. In destructuring assignment, the left-hand side of an assignment consists of sub*expressions*, but -which act intuitively like patterns, so it is not clear what `&` and friends should mean. We feel it is more -confusing than helpful to allow these cases. Conversely, destructuring tuples, slices or structs is -very natural and we do not foresee confusion with allowing these. +which act intuitively like patterns, so it is not clear what `&` and friends should mean. We feel it +is more confusing than helpful to allow these cases. Conversely, destructuring tuples, slices or +structs is very natural and we do not foresee confusion with allowing these. -Our implementation is forwards-compatible with allowing these patterns in destructuring assigmnent, in any case, so we lose nothing by not allowing them from the start. +Our implementation is forwards-compatible with allowing these patterns in destructuring assigmnent, +in any case, so we lose nothing by not allowing them from the start. + +Additionally, we do not give analogues for any of the following, which make little sense in this +context: + +- Literal patterns. +- Range patterns. +- Or patterns. ## Compound destructuring assignment From b79d556ec59823b65aad7cfb36e17bf16510873c Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 21:19:08 +0100 Subject: [PATCH 18/29] Mention that destructuring assignment is an expression --- text/0000-destructuring-assignment.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index dd2e613a2da..d0097ee04c6 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -88,6 +88,9 @@ Struct { x: a, y: b } = Struct { x: 3, y: 4}; } ``` +Note that the desugaring ensures that destructuring assignment, like normal assignment, is an +expression. + We support the following classes of expressions: - Tuples. From 80b6f4d58bbd4d29c5c81119e442c80505538943 Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 21:35:06 +0100 Subject: [PATCH 19/29] Mention `@` --- text/0000-destructuring-assignment.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index d0097ee04c6..2a5e1f2983e 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -189,14 +189,17 @@ We do not support the following "patterns" in destructuring assignment: - `&x = foo();`. - `&mut x = foo();`. - `ref x = foo();`. +- `x @ y = foo()`. - (`box` patterns, which are deprecated.) This is primarily for learnability: the behaviour of `&` can already be slightly confusing to newcomers, as it has different meanings depending on whether it is used in an expression or pattern. In destructuring assignment, the left-hand side of an assignment consists of sub*expressions*, but which act intuitively like patterns, so it is not clear what `&` and friends should mean. We feel it -is more confusing than helpful to allow these cases. Conversely, destructuring tuples, slices or -structs is very natural and we do not foresee confusion with allowing these. +is more confusing than helpful to allow these cases. Similarly, although coming up with a sensible +meaning for `@`-bindings in destructuring assignment is not inconceivable, we believe they would be +confusing at best in this context. Conversely, destructuring tuples, slices or structs is very +natural and we do not foresee confusion with allowing these. Our implementation is forwards-compatible with allowing these patterns in destructuring assigmnent, in any case, so we lose nothing by not allowing them from the start. From 50a8dbaabe71babfa3ea4cede8ef810975b5197c Mon Sep 17 00:00:00 2001 From: varkor Date: Fri, 17 Apr 2020 22:49:43 +0100 Subject: [PATCH 20/29] Add reference to alternative involving new keyword --- text/0000-destructuring-assignment.md | 57 +++++++++++++++++++-------- 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 2a5e1f2983e..174c419b9bb 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -263,8 +263,11 @@ We thus feel that a lint is more appropriate. # Drawbacks [drawbacks]: #drawbacks -- It could be argued that this feature increases the surface area of the language and thus complexity. However, we feel that by decreasing surprise, it actually makes the language less complex for users. -- It is possible that these changes could result in some confusing diagnostics. However, we have not found any during testing, and these could in any case be ironed out before stabilisation. +- It could be argued that this feature increases the surface area of the language and thus + complexity. However, we feel that by decreasing surprise, it actually makes the language less + complex for users. +- It is possible that these changes could result in some confusing diagnostics. However, we have not + found any during testing, and these could in any case be ironed out before stabilisation. # Rationale and alternatives [rationale-and-alternatives]: #rationale-and-alternatives @@ -273,18 +276,40 @@ As we argue above, we believe this change increases the perceived consistency of idiomatic code in the presence of mutability, and that the implementation is simple and intuitive. -One potential alternative that has been put forth in the past is to allow arbitrary patterns on the left-hand side of an assignment, -but as discussed above and [extensively in this +One potential alternative that has been put forth in the past is to allow arbitrary patterns on the +left-hand side of an assignment, but as discussed above and [extensively in this thread](https://github.com/rust-lang/rfcs/issues/372), it is difficult to see how this could work in -practice (especially with complex left-hand sides that do not simply involve identifiers) and it is not clear that this would have any advantages. +practice (especially with complex left-hand sides that do not simply involve identifiers) and it is +not clear that this would have any advantages. + +Another suggested alternative is to introduce a new keyword for indicating an assignment to an +existing expression during a `let` variable declaration. For example, something like the following: + +```rust +let (a, reassign b) = expr; +``` + +This has the advantage that we can reuse the existing infrastructure for patterns. However, it has +the following disadvantages, which we believe make it less suitable than our proposal: + +- It requires a new keyword or overloading an existing one, both of which have syntactic and + semantic overhead. +- It is something that needs to be learnt by users: conversely, we maintain that it is natural to + attempt destructuring assignment with the syntax we propose already, so does not need to be + learnt. +- It changes the meaning of `let` (which has previously been associated only with binding new + variables). +- To be consistent, we ought to allow `let reassign x = value;`, which introduces another way + to simply write `x = value;`. +- It is longer and no more readable than the proposed syntax. # Prior art [prior-art]: #prior-art -The most persuasive prior art is Rust itself, which already permits destructuring -declarations. Intuitively, a declaration is an assignment that also introduces a new binding. -Therefore, it seems clear that assignments should act similarly to declarations where possible. -However, it is also the case that destructuring assignments are present in many languages that permit destructuring +The most persuasive prior art is Rust itself, which already permits destructuring declarations. +Intuitively, a declaration is an assignment that also introduces a new binding. Therefore, it seems +clear that assignments should act similarly to declarations where possible. However, it is also the +case that destructuring assignments are present in many languages that permit destructuring declarations. - JavaScript @@ -305,15 +330,15 @@ None. # Future possibilities [future-possibilities]: #future-possibilities -- The implementation already supports destructuring of every class of expressions that currently make -sense in Rust. This feature naturally should be extended to any new class of expressions for which -it makes sense. -- It could make sense to permit -[destructuring compound assignments](#Compound-destructuring-assignment) in the future, though we -defer this question for later discussions. +- The implementation already supports destructuring of every class of expressions that currently + make sense in Rust. This feature naturally should be extended to any new class of expressions for + which it makes sense. +- It could make sense to permit [destructuring compound + assignments](#Compound-destructuring-assignment) in the future, though we defer this question for + later discussions. - It could make sense to permit [`ref` and `&`](#Unsupported-patterns) in the future. - It [has been suggested](https://github.com/rust-lang/rfcs/issues/372#issuecomment-365606878) that -mixed declarations and assignments could be permitted, as in the following: + mixed declarations and assignments could be permitted, as in the following: ```rust let a; From e5cfd6571929712d4051177d0d8b2553903602c6 Mon Sep 17 00:00:00 2001 From: varkor Date: Sat, 18 Apr 2020 12:19:36 +0100 Subject: [PATCH 21/29] Give earlier example of non-ident lvalue --- text/0000-destructuring-assignment.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 174c419b9bb..5400f588e4c 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -11,9 +11,9 @@ We allow destructuring on assignment, as in `let` declarations. For instance, th accepted: ```rust -(a, (b, c)) = (0, (1, 2)); +(a, (b.x.y, c)) = (0, (1, 2)); (x, y, .., z) = (1.0, 2.0, 3.0, 4.0, 5.0); -[_, f] = foo(); +[_, f, *baz()] = foo(); [g, _, h, ..] = ['a', 'w', 'e', 's', 'o', 'm', 'e', '!']; Struct { x: a, y: b } = bar(); ``` From db1a22b6f03d537ec1a0a76a5d3f8e220043a6ff Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 19 Apr 2020 17:51:37 +0100 Subject: [PATCH 22/29] Mention field shorthand --- text/0000-destructuring-assignment.md | 1 + 1 file changed, 1 insertion(+) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 5400f588e4c..4b0c787006f 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -16,6 +16,7 @@ accepted: [_, f, *baz()] = foo(); [g, _, h, ..] = ['a', 'w', 'e', 's', 'o', 'm', 'e', '!']; Struct { x: a, y: b } = bar(); +Struct { x, y } = Struct { x: 5, y: 6 }; ``` This brings assignment in line with `let` declaration, in which destructuring is permitted. This From 821dcc84678df39f2ceb44fe3eb248a21b5beef3 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 19 Apr 2020 17:59:24 +0100 Subject: [PATCH 23/29] Add note about place expressions --- text/0000-destructuring-assignment.md | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 4b0c787006f..16892c64892 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -46,9 +46,10 @@ You may use `_` and `..` as in a normal declaration pattern to ignore certain va # Reference-level explanation [reference-level-explanation]: #reference-level-explanation -The feature as described here has been implemented as a proof-of-concept (https://github.com/rust-lang/rust/pull/71156). It follows essentially the -[suggestions of @Kimundi](https://github.com/rust-lang/rfcs/issues/372#issuecomment-214022963) and -[of @drunwald](https://github.com/rust-lang/rfcs/issues/372#issuecomment-262519146). +The feature as described here has been implemented as a proof-of-concept +(https://github.com/rust-lang/rust/pull/71156). It follows essentially the [suggestions of +@Kimundi](https://github.com/rust-lang/rfcs/issues/372#issuecomment-214022963) and [of +@drunwald](https://github.com/rust-lang/rfcs/issues/372#issuecomment-262519146). The Rust compiler already parses complex expressions on the left-hand side of an assignment, but does not handle them other than emitting an error later in compilation. We propose to add @@ -59,6 +60,18 @@ complicates Rust's grammar and it is not clear that it is even technically feasi handling some classes of expressions is much simpler, and is indistinguishable to users, who will receive pattern-oriented diagnostics due to the desugaring of expressions into patterns. +In effect, we are extending the [place +expressions](https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions) (also called "lvalues") +that Rust accepts by the following: + +- Underscore: `_`. +- Tuples: `(place, place, place)`, `(place, .., place)`, `(.., place, place)`, `(place, place, ..)`. +- Slices: `[place, place, place]`, `[place, .., place]`, `[.., place, place]`, `[place, place, ..]`. +- Tuple structs: `path(place, place, place)`, `path(place, .., place)`, `path(.., place, place)`, + `path(place, place, ..)`. +- Structs: `path { field: place, field: place }`, `path { field: place, field: place, .. }`. +- Unit structs: `path`. + The general idea is that we will desugar the following complex assignments as demonstrated. ```rust From ff995bb9e49fab8d5f4369a272cbceb482f6961e Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 31 May 2020 23:13:32 +0100 Subject: [PATCH 24/29] Add notion of "assignee expression" --- text/0000-destructuring-assignment.md | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 16892c64892..dbcc685b7db 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -60,18 +60,29 @@ complicates Rust's grammar and it is not clear that it is even technically feasi handling some classes of expressions is much simpler, and is indistinguishable to users, who will receive pattern-oriented diagnostics due to the desugaring of expressions into patterns. -In effect, we are extending the [place -expressions](https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions) (also called "lvalues") -that Rust accepts by the following: +To describe the context of destructuring assignments more precisely, we add a new class of +expressions, which we call "assignee expressions". +Assignee expressions are analogous to [place +expressions](https://doc.rust-lang.org/reference/expressions.html#place-expressions-and-value-expressions) +(also called "lvalues") in that they refer to expressions representing a memory location, but may +only appear on the left-hand side of an assignment (unlike place expressions). Every place +expression is also an assignee expression. +The class of assignee expressions is defined inductively: + +- Place: `place`. - Underscore: `_`. -- Tuples: `(place, place, place)`, `(place, .., place)`, `(.., place, place)`, `(place, place, ..)`. -- Slices: `[place, place, place]`, `[place, .., place]`, `[.., place, place]`, `[place, place, ..]`. -- Tuple structs: `path(place, place, place)`, `path(place, .., place)`, `path(.., place, place)`, - `path(place, place, ..)`. -- Structs: `path { field: place, field: place }`, `path { field: place, field: place, .. }`. +- Tuples: `(assignee, assignee, assignee)`, `(assignee, .., assignee)`, `(.., assignee, assignee)`, `(assignee, assignee, ..)`. +- Slices: `[assignee, assignee, assignee]`, `[assignee, .., assignee]`, `[.., assignee, assignee]`, `[assignee, assignee, ..]`. +- Tuple structs: `path(assignee, assignee, assignee)`, `path(assignee, .., assignee)`, `path(.., assignee, assignee)`, + `path(assignee, assignee, ..)`. +- Structs: `path { field: assignee, field: assignee }`, `path { field: assignee, field: assignee, .. }`. - Unit structs: `path`. +The place expression "The left operand of an assignment or compound assignment expression." ibid. +is changed to "The left operand of a compound assignment expression.", while +"The left operand of an assignment expression." is now an assignee expression. + The general idea is that we will desugar the following complex assignments as demonstrated. ```rust From 7120df9717c55f067dd2b931945dac025282a107 Mon Sep 17 00:00:00 2001 From: varkor Date: Sun, 31 May 2020 23:13:39 +0100 Subject: [PATCH 25/29] Make clarifications after review --- text/0000-destructuring-assignment.md | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index dbcc685b7db..993e0cdd3b4 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -13,7 +13,7 @@ accepted: ```rust (a, (b.x.y, c)) = (0, (1, 2)); (x, y, .., z) = (1.0, 2.0, 3.0, 4.0, 5.0); -[_, f, *baz()] = foo(); +[_, f, *baz(), a[i]] = foo(); [g, _, h, ..] = ['a', 'w', 'e', 's', 'o', 'm', 'e', '!']; Struct { x: a, y: b } = bar(); Struct { x, y } = Struct { x: 5, y: 6 }; @@ -128,7 +128,7 @@ identifiers are fresh and thus do not conflict with existing variables). A nice we inherit the diagnostics for normal pattern-matching, so users benefit from existing diagnostics for destructuring declarations. -Nested structures are destructured appropriately, for instance: +Nested structures may be destructured, for instance: ```rust let (a, b, c); @@ -152,6 +152,11 @@ Note that `#[non_exhaustive]` must be taken into account properly: enums marked may not have their variants destructured, and structs marked `#[non_exhaustive]` may only be destructured using `..`. +Patterns must be irrefutable. In particular, only slice patterns whose length is known at compile- +time, and the trivial slice `[..]` may be used for destructuring assignment. + +As expected from the desugaring, the default binding modes of normal `let` destructuring applying. + ## Diagnostics It is worth being explicit that, in the implementation, the diagnostics that are reported are From 15951091c09de9f75517375762c5718cbb54b418 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 14 Sep 2020 23:08:59 +0100 Subject: [PATCH 26/29] Default binding modes do not apply for destructuring assignment --- text/0000-destructuring-assignment.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 993e0cdd3b4..18eec5a6d93 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -155,7 +155,9 @@ destructured using `..`. Patterns must be irrefutable. In particular, only slice patterns whose length is known at compile- time, and the trivial slice `[..]` may be used for destructuring assignment. -As expected from the desugaring, the default binding modes of normal `let` destructuring applying. +Unlike in usual `let` bindings, default binding modes do *not* apply for the desugared destructuring +assignments, as this leads to counterintuitive behaviour since the desguaring is an implementation +detail. ## Diagnostics From cfe880fc126c967d656146f47a35570725e8f357 Mon Sep 17 00:00:00 2001 From: varkor Date: Thu, 17 Sep 2020 12:17:19 +0100 Subject: [PATCH 27/29] Fix typo --- text/0000-destructuring-assignment.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 18eec5a6d93..cdce5f4a8cd 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -38,7 +38,7 @@ You may destructure a value when making an assignment, just as when you declare - Tuples. - Slices. -- Structs (inclduing unit and tuple structs). +- Structs (including unit and tuple structs). - Unique variants of enums. You may use `_` and `..` as in a normal declaration pattern to ignore certain values. @@ -120,7 +120,7 @@ We support the following classes of expressions: - Tuples. - Slices. -- Structs (inclduing unit and tuple structs). +- Structs (including unit and tuple structs). - Unique variants of enums. In the desugaring, we convert the expression `(a, b)` into an analogous pattern `(_a, _b)` (whose From 9daec615ce20617c0963dc50ecedf03caebc2502 Mon Sep 17 00:00:00 2001 From: varkor Date: Mon, 21 Sep 2020 21:06:12 +0100 Subject: [PATCH 28/29] Fix another typo Co-authored-by: Jubilee <46493976+workingjubilee@users.noreply.github.com> --- text/0000-destructuring-assignment.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index cdce5f4a8cd..8fbac1e9400 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -156,7 +156,7 @@ Patterns must be irrefutable. In particular, only slice patterns whose length is time, and the trivial slice `[..]` may be used for destructuring assignment. Unlike in usual `let` bindings, default binding modes do *not* apply for the desugared destructuring -assignments, as this leads to counterintuitive behaviour since the desguaring is an implementation +assignments, as this leads to counterintuitive behaviour since the desugaring is an implementation detail. ## Diagnostics From 58091b60e98cf3ec5f72b4f5ba0d84cd59048810 Mon Sep 17 00:00:00 2001 From: varkor Date: Wed, 30 Sep 2020 20:08:22 +0100 Subject: [PATCH 29/29] Clarify behaviour of range expressions --- text/0000-destructuring-assignment.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/text/0000-destructuring-assignment.md b/text/0000-destructuring-assignment.md index 8fbac1e9400..2e63e506a1a 100644 --- a/text/0000-destructuring-assignment.md +++ b/text/0000-destructuring-assignment.md @@ -243,11 +243,14 @@ context: - Range patterns. - Or patterns. +Therefore, literals, bitwise OR, and range expressions (`..`, `..=`) are not permitted on the +left-hand side of a destructuring assignment. + ## Compound destructuring assignment We forbid destructuring compound assignment, i.e. destructuring for operators like `+=`, `*=` and so -on. This is both for the sake of simplicity and since there are relevant design questions that do not have obvious answers, -e.g. how this could interact with custom implementations of the operators. +on. This is both for the sake of simplicity and since there are relevant design questions that do +not have obvious answers, e.g. how this could interact with custom implementations of the operators. ## Order-of-assignment