Skip to content

Commit a170307

Browse files
committed
Document (tuple) struct pattern namespace behavior
We had not documented what namespaces were used when matching struct and tuple struct patterns. As it turns out, this is a bit nuanced. Let's document the current behavior, describe the nature of this nuance with an example, and note the possible uncertainly about the desirability of this behavior long-term.
1 parent 743ba16 commit a170307

File tree

1 file changed

+48
-1
lines changed

1 file changed

+48
-1
lines changed

src/patterns.md

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,9 @@ let Struct{a: x, b: y, c: z} = struct_value; // destructure all fields
801801
r[patterns.struct.refutable]
802802
A struct pattern is refutable if the [PathInExpression] resolves to a constructor of an enum with more than one variant, or one of its subpatterns is refutable.
803803

804+
r[patterns.struct.namespace]
805+
A struct pattern matches against the struct, union, or enum variant whose constructor is resolved from [PathInExpression] in the [type namespace]. See [patterns.tuple-struct.namespace] for more details.
806+
804807
r[patterns.tuple-struct]
805808
## Tuple struct patterns
806809

@@ -818,6 +821,46 @@ They are also used to [destructure](#destructuring) a tuple struct or enum value
818821
r[patterns.tuple-struct.refutable]
819822
A tuple struct pattern is refutable if the [PathInExpression] resolves to a constructor of an enum with more than one variant, or one of its subpatterns is refutable.
820823

824+
r[patterns.tuple-struct.namespace]
825+
A tuple struct pattern matches against the tuple struct or [tuple-like enum variant] whose constructor is resolved from [PathInExpression] in the [value namespace].
826+
827+
> [!NOTE]
828+
> Conversely, a struct pattern for a tuple struct or [tuple-like enum variant], e.g. `S { 0: _ }`, matches against the tuple struct or variant whose constructor is resolved in the [type namespace].
829+
>
830+
> ```rust,no_run
831+
> enum E1 { V(u16) }
832+
> enum E2 { V(u32) }
833+
>
834+
> // Import `E1::V` from the type namespace only.
835+
> mod _0 {
836+
> const V: () = (); // For namespace masking.
837+
> pub(super) use super::E1::*;
838+
> }
839+
> use _0::*;
840+
>
841+
> // Import `E2::V` from the value namespace only.
842+
> mod _1 {
843+
> struct V {} // For namespace masking.
844+
> pub(super) use super::E2::*;
845+
> }
846+
> use _1::*;
847+
>
848+
> fn f() {
849+
> // This struct pattern matches against the tuple-like
850+
> // enum variant whose constructor was found in the type
851+
> // namespace.
852+
> let V { 0: ..=u16::MAX } = (loop {}) else { loop {} };
853+
> // This tuple struct pattern matches against the tuple-like
854+
> // enum variant whose constructor was found in the value
855+
> // namespace.
856+
> let V(..=u32::MAX) = (loop {}) else { loop {} };
857+
> }
858+
> # // Required due to the odd behavior of `super` within functions.
859+
> # fn main() {}
860+
> ```
861+
>
862+
> The Lang team has made certain decisions, such as in [PR #138458], that raise questions about the desirability of using the value namespace in this way for patterns, as described in [PR #140593]. It might be prudent to not intentionally rely on this nuance in your code.
863+
821864
r[patterns.tuple]
822865
## Tuple patterns
823866
@@ -1035,6 +1078,8 @@ This allows us to reserve syntactic space for a possible future type ascription
10351078
For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound in all patterns.
10361079
`&A(x) | B(x)` will result in a type mismatch between `x` in the different subpatterns.
10371080

1081+
[PR #138458]: https://github.com/rust-lang/rust/pull/138458
1082+
[PR #140593]: https://github.com/rust-lang/rust/pull/140593#issuecomment-2972338457
10381083
[`Copy`]: special-types-and-traits.md#copy
10391084
[constant]: items/constant-items.md
10401085
[enums]: items/enumerations.md
@@ -1048,5 +1093,7 @@ For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound i
10481093
[structs]: items/structs.md
10491094
[tuples]: types/tuple.md
10501095
[scrutinee]: glossary.md#scrutinee
1096+
[tuple-like enum variant]: items.enum.tuple-expr
10511097
[type coercions]: type-coercions.md
1052-
[value namespace]: names/namespaces.md
1098+
[type namespace]: names.namespaces.kinds
1099+
[value namespace]: names.namespaces.kinds

0 commit comments

Comments
 (0)