From 80055dee3a58f569963c12a446bbf943ebb7670c Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Mon, 2 Dec 2013 14:20:27 -0800 Subject: [PATCH] Disallow duplicate bindings of struct fields Closes #9725 --- src/librustc/middle/typeck/check/_match.rs | 15 +++++++++++---- src/test/compile-fail/issue-9725.rs | 15 +++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) create mode 100644 src/test/compile-fail/issue-9725.rs diff --git a/src/librustc/middle/typeck/check/_match.rs b/src/librustc/middle/typeck/check/_match.rs index 2e2d223242193..4623c0bc6d865 100644 --- a/src/librustc/middle/typeck/check/_match.rs +++ b/src/librustc/middle/typeck/check/_match.rs @@ -294,17 +294,24 @@ pub fn check_struct_pat_fields(pcx: &pat_ctxt, etc: bool) { let tcx = pcx.fcx.ccx.tcx; - // Index the class fields. + // Index the class fields. The second argument in the tuple is whether the + // field has been bound yet or not. let mut field_map = HashMap::new(); for (i, class_field) in class_fields.iter().enumerate() { - field_map.insert(class_field.name, i); + field_map.insert(class_field.name, (i, false)); } // Typecheck each field. let mut found_fields = HashSet::new(); for field in fields.iter() { - match field_map.find(&field.ident.name) { - Some(&index) => { + match field_map.find_mut(&field.ident.name) { + Some(&(_, true)) => { + tcx.sess.span_err(span, + format!("field `{}` bound twice in pattern", + tcx.sess.str_of(field.ident))); + } + Some(&(index, ref mut used)) => { + *used = true; let class_field = class_fields[index]; let field_type = ty::lookup_field_type(tcx, class_id, diff --git a/src/test/compile-fail/issue-9725.rs b/src/test/compile-fail/issue-9725.rs new file mode 100644 index 0000000000000..2a0896380fd77 --- /dev/null +++ b/src/test/compile-fail/issue-9725.rs @@ -0,0 +1,15 @@ +// Copyright 2013 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +struct A { foo: int } + +fn main() { + let A { foo, foo } = A { foo: 3 }; //~ ERROR: field `foo` bound twice +}