@@ -186,139 +186,6 @@ fn check_pat_variant(pcx: pat_ctxt, pat: @ast::pat, path: @ast::path,
186
186
}
187
187
}
188
188
189
- /// `path` is the AST path item naming the type of this struct.
190
- /// `fields` is the field patterns of the struct pattern.
191
- /// `class_fields` describes the type of each field of the struct.
192
- /// `class_id` is the ID of the struct.
193
- /// `substitutions` are the type substitutions applied to this struct type
194
- /// (e.g. K,V in HashMap<K,V>).
195
- /// `etc` is true if the pattern said '...' and false otherwise.
196
- fn check_struct_pat_fields( pcx: pat_ctxt,
197
- span: span,
198
- path: @ast:: path,
199
- fields: ~[ ast:: field_pat] ,
200
- class_fields: ~[ ty:: field_ty] ,
201
- class_id: ast:: def_id,
202
- substitutions: & ty:: substs,
203
- etc: bool ) {
204
- let tcx = pcx. fcx. ccx. tcx;
205
-
206
- // Index the class fields.
207
- let field_map = std:: map:: HashMap ( ) ;
208
- for class_fields. eachi |i, class_field| {
209
- field_map. insert( class_field. ident, i) ;
210
- }
211
-
212
- // Typecheck each field.
213
- let found_fields = std:: map:: HashMap ( ) ;
214
- for fields. each |field| {
215
- match field_map. find( field. ident) {
216
- Some ( index) => {
217
- let class_field = class_fields[ index] ;
218
- let field_type = ty:: lookup_field_type( tcx,
219
- class_id,
220
- class_field. id,
221
- substitutions) ;
222
- check_pat( pcx, field. pat, field_type) ;
223
- found_fields. insert( index, ( ) ) ;
224
- }
225
- None => {
226
- let name = pprust:: path_to_str( path, tcx. sess. intr( ) ) ;
227
- tcx. sess. span_err( span,
228
- fmt!( "struct `%s` does not have a field
229
- named `%s`" , name,
230
- tcx. sess. str_of( field. ident) ) ) ;
231
- }
232
- }
233
- }
234
-
235
- // Report an error if not all the fields were specified.
236
- if !etc {
237
- for class_fields. eachi |i, field| {
238
- if found_fields. contains_key( i) {
239
- loop ;
240
- }
241
- tcx. sess. span_err( span,
242
- fmt!( "pattern does not mention field `%s`" ,
243
- tcx. sess. str_of( field. ident) ) ) ;
244
- }
245
- }
246
- }
247
-
248
- fn check_struct_pat( pcx: pat_ctxt, pat_id: ast:: node_id, span: span,
249
- expected: ty:: t, path: @ast:: path,
250
- fields: ~[ ast:: field_pat] , etc: bool ,
251
- class_id: ast:: def_id, substitutions: & ty:: substs) {
252
- let fcx = pcx. fcx;
253
- let tcx = pcx. fcx. ccx. tcx;
254
-
255
- let class_fields = ty:: lookup_class_fields( tcx, class_id) ;
256
-
257
- // Check to ensure that the struct is the one specified.
258
- match tcx. def_map. find( pat_id) {
259
- Some ( ast:: def_class( supplied_def_id) )
260
- if supplied_def_id == class_id => {
261
- // OK.
262
- }
263
- Some ( ast:: def_class( * ) ) | Some ( ast:: def_variant( * ) ) => {
264
- let name = pprust:: path_to_str( path, tcx. sess. intr( ) ) ;
265
- tcx. sess. span_err( span,
266
- fmt!( "mismatched types: expected `%s` but \
267
- found `%s`",
268
- fcx. infcx( ) . ty_to_str( expected) ,
269
- name) ) ;
270
- }
271
- _ => {
272
- tcx. sess. span_bug( span, ~"resolve didn' t write in class");
273
- }
274
- }
275
-
276
- // Forbid pattern-matching structs with destructors.
277
- if ty::has_dtor(tcx, class_id) {
278
- tcx.sess.span_err(span, ~" deconstructing struct not allowed in \
279
- pattern ( it has a destructor) ");
280
- }
281
-
282
- check_struct_pat_fields(pcx, span, path, fields, class_fields, class_id,
283
- substitutions, etc);
284
- }
285
-
286
- fn check_struct_like_enum_variant_pat(pcx: pat_ctxt,
287
- pat_id: ast::node_id,
288
- span: span,
289
- expected: ty::t,
290
- path: @ast::path,
291
- fields: ~[ast::field_pat],
292
- etc: bool,
293
- enum_id: ast::def_id,
294
- substitutions: &ty::substs) {
295
- let fcx = pcx.fcx;
296
- let tcx = pcx.fcx.ccx.tcx;
297
-
298
- // Find the variant that was specified.
299
- match tcx.def_map.find(pat_id) {
300
- Some(ast::def_variant(found_enum_id, variant_id))
301
- if found_enum_id == enum_id => {
302
- // Get the struct fields from this struct-like enum variant.
303
- let class_fields = ty::lookup_class_fields(tcx, variant_id);
304
-
305
- check_struct_pat_fields(pcx, span, path, fields, class_fields,
306
- variant_id, substitutions, etc);
307
- }
308
- Some(ast::def_class(*)) | Some(ast::def_variant(*)) => {
309
- let name = pprust::path_to_str(path, tcx.sess.intr());
310
- tcx.sess.span_err(span,
311
- fmt!(" mismatched types: expected `%s` but \
312
- found `%s`",
313
- fcx. infcx( ) . ty_to_str( expected) ,
314
- name) ) ;
315
- }
316
- _ => {
317
- tcx. sess. span_bug( span, ~"resolve didn' t write in variant");
318
- }
319
- }
320
- }
321
-
322
189
// Pattern checking is top-down rather than bottom-up so that bindings get
323
190
// their types immediately.
324
191
fn check_pat( pcx: pat_ctxt, pat: @ast:: pat, expected: ty:: t) {
@@ -439,16 +306,13 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
439
306
}
440
307
ast:: pat_struct( path, fields, etc) => {
441
308
// Grab the class data that we care about.
309
+ let class_fields, class_id, substitutions;
442
310
let structure = structure_of( fcx, pat. span, expected) ;
443
311
match structure {
444
312
ty:: ty_class( cid, ref substs) => {
445
- check_struct_pat( pcx, pat. id, pat. span, expected, path,
446
- fields, etc, cid, substs) ;
447
- }
448
- ty:: ty_enum( eid, ref substs) => {
449
- check_struct_like_enum_variant_pat(
450
- pcx, pat. id, pat. span, expected, path, fields, etc, eid,
451
- substs) ;
313
+ class_id = cid;
314
+ substitutions = substs;
315
+ class_fields = ty:: lookup_class_fields( tcx, class_id) ;
452
316
}
453
317
_ => {
454
318
// XXX: This should not be fatal.
@@ -459,6 +323,72 @@ fn check_pat(pcx: pat_ctxt, pat: @ast::pat, expected: ty::t) {
459
323
}
460
324
}
461
325
326
+ // Check to ensure that the struct is the one specified.
327
+ match tcx. def_map. get( pat. id) {
328
+ ast:: def_class( supplied_def_id)
329
+ if supplied_def_id == class_id => {
330
+ // OK.
331
+ }
332
+ ast:: def_class( * ) => {
333
+ let name = pprust:: path_to_str( path, tcx. sess. intr( ) ) ;
334
+ tcx. sess. span_err( pat. span,
335
+ fmt!( "mismatched types: expected `%s` but \
336
+ found `%s`",
337
+ fcx. infcx( ) . ty_to_str( expected) ,
338
+ name) ) ;
339
+ }
340
+ _ => {
341
+ tcx. sess. span_bug( pat. span, ~"resolve didn' t write in class");
342
+ }
343
+ }
344
+
345
+ // Forbid pattern-matching structs with destructors.
346
+ if ty::has_dtor(tcx, class_id) {
347
+ tcx.sess.span_err(pat.span, ~" deconstructing struct not allowed \
348
+ in pattern ( it has a destructor) ");
349
+ }
350
+
351
+ // Index the class fields.
352
+ let field_map = std::map::HashMap();
353
+ for class_fields.eachi |i, class_field| {
354
+ field_map.insert(class_field.ident, i);
355
+ }
356
+
357
+ // Typecheck each field.
358
+ let found_fields = std::map::HashMap();
359
+ for fields.each |field| {
360
+ match field_map.find(field.ident) {
361
+ Some(index) => {
362
+ let class_field = class_fields[index];
363
+ let field_type = ty::lookup_field_type(tcx,
364
+ class_id,
365
+ class_field.id,
366
+ substitutions);
367
+ check_pat(pcx, field.pat, field_type);
368
+ found_fields.insert(index, ());
369
+ }
370
+ None => {
371
+ let name = pprust::path_to_str(path, tcx.sess.intr());
372
+ tcx.sess.span_err(pat.span,
373
+ fmt!(" struct `%s` does not have a field
374
+ named `%s`", name,
375
+ tcx. sess. str_of( field. ident) ) ) ;
376
+ }
377
+ }
378
+ }
379
+
380
+ // Report an error if not all the fields were specified.
381
+ if !etc {
382
+ for class_fields. eachi |i, field| {
383
+ if found_fields. contains_key( i) {
384
+ loop ;
385
+ }
386
+ tcx. sess. span_err( pat. span,
387
+ fmt!( "pattern does not mention field `%s`" ,
388
+ tcx. sess. str_of( field. ident) ) ) ;
389
+ }
390
+ }
391
+
462
392
// Finally, write in the type.
463
393
fcx. write_ty( pat. id, expected) ;
464
394
}
0 commit comments