Skip to content

Commit 11b6489

Browse files
committed
---
yaml --- r: 36061 b: refs/heads/try2 c: 1048f9a h: refs/heads/master i: 36059: d42adde v: v3
1 parent 77d0a44 commit 11b6489

File tree

2 files changed

+133
-123
lines changed

2 files changed

+133
-123
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ refs/heads/snap-stage3: eb8fd119c65c67f3b1b8268cc7341c22d39b7b61
55
refs/heads/try: d324a424d8f84b1eb049b12cf34182bda91b0024
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
8-
refs/heads/try2: ec1c60c4d6b54d30c11c79e1fa51dc6cbee61223
8+
refs/heads/try2: 1048f9abfac08c59d313e0764c909cfa0821a39e
99
refs/heads/incoming: d9317a174e434d4c99fc1a37fd7dc0d2f5328d37
1010
refs/heads/dist-snap: 22efa39382d41b084fde1719df7ae8ce5697d8c9
1111
refs/tags/release-0.2: c870d2dffb391e14efb05aa27898f1f6333a9596

branches/try2/src/rustc/middle/typeck/check.rs

Lines changed: 132 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -1441,6 +1441,136 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
14411441
return bot;
14421442
}
14431443
1444+
fn check_struct_constructor(fcx: @fn_ctxt,
1445+
id: ast::node_id,
1446+
span: syntax::codemap::span,
1447+
class_id: ast::def_id,
1448+
fields: ~[ast::field],
1449+
base_expr: Option<@ast::expr>) -> bool {
1450+
let mut bot = false;
1451+
let tcx = fcx.ccx.tcx;
1452+
1453+
// Look up the number of type parameters and the raw type, and
1454+
// determine whether the class is region-parameterized.
1455+
let type_parameter_count, region_parameterized, raw_type;
1456+
if class_id.crate == ast::local_crate {
1457+
region_parameterized =
1458+
tcx.region_paramd_items.find(class_id.node);
1459+
match tcx.items.find(class_id.node) {
1460+
Some(ast_map::node_item(@{
1461+
node: ast::item_class(_, type_parameters),
1462+
_
1463+
}, _)) => {
1464+
1465+
type_parameter_count = type_parameters.len();
1466+
1467+
let self_region =
1468+
bound_self_region(region_parameterized);
1469+
1470+
raw_type = ty::mk_class(tcx, class_id, {
1471+
self_r: self_region,
1472+
self_ty: None,
1473+
tps: ty::ty_params_to_tys(tcx, type_parameters)
1474+
});
1475+
}
1476+
_ => {
1477+
tcx.sess.span_bug(span,
1478+
~"resolve didn't map this to a class");
1479+
}
1480+
}
1481+
} else {
1482+
let item_type = ty::lookup_item_type(tcx, class_id);
1483+
type_parameter_count = (*item_type.bounds).len();
1484+
region_parameterized = item_type.region_param;
1485+
raw_type = item_type.ty;
1486+
}
1487+
1488+
// Generate the struct type.
1489+
let self_region =
1490+
fcx.region_var_if_parameterized(region_parameterized,
1491+
span,
1492+
ty::re_scope(id));
1493+
let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
1494+
let substitutions = {
1495+
self_r: self_region,
1496+
self_ty: None,
1497+
tps: type_parameters
1498+
};
1499+
1500+
let struct_type = ty::subst(tcx, &substitutions, raw_type);
1501+
1502+
// Look up the class fields and build up a map.
1503+
let class_fields = ty::lookup_class_fields(tcx, class_id);
1504+
let class_field_map = HashMap();
1505+
let mut fields_found = 0;
1506+
for class_fields.each |field| {
1507+
// XXX: Check visibility here.
1508+
class_field_map.insert(field.ident, (field.id, false));
1509+
}
1510+
1511+
// Typecheck each field.
1512+
for fields.each |field| {
1513+
match class_field_map.find(field.node.ident) {
1514+
None => {
1515+
tcx.sess.span_err(
1516+
field.span,
1517+
fmt!("structure has no field named field named `%s`",
1518+
tcx.sess.str_of(field.node.ident)));
1519+
}
1520+
Some((_, true)) => {
1521+
tcx.sess.span_err(
1522+
field.span,
1523+
fmt!("field `%s` specified more than once",
1524+
tcx.sess.str_of(field.node.ident)));
1525+
}
1526+
Some((field_id, false)) => {
1527+
let expected_field_type =
1528+
ty::lookup_field_type(tcx, class_id, field_id,
1529+
&substitutions);
1530+
bot |= check_expr(fcx,
1531+
field.node.expr,
1532+
Some(expected_field_type));
1533+
fields_found += 1;
1534+
}
1535+
}
1536+
}
1537+
1538+
match base_expr {
1539+
None => {
1540+
// Make sure the programmer specified all the fields.
1541+
assert fields_found <= class_fields.len();
1542+
if fields_found < class_fields.len() {
1543+
let mut missing_fields = ~[];
1544+
for class_fields.each |class_field| {
1545+
let name = class_field.ident;
1546+
let (_, seen) = class_field_map.get(name);
1547+
if !seen {
1548+
missing_fields.push(
1549+
~"`" + tcx.sess.str_of(name) + ~"`");
1550+
}
1551+
}
1552+
1553+
tcx.sess.span_err(span,
1554+
fmt!("missing field%s: %s",
1555+
if missing_fields.len() == 1 {
1556+
~""
1557+
} else {
1558+
~"s"
1559+
},
1560+
str::connect(missing_fields,
1561+
~", ")));
1562+
}
1563+
}
1564+
Some(base_expr) => {
1565+
// Just check the base expression.
1566+
check_expr(fcx, base_expr, Some(struct_type));
1567+
}
1568+
}
1569+
1570+
// Write in the resulting type.
1571+
fcx.write_ty(id, struct_type);
1572+
return bot;
1573+
}
14441574
14451575
let tcx = fcx.ccx.tcx;
14461576
let id = expr.id;
@@ -1911,136 +2041,16 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
19112041
}
19122042
ast::expr_struct(path, fields, base_expr) => {
19132043
// Resolve the path.
1914-
let class_id;
19152044
match tcx.def_map.find(id) {
19162045
Some(ast::def_class(type_def_id)) => {
1917-
class_id = type_def_id;
2046+
check_struct_constructor(fcx, id, expr.span, type_def_id,
2047+
fields, base_expr);
19182048
}
19192049
_ => {
19202050
tcx.sess.span_bug(path.span, ~"structure constructor does \
19212051
not name a structure type");
19222052
}
19232053
}
1924-
1925-
// Look up the number of type parameters and the raw type, and
1926-
// determine whether the class is region-parameterized.
1927-
let type_parameter_count, region_parameterized, raw_type;
1928-
if class_id.crate == ast::local_crate {
1929-
region_parameterized =
1930-
tcx.region_paramd_items.find(class_id.node);
1931-
match tcx.items.find(class_id.node) {
1932-
Some(ast_map::node_item(@{
1933-
node: ast::item_class(_, type_parameters),
1934-
_
1935-
}, _)) => {
1936-
1937-
type_parameter_count = type_parameters.len();
1938-
1939-
let self_region =
1940-
bound_self_region(region_parameterized);
1941-
1942-
raw_type = ty::mk_class(tcx, class_id, {
1943-
self_r: self_region,
1944-
self_ty: None,
1945-
tps: ty::ty_params_to_tys(tcx, type_parameters)
1946-
});
1947-
}
1948-
_ => {
1949-
tcx.sess.span_bug(expr.span,
1950-
~"resolve didn't map this to a class");
1951-
}
1952-
}
1953-
} else {
1954-
let item_type = ty::lookup_item_type(tcx, class_id);
1955-
type_parameter_count = (*item_type.bounds).len();
1956-
region_parameterized = item_type.region_param;
1957-
raw_type = item_type.ty;
1958-
}
1959-
1960-
// Generate the struct type.
1961-
let self_region =
1962-
fcx.region_var_if_parameterized(region_parameterized,
1963-
expr.span,
1964-
ty::re_scope(expr.id));
1965-
let type_parameters = fcx.infcx().next_ty_vars(type_parameter_count);
1966-
let substitutions = {
1967-
self_r: self_region,
1968-
self_ty: None,
1969-
tps: type_parameters
1970-
};
1971-
1972-
let struct_type = ty::subst(tcx, &substitutions, raw_type);
1973-
1974-
// Look up the class fields and build up a map.
1975-
let class_fields = ty::lookup_class_fields(tcx, class_id);
1976-
let class_field_map = HashMap();
1977-
let mut fields_found = 0;
1978-
for class_fields.each |field| {
1979-
// XXX: Check visibility here.
1980-
class_field_map.insert(field.ident, (field.id, false));
1981-
}
1982-
1983-
// Typecheck each field.
1984-
for fields.each |field| {
1985-
match class_field_map.find(field.node.ident) {
1986-
None => {
1987-
tcx.sess.span_err(
1988-
field.span,
1989-
fmt!("structure has no field named field named `%s`",
1990-
tcx.sess.str_of(field.node.ident)));
1991-
}
1992-
Some((_, true)) => {
1993-
tcx.sess.span_err(
1994-
field.span,
1995-
fmt!("field `%s` specified more than once",
1996-
tcx.sess.str_of(field.node.ident)));
1997-
}
1998-
Some((field_id, false)) => {
1999-
let expected_field_type =
2000-
ty::lookup_field_type(tcx, class_id, field_id,
2001-
&substitutions);
2002-
bot |= check_expr(fcx,
2003-
field.node.expr,
2004-
Some(expected_field_type));
2005-
fields_found += 1;
2006-
}
2007-
}
2008-
}
2009-
2010-
match base_expr {
2011-
None => {
2012-
// Make sure the programmer specified all the fields.
2013-
assert fields_found <= class_fields.len();
2014-
if fields_found < class_fields.len() {
2015-
let mut missing_fields = ~[];
2016-
for class_fields.each |class_field| {
2017-
let name = class_field.ident;
2018-
let (_, seen) = class_field_map.get(name);
2019-
if !seen {
2020-
missing_fields.push(
2021-
~"`" + tcx.sess.str_of(name) + ~"`");
2022-
}
2023-
}
2024-
2025-
tcx.sess.span_err(expr.span,
2026-
fmt!("missing field%s: %s",
2027-
if missing_fields.len() == 1 {
2028-
~""
2029-
} else {
2030-
~"s"
2031-
},
2032-
str::connect(missing_fields,
2033-
~", ")));
2034-
}
2035-
}
2036-
Some(base_expr) => {
2037-
// Just check the base expression.
2038-
check_expr(fcx, base_expr, Some(struct_type));
2039-
}
2040-
}
2041-
2042-
// Write in the resulting type.
2043-
fcx.write_ty(id, struct_type);
20442054
}
20452055
ast::expr_field(base, field, tys) => {
20462056
bot = check_field(fcx, expr, false, base, field, tys);

0 commit comments

Comments
 (0)