Skip to content

Commit 60acae4

Browse files
committed
Add type argument field to expr_path
This way, you can explicitly provide type parameters when calling a generic method. Issue #1227
1 parent 4d524b9 commit 60acae4

File tree

13 files changed

+60
-16
lines changed

13 files changed

+60
-16
lines changed

src/comp/middle/mut.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
4747
let ds: [deref] = [], ex = ex;
4848
while true {
4949
alt copy ex.node {
50-
expr_field(base, ident) {
50+
expr_field(base, ident, _) {
5151
let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
5252
let is_mut = false;
5353
alt ty::struct(tcx, auto_unbox.t) {

src/comp/middle/resolve.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1771,7 +1771,7 @@ fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, sc: iscopes,
17711771

17721772
fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
17731773
alt x.node {
1774-
ast::expr_field(_, _) { e.impl_map.insert(x.id, sc); }
1774+
ast::expr_field(_, _, _) { e.impl_map.insert(x.id, sc); }
17751775
_ {}
17761776
}
17771777
visit::visit_expr(x, sc, v);

src/comp/middle/trans.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2858,7 +2858,7 @@ fn trans_method_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
28582858
fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
28592859
alt e.node {
28602860
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
2861-
ast::expr_field(base, ident) {
2861+
ast::expr_field(base, ident, _) {
28622862
// Lval means this is a record field, so not a method
28632863
if !expr_is_lval(bcx, e) {
28642864
alt bcx_ccx(bcx).method_map.find(e.id) {
@@ -2889,7 +2889,7 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
28892889
let v = trans_path(cx, p, e.id);
28902890
ret lval_maybe_callee_to_lval(v, ty::expr_ty(bcx_tcx(cx), e));
28912891
}
2892-
ast::expr_field(base, ident) {
2892+
ast::expr_field(base, ident, _) {
28932893
ret trans_rec_field(cx, base, ident);
28942894
}
28952895
ast::expr_index(base, idx) {
@@ -3580,7 +3580,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
35803580
ast::expr_call(f, args, _) {
35813581
ret trans_call(bcx, f, args, e.id, dest);
35823582
}
3583-
ast::expr_field(_, _) {
3583+
ast::expr_field(_, _, _) {
35843584
fail "Taking the value of a method does not work yet (issue #435)";
35853585
}
35863586

src/comp/middle/tstate/pre_post_conditions.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -476,7 +476,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
476476
set_pre_and_post(fcx.ccx, e.id, alts_overall_pp.precondition,
477477
alts_overall_pp.postcondition);
478478
}
479-
expr_field(operator, _) {
479+
expr_field(operator, _, _) {
480480
find_pre_post_expr(fcx, operator);
481481
copy_pre_post(fcx.ccx, e.id, operator);
482482
}

src/comp/middle/tstate/states.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
551551
}
552552
ret changed | set_poststate_ann(fcx.ccx, e.id, a_post);
553553
}
554-
expr_field(val, _) {
554+
expr_field(val, _, _) {
555555
ret find_pre_post_state_sub(fcx, pres, val, e.id, none);
556556
}
557557
expr_unary(_, operand) {

src/comp/middle/ty.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1678,7 +1678,7 @@ fn expr_is_lval(method_map: typeck::method_map, tcx: ty::ctxt,
16781678
alt e.node {
16791679
ast::expr_path(_) | ast::expr_index(_, _) |
16801680
ast::expr_unary(ast::deref., _) { true }
1681-
ast::expr_field(base, ident) {
1681+
ast::expr_field(base, ident, _) {
16821682
method_map.contains_key(e.id) ? false : {
16831683
let basety = type_autoderef(tcx, expr_ty(tcx, base));
16841684
alt struct(tcx, basety) {

src/comp/middle/typeck.rs

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2132,15 +2132,20 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
21322132
}
21332133
}
21342134
}
2135-
ast::expr_field(base, field) {
2135+
ast::expr_field(base, field, tys) {
21362136
bot |= check_expr(fcx, base);
21372137
let expr_t = expr_ty(tcx, base);
21382138
let base_t = do_autoderef(fcx, expr.span, expr_t);
2139-
let handled = false;
2139+
let handled = false, n_tys = vec::len(tys);
21402140
alt structure_of(fcx, expr.span, base_t) {
21412141
ty::ty_rec(fields) {
21422142
alt ty::field_idx(field, fields) {
21432143
some(ix) {
2144+
if n_tys > 0u {
2145+
tcx.sess.span_err(expr.span,
2146+
"can't provide type parameters \
2147+
to a field access");
2148+
}
21442149
write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
21452150
handled = true;
21462151
}
@@ -2150,6 +2155,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
21502155
ty::ty_obj(methods) {
21512156
alt ty::method_idx(field, methods) {
21522157
some(ix) {
2158+
if n_tys > 0u {
2159+
tcx.sess.span_err(expr.span,
2160+
"can't provide type parameters \
2161+
to an obj method");
2162+
}
21532163
let meth = methods[ix];
21542164
let t = ty::mk_fn(tcx, meth.proto, meth.inputs,
21552165
meth.output, meth.cf, meth.constrs);
@@ -2181,6 +2191,25 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
21812191
fty, method.n_tps);
21822192
ids += b.ids;
21832193
fty = b.ty;
2194+
if n_tys > 0u {
2195+
if n_tys != method.n_tps {
2196+
tcx.sess.span_fatal
2197+
(expr.span, "incorrect number of type \
2198+
parameters given for this method");
2199+
2200+
}
2201+
let i = 0u;
2202+
for ty in tys {
2203+
let tvar = ty::mk_var(fcx.ccx.tcx, b.ids[i]);
2204+
let t_subst = ast_ty_to_ty_crate(fcx.ccx, ty);
2205+
demand::simple(fcx, expr.span, tvar, t_subst);
2206+
i += 1u;
2207+
}
2208+
}
2209+
} else if n_tys > 0u {
2210+
tcx.sess.span_fatal(expr.span,
2211+
"this method does not take type \
2212+
parameters");
21842213
}
21852214
let substs = vec::map(ids, {|id| ty::mk_var(tcx, id)});
21862215
write::ty_fixup(fcx, id, {substs: some(substs), ty: fty});

src/comp/syntax/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -238,7 +238,7 @@ tag expr_ {
238238
expr_assign(@expr, @expr);
239239
expr_swap(@expr, @expr);
240240
expr_assign_op(binop, @expr, @expr);
241-
expr_field(@expr, ident);
241+
expr_field(@expr, ident, [@ty]);
242242
expr_index(@expr, @expr);
243243
expr_path(@path);
244244
expr_fail(option::t<@expr>);

src/comp/syntax/fold.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -401,8 +401,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
401401
expr_assign_op(op, el, er) {
402402
expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er))
403403
}
404-
expr_field(el, id) {
405-
expr_field(fld.fold_expr(el), fld.fold_ident(id))
404+
expr_field(el, id, tys) {
405+
expr_field(fld.fold_expr(el), fld.fold_ident(id),
406+
vec::map(tys, fld.fold_ty))
406407
}
407408
expr_index(el, er) {
408409
expr_index(fld.fold_expr(el), fld.fold_expr(er))

src/comp/syntax/parse/parser.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1025,7 +1025,12 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
10251025
token::IDENT(i, _) {
10261026
hi = p.get_hi_pos();
10271027
p.bump();
1028-
e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i)));
1028+
let tys = if eat(p, token::MOD_SEP) {
1029+
expect(p, token::LT);
1030+
parse_seq_to_gt(some(token::COMMA),
1031+
{|p| parse_ty(p, false)}, p)
1032+
} else { [] };
1033+
e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i), tys));
10291034
}
10301035
t { unexpected(p, t); }
10311036
}

src/comp/syntax/print/pprust.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -879,7 +879,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
879879
word_space(s, "=");
880880
print_expr(s, rhs);
881881
}
882-
ast::expr_field(expr, id) {
882+
ast::expr_field(expr, id, tys) {
883883
// Deal with '10.x'
884884
if ends_in_lit_int(expr) {
885885
popen(s); print_expr(s, expr); pclose(s);
@@ -888,6 +888,11 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
888888
}
889889
word(s.s, ".");
890890
word(s.s, id);
891+
if vec::len(tys) > 0u {
892+
word(s.s, "::<");
893+
commasep(s, inconsistent, tys, print_type);
894+
word(s.s, ">");
895+
}
891896
}
892897
ast::expr_index(expr, index) {
893898
print_expr_parens_if_not_bot(s, expr);

src/comp/syntax/visit.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,10 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
295295
v.visit_expr(b, e, v);
296296
v.visit_expr(a, e, v);
297297
}
298-
expr_field(x, _) { v.visit_expr(x, e, v); }
298+
expr_field(x, _, tys) {
299+
v.visit_expr(x, e, v);
300+
for tp in tys { v.visit_ty(tp, e, v); }
301+
}
299302
expr_index(a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
300303
expr_path(p) { visit_path(p, e, v); }
301304
expr_fail(eo) { visit_expr_opt(eo, e, v); }

src/test/run-pass/static-impl.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ fn main() {
3535

3636
assert [1].len().str() == "1";
3737
assert [3, 4].map({|a| a + 4})[0] == 7;
38+
assert [3, 4].map::<uint>({|a| a as uint + 4u})[0] == 7u;
3839
let x = 0u;
3940
10u.times {|_n| x += 2u;}
4041
assert x == 20u;

0 commit comments

Comments
 (0)