@@ -64,130 +64,159 @@ pub(crate) enum PatKind<'tcx> {
6464
6565impl < ' tcx > fmt:: Display for Pat < ' tcx > {
6666 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-
7967 match self . kind {
8068 PatKind :: Wild => write ! ( f, "_" ) ,
8169 PatKind :: Never => write ! ( f, "!" ) ,
8270 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)
17072 }
73+ PatKind :: Deref { ref subpattern } => write_ref_like ( f, self . ty , subpattern) ,
17174 PatKind :: Constant { value } => write ! ( f, "{value}" ) ,
17275 PatKind :: Range ( ref range) => write ! ( f, "{range}" ) ,
17376 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 ;
185142 }
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 ;
188168 }
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, "_" ) ?;
190176 }
191177 }
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) ?;
192220 }
221+ write ! ( f, "]" )
193222}
0 commit comments