Skip to content

Commit d031ab3

Browse files
committed
---
yaml --- r: 20894 b: refs/heads/snap-stage3 c: bff512a h: refs/heads/master v: v3
1 parent fdf66f5 commit d031ab3

File tree

11 files changed

+128
-47
lines changed

11 files changed

+128
-47
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
refs/heads/master: e430a699f2c60890d9b86069fd0c68a70ece7120
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
4-
refs/heads/snap-stage3: 1e3143b34e66ca5157b03d3658d64d7c01563186
4+
refs/heads/snap-stage3: bff512a90facf2b0064f13737d44c716863f644d
55
refs/heads/try: ffbe0e0e00374358b789b0037bcb3a577cd218be
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b

branches/snap-stage3/src/libsyntax/ast.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -347,9 +347,7 @@ enum expr_ {
347347
expr_mac(mac),
348348

349349
// A struct literal expression.
350-
//
351-
// XXX: Add functional record update.
352-
expr_struct(@path, ~[field]),
350+
expr_struct(@path, ~[field], option<@expr>),
353351

354352
// A vector literal constructed from one repeated element.
355353
expr_repeat(@expr /* element */, @expr /* count */, mutability)

branches/snap-stage3/src/libsyntax/fold.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -478,8 +478,10 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
478478
fld.fold_expr(e)),
479479
expr_assert(e) => expr_assert(fld.fold_expr(e)),
480480
expr_mac(mac) => expr_mac(fold_mac(mac)),
481-
expr_struct(path, fields) => {
482-
expr_struct(fld.fold_path(path), vec::map(fields, fold_field))
481+
expr_struct(path, fields, maybe_expr) => {
482+
expr_struct(fld.fold_path(path),
483+
vec::map(fields, fold_field),
484+
option::map(maybe_expr, |x| fld.fold_expr(x)))
483485
}
484486
}
485487
}

branches/snap-stage3/src/libsyntax/parse/parser.rs

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -912,18 +912,27 @@ class parser {
912912
self.bump();
913913
let mut fields = ~[];
914914
vec::push(fields, self.parse_field(token::COLON));
915-
while self.token != token::RBRACE {
915+
while self.token != token::RBRACE &&
916+
!self.is_keyword(~"with") {
916917
self.expect(token::COMMA);
917-
if self.token == token::RBRACE {
918+
if self.token == token::RBRACE ||
919+
self.is_keyword(~"with") {
918920
// Accept an optional trailing comma.
919921
break;
920922
}
921923
vec::push(fields, self.parse_field(token::COLON));
922924
}
923925

926+
let base;
927+
if self.eat_keyword(~"with") {
928+
base = some(self.parse_expr());
929+
} else {
930+
base = none;
931+
}
932+
924933
hi = pth.span.hi;
925934
self.expect(token::RBRACE);
926-
ex = expr_struct(pth, fields);
935+
ex = expr_struct(pth, fields, base);
927936
return self.mk_pexpr(lo, hi, ex);
928937
}
929938
}

branches/snap-stage3/src/libsyntax/print/pprust.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -973,11 +973,20 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
973973
}
974974
word(s.s, ~"}");
975975
}
976-
ast::expr_struct(path, fields) => {
976+
ast::expr_struct(path, fields, wth) => {
977977
print_path(s, path, true);
978978
word(s.s, ~"{");
979979
commasep_cmnt(s, consistent, fields, print_field, get_span);
980-
word(s.s, ~",");
980+
alt wth {
981+
some(expr) => {
982+
if vec::len(fields) > 0u { space(s.s); }
983+
ibox(s, indent_unit);
984+
word_space(s, ~"with");
985+
print_expr(s, expr);
986+
end(s);
987+
}
988+
_ => word(s.s, ~",")
989+
}
981990
word(s.s, ~"}");
982991
}
983992
ast::expr_tup(exprs) => {

branches/snap-stage3/src/libsyntax/visit.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,9 +364,10 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
364364
for flds.each |f| { v.visit_expr(f.node.expr, e, v); }
365365
visit_expr_opt(base, e, v);
366366
}
367-
expr_struct(p, flds) => {
367+
expr_struct(p, flds, base) => {
368368
visit_path(p, e, v);
369369
for flds.each |f| { v.visit_expr(f.node.expr, e, v); }
370+
visit_expr_opt(base, e, v);
370371
}
371372
expr_tup(elts) => for elts.each |el| { v.visit_expr(el, e, v); }
372373
expr_call(callee, args, _) => {

branches/snap-stage3/src/rustc/middle/liveness.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1071,7 +1071,8 @@ class liveness {
10711071
}
10721072
}
10731073

1074-
expr_struct(_, fields) => {
1074+
expr_struct(_, fields, with_expr) => {
1075+
let succ = self.propagate_through_opt_expr(with_expr, succ);
10751076
do fields.foldr(succ) |field, succ| {
10761077
self.propagate_through_expr(field.node.expr, succ)
10771078
}

branches/snap-stage3/src/rustc/middle/resolve3.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4272,7 +4272,7 @@ class Resolver {
42724272
visitor);
42734273
}
42744274
4275-
expr_struct(path, _) => {
4275+
expr_struct(path, _, _) => {
42764276
// Resolve the path to the structure it goes to.
42774277
//
42784278
// XXX: We might want to support explicit type parameters in

branches/snap-stage3/src/rustc/middle/trans/base.rs

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3392,7 +3392,8 @@ fn trans_rec(bcx: block, fields: ~[ast::field],
33923392
}
33933393

33943394
fn trans_struct(block_context: block, span: span, fields: ~[ast::field],
3395-
id: ast::node_id, dest: dest) -> block {
3395+
base: option<@ast::expr>, id: ast::node_id, dest: dest)
3396+
-> block {
33963397

33973398
let _instruction_context = block_context.insn_ctxt(~"trans_struct");
33983399
let mut block_context = block_context;
@@ -3433,6 +3434,18 @@ fn trans_struct(block_context: block, span: span, fields: ~[ast::field],
34333434
}
34343435
}
34353436

3437+
// If the class has a destructor, our GEP is a little more
3438+
// complicated.
3439+
fn get_field(block_context: block, dest_address: ValueRef,
3440+
class_id: ast::def_id, index: uint) -> ValueRef {
3441+
if ty::ty_dtor(block_context.tcx(), class_id).is_some() {
3442+
return GEPi(block_context,
3443+
GEPi(block_context, dest_address, ~[0, 1]),
3444+
~[0, index]);
3445+
}
3446+
return GEPi(block_context, dest_address, ~[0, index]);
3447+
}
3448+
34363449
// Now translate each field.
34373450
let mut temp_cleanups = ~[];
34383451
for fields.each |field| {
@@ -3455,16 +3468,7 @@ fn trans_struct(block_context: block, span: span, fields: ~[ast::field],
34553468
}
34563469
}
34573470

3458-
// If the class has a destructor, our GEP is a little more
3459-
// complicated.
3460-
let dest;
3461-
if ty::ty_dtor(block_context.tcx(), class_id).is_some() {
3462-
dest = GEPi(block_context,
3463-
GEPi(block_context, dest_address, ~[0, 1]),
3464-
~[0, index]);
3465-
} else {
3466-
dest = GEPi(block_context, dest_address, ~[0, index]);
3467-
}
3471+
let dest = get_field(block_context, dest_address, class_id, index);
34683472

34693473
block_context = trans_expr_save_in(block_context,
34703474
field.node.expr,
@@ -3476,6 +3480,42 @@ fn trans_struct(block_context: block, span: span, fields: ~[ast::field],
34763480
vec::push(temp_cleanups, dest);
34773481
}
34783482

3483+
match base {
3484+
some(base_expr) => {
3485+
let { bcx: bcx, val: llbasevalue } =
3486+
trans_temp_expr(block_context, base_expr);
3487+
block_context = bcx;
3488+
3489+
// Copy over inherited fields.
3490+
for class_fields.eachi |i, class_field| {
3491+
let exists = do vec::any(fields) |provided_field| {
3492+
str::eq(provided_field.node.ident, class_field.ident)
3493+
};
3494+
if exists {
3495+
again;
3496+
}
3497+
let lldestfieldvalue = get_field(block_context,
3498+
dest_address,
3499+
class_id,
3500+
i);
3501+
let llbasefieldvalue = GEPi(block_context,
3502+
llbasevalue,
3503+
~[0, i]);
3504+
let field_type = ty::lookup_field_type(block_context.tcx(),
3505+
class_id,
3506+
class_field.id,
3507+
substitutions);
3508+
let llbasefieldvalue = load_if_immediate(block_context,
3509+
llbasefieldvalue,
3510+
field_type);
3511+
block_context = copy_val(block_context, INIT,
3512+
lldestfieldvalue, llbasefieldvalue,
3513+
field_type);
3514+
}
3515+
}
3516+
none => ()
3517+
}
3518+
34793519
// Now revoke the cleanups, as we pass responsibility for the data
34803520
// structure onto the caller.
34813521
for temp_cleanups.each |temp_cleanup| {
@@ -3633,8 +3673,8 @@ fn trans_expr(bcx: block, e: @ast::expr, dest: dest) -> block {
36333673
ast::expr_rec(args, base) => {
36343674
return trans_rec(bcx, args, base, e.id, dest);
36353675
}
3636-
ast::expr_struct(_, fields) => {
3637-
return trans_struct(bcx, e.span, fields, e.id, dest);
3676+
ast::expr_struct(_, fields, base) => {
3677+
return trans_struct(bcx, e.span, fields, base, e.id, dest);
36383678
}
36393679
ast::expr_tup(args) => { return trans_tup(bcx, args, dest); }
36403680
ast::expr_vstore(e, v) => {

branches/snap-stage3/src/rustc/middle/typeck/check.rs

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1699,7 +1699,7 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
16991699
}
17001700
}
17011701
}
1702-
ast::expr_struct(path, fields) => {
1702+
ast::expr_struct(path, fields, base_expr) => {
17031703
// Resolve the path.
17041704
let class_id;
17051705
alt tcx.def_map.find(id) {
@@ -1804,27 +1804,36 @@ fn check_expr_with_unifier(fcx: @fn_ctxt,
18041804
}
18051805
}
18061806

1807-
// Make sure the programmer specified all the fields.
1808-
assert fields_found <= class_fields.len();
1809-
if fields_found < class_fields.len() {
1810-
let mut missing_fields = ~[];
1811-
for class_fields.each |class_field| {
1812-
let name = *class_field.ident;
1813-
let (_, seen) = class_field_map.get(name);
1814-
if !seen {
1815-
vec::push(missing_fields,
1816-
~"`" + name + ~"`");
1807+
match base_expr {
1808+
none => {
1809+
// Make sure the programmer specified all the fields.
1810+
assert fields_found <= class_fields.len();
1811+
if fields_found < class_fields.len() {
1812+
let mut missing_fields = ~[];
1813+
for class_fields.each |class_field| {
1814+
let name = *class_field.ident;
1815+
let (_, seen) = class_field_map.get(name);
1816+
if !seen {
1817+
vec::push(missing_fields,
1818+
~"`" + name + ~"`");
1819+
}
1820+
}
1821+
1822+
tcx.sess.span_err(expr.span,
1823+
fmt!{"missing field%s: %s",
1824+
if missing_fields.len() == 1 {
1825+
~""
1826+
} else {
1827+
~"s"
1828+
},
1829+
str::connect(missing_fields,
1830+
~", ")});
18171831
}
18181832
}
1819-
1820-
tcx.sess.span_err(expr.span,
1821-
fmt!{"missing field%s: %s",
1822-
if missing_fields.len() == 1 {
1823-
~""
1824-
} else {
1825-
~"s"
1826-
},
1827-
str::connect(missing_fields, ~", ")});
1833+
some(base_expr) => {
1834+
// Just check the base expression.
1835+
check_expr(fcx, base_expr, some(struct_type));
1836+
}
18281837
}
18291838
18301839
// Write in the resulting type.
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
struct Foo {
2+
x: int;
3+
y: int;
4+
}
5+
6+
fn main() {
7+
let a = Foo { x: 1, y: 2 };
8+
let b = Foo { x: 3 with a };
9+
let c = Foo { x: 4, with a };
10+
io::println(fmt!("%? %?", b, c));
11+
}
12+

0 commit comments

Comments
 (0)