@@ -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
@@ -79,17 +72,11 @@ impl<'p, Cx: TypeCx> DeconstructedPat<'p, Cx> {
7972 /// `other_ctor` can be different from `self.ctor`, but must be covered by it.
8073 pub ( crate ) fn specialize (
8174 & self ,
82- pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
75+ _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,87 @@ 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+ ///
153+ /// This is morally `Option<&'p DeconstructedPat>` where `None` is interpreted as a wildcard.
154+ #[ derive( derivative:: Derivative ) ]
155+ #[ derivative( Clone ( bound = "" ) , Copy ( bound = "" ) ) ]
156+ pub ( crate ) enum PatOrWild < ' p , Cx : TypeCx > {
157+ /// A non-user-provided wildcard, created during specialization.
158+ Wild ,
159+ /// A user-provided pattern.
160+ Pat ( & ' p DeconstructedPat < ' p , Cx > ) ,
161+ }
162+
163+ impl < ' p , Cx : TypeCx > PatOrWild < ' p , Cx > {
164+ pub ( crate ) fn as_pat ( & self ) -> Option < & ' p DeconstructedPat < ' p , Cx > > {
165+ match self {
166+ Wild => None ,
167+ Pat ( pat) => Some ( pat) ,
168+ }
169+ }
170+ pub ( crate ) fn ctor ( self ) -> & ' p Constructor < Cx > {
171+ match self {
172+ Wild => & Wildcard ,
173+ Pat ( pat) => pat. ctor ( ) ,
174+ }
175+ }
176+
177+ pub ( crate ) fn is_or_pat ( & self ) -> bool {
178+ match self {
179+ Wild => false ,
180+ Pat ( pat) => pat. is_or_pat ( ) ,
181+ }
182+ }
183+
184+ /// Expand this (possibly-nested) or-pattern into its alternatives.
185+ pub ( crate ) fn flatten_or_pat ( self ) -> SmallVec < [ Self ; 1 ] > {
186+ match self {
187+ Pat ( pat) if pat. is_or_pat ( ) => {
188+ pat. iter_fields ( ) . flat_map ( |p| Pat ( p) . flatten_or_pat ( ) ) . collect ( )
189+ }
190+ _ => smallvec ! [ self ] ,
191+ }
192+ }
193+
194+ /// Specialize this pattern with a constructor.
195+ /// `other_ctor` can be different from `self.ctor`, but must be covered by it.
196+ pub ( crate ) fn specialize (
197+ & self ,
198+ pcx : & PlaceCtxt < ' _ , ' p , Cx > ,
199+ other_ctor : & Constructor < Cx > ,
200+ ctor_sub_tys : & [ Cx :: Ty ] ,
201+ ) -> SmallVec < [ PatOrWild < ' p , Cx > ; 2 ] > {
202+ match self {
203+ Wild => ctor_sub_tys. iter ( ) . map ( |_| Wild ) . collect ( ) ,
204+ Pat ( pat) => pat. specialize ( pcx, other_ctor, ctor_sub_tys) ,
205+ }
206+ }
207+
208+ pub ( crate ) fn set_useful ( & self ) {
209+ if let Pat ( pat) = self {
210+ pat. set_useful ( )
211+ }
212+ }
213+ }
214+
215+ impl < ' p , Cx : TypeCx > fmt:: Debug for PatOrWild < ' p , Cx > {
216+ fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
217+ match self {
218+ Wild => write ! ( f, "_" ) ,
219+ Pat ( pat) => pat. fmt ( f) ,
220+ }
221+ }
222+ }
223+
164224/// Same idea as `DeconstructedPat`, except this is a fictitious pattern built up for diagnostics
165225/// purposes. As such they don't use interning and can be cloned.
166226#[ derive( derivative:: Derivative ) ]
0 commit comments