@@ -4,7 +4,7 @@ use std::iter::repeat_with;
4
4
5
5
use chalk_ir:: Mutability ;
6
6
use hir_def:: {
7
- expr:: { BindingAnnotation , Expr , Literal , Pat , PatId , RecordFieldPat } ,
7
+ expr:: { BindingAnnotation , Expr , Literal , Pat , PatId } ,
8
8
path:: Path ,
9
9
type_ref:: ConstScalar ,
10
10
} ;
@@ -17,15 +17,20 @@ use crate::{
17
17
TyKind ,
18
18
} ;
19
19
20
+ use super :: PatLike ;
21
+
20
22
impl < ' a > InferenceContext < ' a > {
21
- fn infer_tuple_struct_pat (
23
+ /// Infers type for tuple struct pattern or its corresponding assignee expression.
24
+ ///
25
+ /// Ellipses found in the original pattern or expression must be filtered out.
26
+ pub ( super ) fn infer_tuple_struct_pat_like < T : PatLike > (
22
27
& mut self ,
23
28
path : Option < & Path > ,
24
- subpats : & [ PatId ] ,
25
29
expected : & Ty ,
26
- default_bm : BindingMode ,
27
- id : PatId ,
30
+ default_bm : T :: BindingMode ,
31
+ id : T ,
28
32
ellipsis : Option < usize > ,
33
+ subs : & [ T ] ,
29
34
) -> Ty {
30
35
let ( ty, def) = self . resolve_variant ( path, true ) ;
31
36
let var_data = def. map ( |it| it. variant_data ( self . db . upcast ( ) ) ) ;
@@ -39,8 +44,8 @@ impl<'a> InferenceContext<'a> {
39
44
40
45
let field_tys = def. map ( |it| self . db . field_types ( it) ) . unwrap_or_default ( ) ;
41
46
let ( pre, post) = match ellipsis {
42
- Some ( idx) => subpats . split_at ( idx) ,
43
- None => ( subpats , & [ ] [ ..] ) ,
47
+ Some ( idx) => subs . split_at ( idx) ,
48
+ None => ( subs , & [ ] [ ..] ) ,
44
49
} ;
45
50
let post_idx_offset = field_tys. iter ( ) . count ( ) . saturating_sub ( post. len ( ) ) ;
46
51
@@ -54,22 +59,22 @@ impl<'a> InferenceContext<'a> {
54
59
field_tys[ field] . clone ( ) . substitute ( Interner , & substs)
55
60
} ) ;
56
61
let expected_ty = self . normalize_associated_types_in ( expected_ty) ;
57
- self . infer_pat ( subpat, & expected_ty, default_bm) ;
62
+ T :: infer ( self , subpat, & expected_ty, default_bm) ;
58
63
}
59
64
60
65
ty
61
66
}
62
67
63
- fn infer_record_pat (
68
+ /// Infers type for record pattern or its corresponding assignee expression.
69
+ pub ( super ) fn infer_record_pat_like < T : PatLike > (
64
70
& mut self ,
65
71
path : Option < & Path > ,
66
- subpats : & [ RecordFieldPat ] ,
67
72
expected : & Ty ,
68
- default_bm : BindingMode ,
69
- id : PatId ,
73
+ default_bm : T :: BindingMode ,
74
+ id : T ,
75
+ subs : impl Iterator < Item = ( Name , T ) > ,
70
76
) -> Ty {
71
77
let ( ty, def) = self . resolve_variant ( path, false ) ;
72
- let var_data = def. map ( |it| it. variant_data ( self . db . upcast ( ) ) ) ;
73
78
if let Some ( variant) = def {
74
79
self . write_variant_resolution ( id. into ( ) , variant) ;
75
80
}
@@ -80,18 +85,64 @@ impl<'a> InferenceContext<'a> {
80
85
ty. as_adt ( ) . map ( |( _, s) | s. clone ( ) ) . unwrap_or_else ( || Substitution :: empty ( Interner ) ) ;
81
86
82
87
let field_tys = def. map ( |it| self . db . field_types ( it) ) . unwrap_or_default ( ) ;
83
- for subpat in subpats {
84
- let matching_field = var_data. as_ref ( ) . and_then ( |it| it. field ( & subpat. name ) ) ;
85
- let expected_ty = matching_field. map_or ( self . err_ty ( ) , |field| {
86
- field_tys[ field] . clone ( ) . substitute ( Interner , & substs)
87
- } ) ;
88
+ let var_data = def. map ( |it| it. variant_data ( self . db . upcast ( ) ) ) ;
89
+
90
+ for ( name, inner) in subs {
91
+ let expected_ty = var_data
92
+ . as_ref ( )
93
+ . and_then ( |it| it. field ( & name) )
94
+ . map_or ( self . err_ty ( ) , |f| field_tys[ f] . clone ( ) . substitute ( Interner , & substs) ) ;
88
95
let expected_ty = self . normalize_associated_types_in ( expected_ty) ;
89
- self . infer_pat ( subpat. pat , & expected_ty, default_bm) ;
96
+
97
+ T :: infer ( self , inner, & expected_ty, default_bm) ;
90
98
}
91
99
92
100
ty
93
101
}
94
102
103
+ /// Infers type for tuple pattern or its corresponding assignee expression.
104
+ ///
105
+ /// Ellipses found in the original pattern or expression must be filtered out.
106
+ pub ( super ) fn infer_tuple_pat_like < T : PatLike > (
107
+ & mut self ,
108
+ expected : & Ty ,
109
+ default_bm : T :: BindingMode ,
110
+ ellipsis : Option < usize > ,
111
+ subs : & [ T ] ,
112
+ ) -> Ty {
113
+ let expectations = match expected. as_tuple ( ) {
114
+ Some ( parameters) => & * parameters. as_slice ( Interner ) ,
115
+ _ => & [ ] ,
116
+ } ;
117
+
118
+ let ( ( pre, post) , n_uncovered_patterns) = match ellipsis {
119
+ Some ( idx) => ( subs. split_at ( idx) , expectations. len ( ) . saturating_sub ( subs. len ( ) ) ) ,
120
+ None => ( ( & subs[ ..] , & [ ] [ ..] ) , 0 ) ,
121
+ } ;
122
+ let mut expectations_iter = expectations
123
+ . iter ( )
124
+ . cloned ( )
125
+ . map ( |a| a. assert_ty_ref ( Interner ) . clone ( ) )
126
+ . chain ( repeat_with ( || self . table . new_type_var ( ) ) ) ;
127
+
128
+ let mut inner_tys = Vec :: with_capacity ( n_uncovered_patterns + subs. len ( ) ) ;
129
+
130
+ inner_tys. extend ( expectations_iter. by_ref ( ) . take ( n_uncovered_patterns + subs. len ( ) ) ) ;
131
+
132
+ // Process pre
133
+ for ( ty, pat) in inner_tys. iter_mut ( ) . zip ( pre) {
134
+ * ty = T :: infer ( self , * pat, ty, default_bm) ;
135
+ }
136
+
137
+ // Process post
138
+ for ( ty, pat) in inner_tys. iter_mut ( ) . skip ( pre. len ( ) + n_uncovered_patterns) . zip ( post) {
139
+ * ty = T :: infer ( self , * pat, ty, default_bm) ;
140
+ }
141
+
142
+ TyKind :: Tuple ( inner_tys. len ( ) , Substitution :: from_iter ( Interner , inner_tys) )
143
+ . intern ( Interner )
144
+ }
145
+
95
146
pub ( super ) fn infer_pat (
96
147
& mut self ,
97
148
pat : PatId ,
@@ -129,42 +180,7 @@ impl<'a> InferenceContext<'a> {
129
180
130
181
let ty = match & self . body [ pat] {
131
182
Pat :: Tuple { args, ellipsis } => {
132
- let expectations = match expected. as_tuple ( ) {
133
- Some ( parameters) => & * parameters. as_slice ( Interner ) ,
134
- _ => & [ ] ,
135
- } ;
136
-
137
- let ( ( pre, post) , n_uncovered_patterns) = match ellipsis {
138
- Some ( idx) => {
139
- ( args. split_at ( * idx) , expectations. len ( ) . saturating_sub ( args. len ( ) ) )
140
- }
141
- None => ( ( & args[ ..] , & [ ] [ ..] ) , 0 ) ,
142
- } ;
143
- let mut expectations_iter = expectations
144
- . iter ( )
145
- . cloned ( )
146
- . map ( |a| a. assert_ty_ref ( Interner ) . clone ( ) )
147
- . chain ( repeat_with ( || self . table . new_type_var ( ) ) ) ;
148
-
149
- let mut inner_tys = Vec :: with_capacity ( n_uncovered_patterns + args. len ( ) ) ;
150
-
151
- inner_tys
152
- . extend ( expectations_iter. by_ref ( ) . take ( n_uncovered_patterns + args. len ( ) ) ) ;
153
-
154
- // Process pre
155
- for ( ty, pat) in inner_tys. iter_mut ( ) . zip ( pre) {
156
- * ty = self . infer_pat ( * pat, ty, default_bm) ;
157
- }
158
-
159
- // Process post
160
- for ( ty, pat) in
161
- inner_tys. iter_mut ( ) . skip ( pre. len ( ) + n_uncovered_patterns) . zip ( post)
162
- {
163
- * ty = self . infer_pat ( * pat, ty, default_bm) ;
164
- }
165
-
166
- TyKind :: Tuple ( inner_tys. len ( ) , Substitution :: from_iter ( Interner , inner_tys) )
167
- . intern ( Interner )
183
+ self . infer_tuple_pat_like ( & expected, default_bm, * ellipsis, args)
168
184
}
169
185
Pat :: Or ( pats) => {
170
186
if let Some ( ( first_pat, rest) ) = pats. split_first ( ) {
@@ -191,16 +207,18 @@ impl<'a> InferenceContext<'a> {
191
207
let subty = self . infer_pat ( * pat, & expectation, default_bm) ;
192
208
TyKind :: Ref ( mutability, static_lifetime ( ) , subty) . intern ( Interner )
193
209
}
194
- Pat :: TupleStruct { path : p, args : subpats, ellipsis } => self . infer_tuple_struct_pat (
195
- p. as_deref ( ) ,
196
- subpats,
197
- & expected,
198
- default_bm,
199
- pat,
200
- * ellipsis,
201
- ) ,
210
+ Pat :: TupleStruct { path : p, args : subpats, ellipsis } => self
211
+ . infer_tuple_struct_pat_like (
212
+ p. as_deref ( ) ,
213
+ & expected,
214
+ default_bm,
215
+ pat,
216
+ * ellipsis,
217
+ subpats,
218
+ ) ,
202
219
Pat :: Record { path : p, args : fields, ellipsis : _ } => {
203
- self . infer_record_pat ( p. as_deref ( ) , fields, & expected, default_bm, pat)
220
+ let subs = fields. iter ( ) . map ( |f| ( f. name . clone ( ) , f. pat ) ) ;
221
+ self . infer_record_pat_like ( p. as_deref ( ) , & expected, default_bm, pat. into ( ) , subs)
204
222
}
205
223
Pat :: Path ( path) => {
206
224
// FIXME use correct resolver for the surrounding expression
0 commit comments