parent
a0d05844ed
commit
f7382c454f
3 changed files with 45 additions and 1 deletions
|
@ -47,7 +47,7 @@ import str::{connect, split_str};
|
||||||
import vec::pop;
|
import vec::pop;
|
||||||
|
|
||||||
import std::list::{cons, list, nil};
|
import std::list::{cons, list, nil};
|
||||||
import std::map::{hashmap, int_hash, str_hash};
|
import std::map::{hashmap, int_hash};
|
||||||
import ASTMap = syntax::ast_map::map;
|
import ASTMap = syntax::ast_map::map;
|
||||||
import str_eq = str::eq;
|
import str_eq = str::eq;
|
||||||
|
|
||||||
|
|
|
@ -376,6 +376,29 @@ fn check_class_member(ccx: @crate_ctxt, class_t: ty::t,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn check_no_duplicate_fields(tcx: ty::ctxt, fields:
|
||||||
|
~[(ast::ident, span)]) {
|
||||||
|
let field_names = hashmap::<@~str, span>(|x| str::hash(*x),
|
||||||
|
|x,y| str::eq(*x, *y));
|
||||||
|
for fields.each |p| {
|
||||||
|
let (id, sp) = p;
|
||||||
|
alt field_names.find(id) {
|
||||||
|
some(orig_sp) {
|
||||||
|
tcx.sess.span_err(sp, #fmt("Duplicate field \
|
||||||
|
name %s in record type declaration",
|
||||||
|
*id));
|
||||||
|
tcx.sess.span_note(orig_sp, ~"First declaration of \
|
||||||
|
this field occurred here");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
none {
|
||||||
|
field_names.insert(id, sp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
fn check_item(ccx: @crate_ctxt, it: @ast::item) {
|
||||||
alt it.node {
|
alt it.node {
|
||||||
ast::item_const(_, e) { check_const(ccx, it.span, e, it.id); }
|
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) {
|
||||||
ast::item_ty(t, tps) {
|
ast::item_ty(t, tps) {
|
||||||
let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
|
let tpt_ty = ty::node_id_to_type(ccx.tcx, it.id);
|
||||||
check_bounds_are_used(ccx, t.span, tps, tpt_ty);
|
check_bounds_are_used(ccx, t.span, tps, tpt_ty);
|
||||||
|
// If this is a record ty, check for duplicate fields
|
||||||
|
alt t.node {
|
||||||
|
ast::ty_rec(fields) {
|
||||||
|
check_no_duplicate_fields(ccx.tcx, fields.map(|f|
|
||||||
|
(f.node.ident, f.span)));
|
||||||
|
}
|
||||||
|
_ {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast::item_foreign_mod(m) {
|
ast::item_foreign_mod(m) {
|
||||||
if syntax::attr::foreign_abi(it.attrs) ==
|
if syntax::attr::foreign_abi(it.attrs) ==
|
||||||
|
@ -1617,6 +1648,13 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
|
||||||
fn get_node(f: spanned<field>) -> field { f.node }
|
fn get_node(f: spanned<field>) -> field { f.node }
|
||||||
let typ = ty::mk_rec(tcx, vec::map(fields_t, get_node));
|
let typ = ty::mk_rec(tcx, vec::map(fields_t, get_node));
|
||||||
fcx.write_ty(id, typ);
|
fcx.write_ty(id, typ);
|
||||||
|
/* Check for duplicate fields */
|
||||||
|
/* Only do this check if there's no base expr -- the reason is
|
||||||
|
that we're extending a record we know has no dup fields, and
|
||||||
|
it would be ill-typed anyway if we duplicated one of its
|
||||||
|
fields */
|
||||||
|
check_no_duplicate_fields(tcx, fields.map(|f|
|
||||||
|
(f.node.ident, f.span)));
|
||||||
}
|
}
|
||||||
some(bexpr) {
|
some(bexpr) {
|
||||||
let bexpr_t = fcx.expr_ty(bexpr);
|
let bexpr_t = fcx.expr_ty(bexpr);
|
||||||
|
|
6
src/test/compile-fail/issue-3033.rs
Normal file
6
src/test/compile-fail/issue-3033.rs
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
type cat = {cat_name: ~str, cat_name: int}; //~ ERROR Duplicate field name cat_name
|
||||||
|
|
||||||
|
fn main()
|
||||||
|
{
|
||||||
|
io::println(int::str({x: 1, x: 2}.x)); //~ ERROR Duplicate field name x
|
||||||
|
}
|
Loading…
Reference in a new issue