@@ -376,6 +376,29 @@ fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
376
376
}
377
377
}
378
378
379
+ fn check_no_duplicate_fields ( tcx : ty:: ctxt , fields :
380
+ ~[ ( ast:: ident , span ) ] ) {
381
+ let field_names = hashmap :: < @~str , span > ( |x| str:: hash ( * x) ,
382
+ |x, y| str:: eq ( * x, * y) ) ;
383
+ for fields. each |p| {
384
+ let ( id, sp) = p;
385
+ alt field_names. find ( id) {
386
+ some ( orig_sp) {
387
+ tcx. sess . span_err ( sp, #fmt ( "Duplicate field \
388
+ name %s in record type declaration",
389
+ * id) ) ;
390
+ tcx. sess . span_note ( orig_sp, ~"First declaration of \
391
+ this field occurred here") ;
392
+ break ;
393
+ }
394
+ none {
395
+ field_names. insert ( id, sp) ;
396
+ }
397
+ }
398
+ }
399
+
400
+ }
401
+
379
402
fn check_item( ccx : @crate_ctxt , it : @ast:: item ) {
380
403
alt it. node {
381
404
ast:: item_const ( _, e) { check_const ( ccx, it. span , e, it. id ) ; }
@@ -429,6 +452,14 @@ fn check_item(ccx: @crate_ctxt, it: @ast::item) {
429
452
ast:: item_ty ( t, tps) {
430
453
let tpt_ty = ty:: node_id_to_type ( ccx. tcx , it. id ) ;
431
454
check_bounds_are_used ( ccx, t. span , tps, tpt_ty) ;
455
+ // If this is a record ty, check for duplicate fields
456
+ alt t. node {
457
+ ast:: ty_rec ( fields) {
458
+ check_no_duplicate_fields ( ccx. tcx , fields. map ( |f|
459
+ ( f. node . ident , f. span ) ) ) ;
460
+ }
461
+ _ { }
462
+ }
432
463
}
433
464
ast:: item_foreign_mod ( m) {
434
465
if syntax:: attr:: foreign_abi ( it. attrs ) ==
@@ -1617,6 +1648,13 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
1617
1648
fn get_node(f: spanned<field>) -> field { f.node }
1618
1649
let typ = ty::mk_rec(tcx, vec::map(fields_t, get_node));
1619
1650
fcx.write_ty(id, typ);
1651
+ /* Check for duplicate fields */
1652
+ /* Only do this check if there's no base expr -- the reason is
1653
+ that we're extending a record we know has no dup fields, and
1654
+ it would be ill-typed anyway if we duplicated one of its
1655
+ fields */
1656
+ check_no_duplicate_fields(tcx, fields.map(|f|
1657
+ (f.node.ident, f.span)));
1620
1658
}
1621
1659
some(bexpr) {
1622
1660
let bexpr_t = fcx.expr_ty(bexpr);
0 commit comments