Skip to content

Commit efba56c

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 efba56c

File tree

1 file changed

+50
-1
lines changed

1 file changed

+50
-1
lines changed

src/patterns.md

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

1084+
[PR #138458]: https://github.com/rust-lang/rust/pull/138458
1085+
[PR #140593]: https://github.com/rust-lang/rust/pull/140593#issuecomment-2972338457
10381086
[`Copy`]: special-types-and-traits.md#copy
10391087
[constant]: items/constant-items.md
10401088
[enums]: items/enumerations.md
@@ -1049,4 +1097,5 @@ For example, `x @ A(..) | B(..)` will result in an error that `x` is not bound i
10491097
[tuples]: types/tuple.md
10501098
[scrutinee]: glossary.md#scrutinee
10511099
[type coercions]: type-coercions.md
1052-
[value namespace]: names/namespaces.md
1100+
[type namespace]: names.namespaces.kinds
1101+
[value namespace]: names.namespaces.kinds

0 commit comments

Comments
 (0)