@@ -64,130 +64,159 @@ pub(crate) enum PatKind<'tcx> {
64
64
65
65
impl < ' tcx > fmt:: Display for Pat < ' tcx > {
66
66
fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
67
- // Printing lists is a chore.
68
- let mut first = true ;
69
- let mut start_or_continue = |s| {
70
- if first {
71
- first = false ;
72
- ""
73
- } else {
74
- s
75
- }
76
- } ;
77
- let mut start_or_comma = || start_or_continue ( ", " ) ;
78
-
79
67
match self . kind {
80
68
PatKind :: Wild => write ! ( f, "_" ) ,
81
69
PatKind :: Never => write ! ( f, "!" ) ,
82
70
PatKind :: Variant { ref subpatterns, .. } | PatKind :: Leaf { ref subpatterns } => {
83
- let variant_and_name = match self . kind {
84
- PatKind :: Variant { adt_def, variant_index, .. } => ty:: tls:: with ( |tcx| {
85
- let variant = adt_def. variant ( variant_index) ;
86
- let adt_did = adt_def. did ( ) ;
87
- let name = if tcx. get_diagnostic_item ( sym:: Option ) == Some ( adt_did)
88
- || tcx. get_diagnostic_item ( sym:: Result ) == Some ( adt_did)
89
- {
90
- variant. name . to_string ( )
91
- } else {
92
- format ! ( "{}::{}" , tcx. def_path_str( adt_def. did( ) ) , variant. name)
93
- } ;
94
- Some ( ( variant, name) )
95
- } ) ,
96
- _ => self . ty . ty_adt_def ( ) . and_then ( |adt_def| {
97
- if !adt_def. is_enum ( ) {
98
- ty:: tls:: with ( |tcx| {
99
- Some ( ( adt_def. non_enum_variant ( ) , tcx. def_path_str ( adt_def. did ( ) ) ) )
100
- } )
101
- } else {
102
- None
103
- }
104
- } ) ,
105
- } ;
106
-
107
- if let Some ( ( variant, name) ) = & variant_and_name {
108
- write ! ( f, "{name}" ) ?;
109
-
110
- // Only for Adt we can have `S {...}`,
111
- // which we handle separately here.
112
- if variant. ctor . is_none ( ) {
113
- write ! ( f, " {{ " ) ?;
114
-
115
- let mut printed = 0 ;
116
- for p in subpatterns {
117
- if let PatKind :: Wild = p. pattern . kind {
118
- continue ;
119
- }
120
- let name = variant. fields [ p. field ] . name ;
121
- write ! ( f, "{}{}: {}" , start_or_comma( ) , name, p. pattern) ?;
122
- printed += 1 ;
123
- }
124
-
125
- let is_union = self . ty . ty_adt_def ( ) . is_some_and ( |adt| adt. is_union ( ) ) ;
126
- if printed < variant. fields . len ( ) && ( !is_union || printed == 0 ) {
127
- write ! ( f, "{}.." , start_or_comma( ) ) ?;
128
- }
129
-
130
- return write ! ( f, " }}" ) ;
131
- }
132
- }
133
-
134
- let num_fields =
135
- variant_and_name. as_ref ( ) . map_or ( subpatterns. len ( ) , |( v, _) | v. fields . len ( ) ) ;
136
- if num_fields != 0 || variant_and_name. is_none ( ) {
137
- write ! ( f, "(" ) ?;
138
- for i in 0 ..num_fields {
139
- write ! ( f, "{}" , start_or_comma( ) ) ?;
140
-
141
- // Common case: the field is where we expect it.
142
- if let Some ( p) = subpatterns. get ( i) {
143
- if p. field . index ( ) == i {
144
- write ! ( f, "{}" , p. pattern) ?;
145
- continue ;
146
- }
147
- }
148
-
149
- // Otherwise, we have to go looking for it.
150
- if let Some ( p) = subpatterns. iter ( ) . find ( |p| p. field . index ( ) == i) {
151
- write ! ( f, "{}" , p. pattern) ?;
152
- } else {
153
- write ! ( f, "_" ) ?;
154
- }
155
- }
156
- write ! ( f, ")" ) ?;
157
- }
158
-
159
- Ok ( ( ) )
160
- }
161
- PatKind :: Deref { ref subpattern } => {
162
- match self . ty . kind ( ) {
163
- ty:: Adt ( def, _) if def. is_box ( ) => write ! ( f, "box " ) ?,
164
- ty:: Ref ( _, _, mutbl) => {
165
- write ! ( f, "&{}" , mutbl. prefix_str( ) ) ?;
166
- }
167
- _ => bug ! ( "{} is a bad Deref pattern type" , self . ty) ,
168
- }
169
- write ! ( f, "{subpattern}" )
71
+ write_struct_like ( f, self . ty , & self . kind , subpatterns)
170
72
}
73
+ PatKind :: Deref { ref subpattern } => write_ref_like ( f, self . ty , subpattern) ,
171
74
PatKind :: Constant { value } => write ! ( f, "{value}" ) ,
172
75
PatKind :: Range ( ref range) => write ! ( f, "{range}" ) ,
173
76
PatKind :: Slice { ref prefix, ref slice, ref suffix } => {
174
- write ! ( f, "[" ) ?;
175
- for p in prefix. iter ( ) {
176
- write ! ( f, "{}{}" , start_or_comma( ) , p) ?;
177
- }
178
- if let Some ( ref slice) = * slice {
179
- write ! ( f, "{}" , start_or_comma( ) ) ?;
180
- match slice. kind {
181
- PatKind :: Wild => { }
182
- _ => write ! ( f, "{slice}" ) ?,
183
- }
184
- write ! ( f, ".." ) ?;
77
+ write_slice_like ( f, prefix, slice, suffix)
78
+ }
79
+ }
80
+ }
81
+ }
82
+
83
+ /// Returns a closure that will return `""` when called the first time,
84
+ /// and then return `", "` when called any subsequent times.
85
+ /// Useful for printing comma-separated lists.
86
+ fn start_or_comma ( ) -> impl FnMut ( ) -> & ' static str {
87
+ let mut first = true ;
88
+ move || {
89
+ if first {
90
+ first = false ;
91
+ ""
92
+ } else {
93
+ ", "
94
+ }
95
+ }
96
+ }
97
+
98
+ fn write_struct_like < ' tcx > (
99
+ f : & mut impl fmt:: Write ,
100
+ ty : Ty < ' tcx > ,
101
+ kind : & PatKind < ' tcx > ,
102
+ subpatterns : & [ FieldPat < ' tcx > ] ,
103
+ ) -> fmt:: Result {
104
+ let variant_and_name = match * kind {
105
+ PatKind :: Variant { adt_def, variant_index, .. } => ty:: tls:: with ( |tcx| {
106
+ let variant = adt_def. variant ( variant_index) ;
107
+ let adt_did = adt_def. did ( ) ;
108
+ let name = if tcx. get_diagnostic_item ( sym:: Option ) == Some ( adt_did)
109
+ || tcx. get_diagnostic_item ( sym:: Result ) == Some ( adt_did)
110
+ {
111
+ variant. name . to_string ( )
112
+ } else {
113
+ format ! ( "{}::{}" , tcx. def_path_str( adt_def. did( ) ) , variant. name)
114
+ } ;
115
+ Some ( ( variant, name) )
116
+ } ) ,
117
+ _ => ty. ty_adt_def ( ) . and_then ( |adt_def| {
118
+ if !adt_def. is_enum ( ) {
119
+ ty:: tls:: with ( |tcx| {
120
+ Some ( ( adt_def. non_enum_variant ( ) , tcx. def_path_str ( adt_def. did ( ) ) ) )
121
+ } )
122
+ } else {
123
+ None
124
+ }
125
+ } ) ,
126
+ } ;
127
+
128
+ let mut start_or_comma = start_or_comma ( ) ;
129
+
130
+ if let Some ( ( variant, name) ) = & variant_and_name {
131
+ write ! ( f, "{name}" ) ?;
132
+
133
+ // Only for Adt we can have `S {...}`,
134
+ // which we handle separately here.
135
+ if variant. ctor . is_none ( ) {
136
+ write ! ( f, " {{ " ) ?;
137
+
138
+ let mut printed = 0 ;
139
+ for p in subpatterns {
140
+ if let PatKind :: Wild = p. pattern . kind {
141
+ continue ;
185
142
}
186
- for p in suffix. iter ( ) {
187
- write ! ( f, "{}{}" , start_or_comma( ) , p) ?;
143
+ let name = variant. fields [ p. field ] . name ;
144
+ write ! ( f, "{}{}: {}" , start_or_comma( ) , name, p. pattern) ?;
145
+ printed += 1 ;
146
+ }
147
+
148
+ let is_union = ty. ty_adt_def ( ) . is_some_and ( |adt| adt. is_union ( ) ) ;
149
+ if printed < variant. fields . len ( ) && ( !is_union || printed == 0 ) {
150
+ write ! ( f, "{}.." , start_or_comma( ) ) ?;
151
+ }
152
+
153
+ return write ! ( f, " }}" ) ;
154
+ }
155
+ }
156
+
157
+ let num_fields = variant_and_name. as_ref ( ) . map_or ( subpatterns. len ( ) , |( v, _) | v. fields . len ( ) ) ;
158
+ if num_fields != 0 || variant_and_name. is_none ( ) {
159
+ write ! ( f, "(" ) ?;
160
+ for i in 0 ..num_fields {
161
+ write ! ( f, "{}" , start_or_comma( ) ) ?;
162
+
163
+ // Common case: the field is where we expect it.
164
+ if let Some ( p) = subpatterns. get ( i) {
165
+ if p. field . index ( ) == i {
166
+ write ! ( f, "{}" , p. pattern) ?;
167
+ continue ;
188
168
}
189
- write ! ( f, "]" )
169
+ }
170
+
171
+ // Otherwise, we have to go looking for it.
172
+ if let Some ( p) = subpatterns. iter ( ) . find ( |p| p. field . index ( ) == i) {
173
+ write ! ( f, "{}" , p. pattern) ?;
174
+ } else {
175
+ write ! ( f, "_" ) ?;
190
176
}
191
177
}
178
+ write ! ( f, ")" ) ?;
179
+ }
180
+
181
+ Ok ( ( ) )
182
+ }
183
+
184
+ fn write_ref_like < ' tcx > (
185
+ f : & mut impl fmt:: Write ,
186
+ ty : Ty < ' tcx > ,
187
+ subpattern : & Pat < ' tcx > ,
188
+ ) -> fmt:: Result {
189
+ match ty. kind ( ) {
190
+ ty:: Adt ( def, _) if def. is_box ( ) => write ! ( f, "box " ) ?,
191
+ ty:: Ref ( _, _, mutbl) => {
192
+ write ! ( f, "&{}" , mutbl. prefix_str( ) ) ?;
193
+ }
194
+ _ => bug ! ( "{ty} is a bad ref pattern type" ) ,
195
+ }
196
+ write ! ( f, "{subpattern}" )
197
+ }
198
+
199
+ fn write_slice_like < ' tcx > (
200
+ f : & mut impl fmt:: Write ,
201
+ prefix : & [ Box < Pat < ' tcx > > ] ,
202
+ slice : & Option < Box < Pat < ' tcx > > > ,
203
+ suffix : & [ Box < Pat < ' tcx > > ] ,
204
+ ) -> fmt:: Result {
205
+ let mut start_or_comma = start_or_comma ( ) ;
206
+ write ! ( f, "[" ) ?;
207
+ for p in prefix. iter ( ) {
208
+ write ! ( f, "{}{}" , start_or_comma( ) , p) ?;
209
+ }
210
+ if let Some ( ref slice) = * slice {
211
+ write ! ( f, "{}" , start_or_comma( ) ) ?;
212
+ match slice. kind {
213
+ PatKind :: Wild => { }
214
+ _ => write ! ( f, "{slice}" ) ?,
215
+ }
216
+ write ! ( f, ".." ) ?;
217
+ }
218
+ for p in suffix. iter ( ) {
219
+ write ! ( f, "{}{}" , start_or_comma( ) , p) ?;
192
220
}
221
+ write ! ( f, "]" )
193
222
}
0 commit comments