From cb4de738cfe479418511025cdac7a33b8b36c407 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Wed, 31 Oct 2012 13:56:08 -0700 Subject: [PATCH] Fix checking of duplicate and missing struct field initializers. Closes #3486. Closes #3892 --- src/rustc/middle/typeck/check.rs | 14 +++++++++----- src/test/compile-fail/struct-fields-dupe.rs | 10 ++++++++++ src/test/compile-fail/struct-fields-missing.rs | 10 ++++++++++ src/test/compile-fail/struct-fields-too-many.rs | 10 ++++++++++ 4 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 src/test/compile-fail/struct-fields-dupe.rs create mode 100644 src/test/compile-fail/struct-fields-missing.rs create mode 100644 src/test/compile-fail/struct-fields-too-many.rs diff --git a/src/rustc/middle/typeck/check.rs b/src/rustc/middle/typeck/check.rs index 5fc92b2d0d0a..044b95915cd3 100644 --- a/src/rustc/middle/typeck/check.rs +++ b/src/rustc/middle/typeck/check.rs @@ -1457,6 +1457,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, let tcx = fcx.ccx.tcx; let mut bot = false; + error!("%? %?", ast_fields.len(), field_types.len()); + let class_field_map = HashMap(); let mut fields_found = 0; for field_types.each |field| { @@ -1470,7 +1472,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, None => { tcx.sess.span_err( field.span, - fmt!("structure has no field named field named `%s`", + fmt!("structure has no field named `%s`", tcx.sess.str_of(field.node.ident))); } Some((_, true)) => { @@ -1486,6 +1488,8 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, bot |= check_expr(fcx, field.node.expr, Some(expected_field_type)); + class_field_map.insert( + field.node.ident, (field_id, true)); fields_found += 1; } } @@ -1493,11 +1497,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, if check_completeness { // Make sure the programmer specified all the fields. - assert fields_found <= ast_fields.len(); - if fields_found < ast_fields.len() { + assert fields_found <= field_types.len(); + if fields_found < field_types.len() { let mut missing_fields = ~[]; - for ast_fields.each |class_field| { - let name = class_field.node.ident; + for field_types.each |class_field| { + let name = class_field.ident; let (_, seen) = class_field_map.get(name); if !seen { missing_fields.push( diff --git a/src/test/compile-fail/struct-fields-dupe.rs b/src/test/compile-fail/struct-fields-dupe.rs new file mode 100644 index 000000000000..43436e36cf75 --- /dev/null +++ b/src/test/compile-fail/struct-fields-dupe.rs @@ -0,0 +1,10 @@ +struct BuildData { + foo: int, +} + +fn main() { + let foo = BuildData { + foo: 0, + foo: 0 //~ ERROR field `foo` specified more than once + }; +} \ No newline at end of file diff --git a/src/test/compile-fail/struct-fields-missing.rs b/src/test/compile-fail/struct-fields-missing.rs new file mode 100644 index 000000000000..5e6098fbe952 --- /dev/null +++ b/src/test/compile-fail/struct-fields-missing.rs @@ -0,0 +1,10 @@ +struct BuildData { + foo: int, + bar: ~int +} + +fn main() { + let foo = BuildData { //~ ERROR missing field: `bar` + foo: 0 + }; +} diff --git a/src/test/compile-fail/struct-fields-too-many.rs b/src/test/compile-fail/struct-fields-too-many.rs new file mode 100644 index 000000000000..f3780aadc113 --- /dev/null +++ b/src/test/compile-fail/struct-fields-too-many.rs @@ -0,0 +1,10 @@ +struct BuildData { + foo: int, +} + +fn main() { + let foo = BuildData { + foo: 0, + bar: 0 //~ ERROR structure has no field named `bar` + }; +}