From b6aadf56c8a6e603c79a8924e6a92398471de8cf Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Fri, 27 Jul 2012 13:03:04 -0700 Subject: [PATCH] In resolve, check for duplicate pattern-bound vars Closes #3038 --- src/rustc/middle/resolve3.rs | 31 +++++++++++++++++++---------- src/test/compile-fail/issue-3038.rs | 25 +++++++++++++++++++++++ 2 files changed, 46 insertions(+), 10 deletions(-) create mode 100644 src/test/compile-fail/issue-3038.rs diff --git a/src/rustc/middle/resolve3.rs b/src/rustc/middle/resolve3.rs index 65ab9e889c0..f4794bd39e4 100644 --- a/src/rustc/middle/resolve3.rs +++ b/src/rustc/middle/resolve3.rs @@ -32,7 +32,7 @@ import syntax::ast::{required, provided}; import syntax::ast_util::{def_id_of_def, dummy_sp, local_def, new_def_hash}; import syntax::ast_util::{walk_pat}; import syntax::attr::{attr_metas, contains_name}; -import syntax::print::pprust::path_to_str; +import syntax::print::pprust::{pat_to_str, path_to_str}; import syntax::codemap::span; import syntax::visit::{default_visitor, fk_method, mk_vt, visit_block}; import syntax::visit::{visit_crate, visit_expr, visit_expr_opt, visit_fn}; @@ -3658,9 +3658,12 @@ class Resolver { fn resolve_pattern(pattern: @pat, mode: PatternBindingMode, mutability: Mutability, - bindings_list: option>, + // Maps idents to the node ID for the (outermost) + // pattern that binds them + bindings_list: option>, visitor: ResolveVisitor) { + let pat_id = pattern.id; do walk_pat(pattern) |pattern| { alt pattern.node { pat_ident(path, _) @@ -3705,19 +3708,18 @@ class Resolver { let is_mutable = mutability == Mutable; - let mut def; - alt mode { + let def = alt mode { RefutableMode { // For pattern arms, we must use // `def_binding` definitions. - def = def_binding(pattern.id); + def_binding(pattern.id) } IrrefutableMode { // But for locals, we use `def_local`. - def = def_local(pattern.id, is_mutable); + def_local(pattern.id, is_mutable) } - } + }; // Record the definition so that later passes // will be able to distinguish variants from @@ -3737,10 +3739,19 @@ class Resolver { let last_rib = (*self.value_ribs).last(); last_rib.bindings.insert(atom, dl_def(def)); - bindings_list.insert(atom, ()); + bindings_list.insert(atom, pat_id); } - some(_) { - // Do nothing. + some(b) { + if b.find(atom) == some(pat_id) { + // Then this is a duplicate variable + // in the same disjunct, which is an + // error + self.session.span_err(pattern.span, + #fmt("Identifier %s is bound more \ + than once in the same pattern", + path_to_str(path))); + } + // Not bound in the same pattern: do nothing } none { let last_rib = (*self.value_ribs).last(); diff --git a/src/test/compile-fail/issue-3038.rs b/src/test/compile-fail/issue-3038.rs new file mode 100644 index 00000000000..0728dca2e8b --- /dev/null +++ b/src/test/compile-fail/issue-3038.rs @@ -0,0 +1,25 @@ +enum f { g(int, int) } + +enum h { i(j, k) } + +enum j { l(int, int) } +enum k { m(int, int) } + +fn main() +{ + + let _z = alt g(1, 2) { + g(x, x) { log(debug, x + x); } + //~^ ERROR Identifier x is bound more than once in the same pattern + }; + + let _z = alt i(l(1, 2), m(3, 4)) { + i(l(x, _), m(_, x)) //~ ERROR Identifier x is bound more than once in the same pattern + { log(error, x + x); } + }; + + let _z = alt (1, 2) { + (x, x) { x } //~ ERROR Identifier x is bound more than once in the same pattern + }; + +}