@@ -10,6 +10,7 @@ use crate::usefulness::PlaceCtxt;
1010use crate :: { Captures , TypeCx } ;
1111
1212use self :: Constructor :: * ;
13+ use self :: PatOrWild :: * ;
1314
1415/// Values and patterns can be represented as a constructor applied to some fields. This represents
1516/// a pattern in this form.
@@ -50,14 +51,6 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
5051 pub ( crate ) fn is_or_pat ( & self ) -> bool {
5152 matches ! ( self . ctor, Or )
5253 }
53- /// Expand this (possibly-nested) or-pattern into its alternatives.
54- pub ( crate ) fn flatten_or_pat ( & self ) -> SmallVec < [ & Self ; 1 ] > {
55- if self . is_or_pat ( ) {
56- self . iter_fields ( ) . flat_map ( |p| p. flatten_or_pat ( ) ) . collect ( )
57- } else {
58- smallvec ! [ self ]
59- }
60- }
6154
6255 pub fn ctor ( & self ) -> & Constructor < Cx > {
6356 & self . ctor
@@ -82,14 +75,8 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
8275 pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
8376 other_ctor : & Constructor < Cx > ,
8477 ctor_sub_tys : & [ Cx :: Ty ] ,
85- ) -> SmallVec < [ & ' p DeconstructedPat < ' p , Cx > ; 2 ] > {
86- let wildcard_sub_tys = || {
87- ctor_sub_tys
88- . iter ( )
89- . map ( |ty| DeconstructedPat :: wildcard ( * ty) )
90- . map ( |pat| pcx. mcx . wildcard_arena . alloc ( pat) as & _ )
91- . collect ( )
92- } ;
78+ ) -> SmallVec < [ PatOrWild < ' p , Cx > ; 2 ] > {
79+ let wildcard_sub_tys = || ctor_sub_tys. iter ( ) . map ( |_| Wild ) . collect ( ) ;
9380 match ( & self . ctor , other_ctor) {
9481 // Return a wildcard for each field of `other_ctor`.
9582 ( Wildcard , _) => wildcard_sub_tys ( ) ,
@@ -105,14 +92,14 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
10592 // Fill in the fields from both ends.
10693 let new_arity = fields. len ( ) ;
10794 for i in 0 ..prefix {
108- fields[ i] = & self . fields [ i] ;
95+ fields[ i] = Pat ( & self . fields [ i] ) ;
10996 }
11097 for i in 0 ..suffix {
111- fields[ new_arity - 1 - i] = & self . fields [ self . fields . len ( ) - 1 - i] ;
98+ fields[ new_arity - 1 - i] = Pat ( & self . fields [ self . fields . len ( ) - 1 - i] ) ;
11299 }
113100 fields
114101 }
115- _ => self . fields . iter ( ) . collect ( ) ,
102+ _ => self . fields . iter ( ) . map ( Pat ) . collect ( ) ,
116103 }
117104 }
118105
@@ -153,14 +140,82 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
153140 }
154141}
155142
156- /// This is mostly copied from the `Pat` impl. This is best effort and not good enough for a
157- /// `Display` impl.
143+ /// This is best effort and not good enough for a `Display` impl.
158144impl < ' p , Cx : TypeCx > fmt:: Debug for DeconstructedPat < ' p , Cx > {
159145 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
160146 Cx :: debug_pat ( f, self )
161147 }
162148}
163149
150+ /// Represents either a pattern obtained from user input or a wildcard constructed during the
151+ /// algorithm. Do not use `Wild` to represent a wildcard pattern comping from user input.
152+ #[ derive( derivative:: Derivative ) ]
153+ #[ derivative( Clone ( bound = "" ) , Copy ( bound = "" ) ) ]
154+ pub ( crate ) enum PatOrWild < ' p , Cx : TypeCx > {
155+ /// A non-user-provided wildcard, created during specialization.
156+ Wild ,
157+ /// A user-provided pattern.
158+ Pat ( & ' p DeconstructedPat < ' p , Cx > ) ,
159+ }
160+
161+ impl < ' p , Cx : TypeCx > PatOrWild < ' p , Cx > {
162+ pub ( crate ) fn as_pat ( & self ) -> Option < & ' p DeconstructedPat < ' p , Cx > > {
163+ match self {
164+ Wild => None ,
165+ Pat ( pat) => Some ( pat) ,
166+ }
167+ }
168+ pub ( crate ) fn ctor ( self ) -> & ' p Constructor < Cx > {
169+ match self {
170+ Wild => & Wildcard ,
171+ Pat ( pat) => pat. ctor ( ) ,
172+ }
173+ }
174+
175+ pub ( crate ) fn is_or_pat ( & self ) -> bool {
176+ matches ! ( self . ctor( ) , Or )
177+ }
178+
179+ /// Expand this (possibly-nested) or-pattern into its alternatives.
180+ pub ( crate ) fn flatten_or_pat ( self ) -> SmallVec < [ Self ; 1 ] > {
181+ match self {
182+ Pat ( pat) if pat. is_or_pat ( ) => {
183+ pat. iter_fields ( ) . flat_map ( |p| Pat ( p) . flatten_or_pat ( ) ) . collect ( )
184+ }
185+ _ => smallvec ! [ self ] ,
186+ }
187+ }
188+
189+ /// Specialize this pattern with a constructor.
190+ /// `other_ctor` can be different from `self.ctor`, but must be covered by it.
191+ pub ( crate ) fn specialize (
192+ & self ,
193+ pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
194+ other_ctor : & Constructor < Cx > ,
195+ ctor_sub_tys : & [ Cx :: Ty ] ,
196+ ) -> SmallVec < [ PatOrWild < ' p , Cx > ; 2 ] > {
197+ match self {
198+ Wild => ctor_sub_tys. iter ( ) . map ( |_| Wild ) . collect ( ) ,
199+ Pat ( pat) => pat. specialize ( pcx, other_ctor, ctor_sub_tys) ,
200+ }
201+ }
202+
203+ pub ( crate ) fn set_useful ( & self ) {
204+ if let Pat ( pat) = self {
205+ pat. set_useful ( )
206+ }
207+ }
208+ }
209+
210+ impl < ' p , Cx : TypeCx > fmt:: Debug for PatOrWild < ' p , Cx > {
211+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
212+ match self {
213+ Wild => write ! ( f, "_" ) ,
214+ Pat ( pat) => pat. fmt ( f) ,
215+ }
216+ }
217+ }
218+
164219/// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
165220/// purposes. As such they don't use interning and can be cloned.
166221#[ derive( derivative:: Derivative ) ]
0 commit comments