Add type argument field to expr_path
This way, you can explicitly provide type parameters when calling a generic method. Issue #1227
This commit is contained in:
parent
4d524b957f
commit
60acae4df7
13 changed files with 60 additions and 16 deletions
|
@ -47,7 +47,7 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) ->
|
||||||
let ds: [deref] = [], ex = ex;
|
let ds: [deref] = [], ex = ex;
|
||||||
while true {
|
while true {
|
||||||
alt copy ex.node {
|
alt copy ex.node {
|
||||||
expr_field(base, ident) {
|
expr_field(base, ident, _) {
|
||||||
let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
|
let auto_unbox = maybe_auto_unbox(tcx, ty::expr_ty(tcx, base));
|
||||||
let is_mut = false;
|
let is_mut = false;
|
||||||
alt ty::struct(tcx, auto_unbox.t) {
|
alt ty::struct(tcx, auto_unbox.t) {
|
||||||
|
|
|
@ -1771,7 +1771,7 @@ fn visit_mod_with_impl_scope(e: @env, m: ast::_mod, s: span, sc: iscopes,
|
||||||
|
|
||||||
fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
|
fn resolve_impl_in_expr(e: @env, x: @ast::expr, sc: iscopes, v: vt<iscopes>) {
|
||||||
alt x.node {
|
alt x.node {
|
||||||
ast::expr_field(_, _) { e.impl_map.insert(x.id, sc); }
|
ast::expr_field(_, _, _) { e.impl_map.insert(x.id, sc); }
|
||||||
_ {}
|
_ {}
|
||||||
}
|
}
|
||||||
visit::visit_expr(x, sc, v);
|
visit::visit_expr(x, sc, v);
|
||||||
|
|
|
@ -2858,7 +2858,7 @@ fn trans_method_callee(bcx: @block_ctxt, e: @ast::expr, base: @ast::expr,
|
||||||
fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
|
fn trans_callee(bcx: @block_ctxt, e: @ast::expr) -> lval_maybe_callee {
|
||||||
alt e.node {
|
alt e.node {
|
||||||
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
|
ast::expr_path(p) { ret trans_path(bcx, p, e.id); }
|
||||||
ast::expr_field(base, ident) {
|
ast::expr_field(base, ident, _) {
|
||||||
// Lval means this is a record field, so not a method
|
// Lval means this is a record field, so not a method
|
||||||
if !expr_is_lval(bcx, e) {
|
if !expr_is_lval(bcx, e) {
|
||||||
alt bcx_ccx(bcx).method_map.find(e.id) {
|
alt bcx_ccx(bcx).method_map.find(e.id) {
|
||||||
|
@ -2889,7 +2889,7 @@ fn trans_lval(cx: @block_ctxt, e: @ast::expr) -> lval_result {
|
||||||
let v = trans_path(cx, p, e.id);
|
let v = trans_path(cx, p, e.id);
|
||||||
ret lval_maybe_callee_to_lval(v, ty::expr_ty(bcx_tcx(cx), e));
|
ret lval_maybe_callee_to_lval(v, ty::expr_ty(bcx_tcx(cx), e));
|
||||||
}
|
}
|
||||||
ast::expr_field(base, ident) {
|
ast::expr_field(base, ident, _) {
|
||||||
ret trans_rec_field(cx, base, ident);
|
ret trans_rec_field(cx, base, ident);
|
||||||
}
|
}
|
||||||
ast::expr_index(base, idx) {
|
ast::expr_index(base, idx) {
|
||||||
|
@ -3580,7 +3580,7 @@ fn trans_expr(bcx: @block_ctxt, e: @ast::expr, dest: dest) -> @block_ctxt {
|
||||||
ast::expr_call(f, args, _) {
|
ast::expr_call(f, args, _) {
|
||||||
ret trans_call(bcx, f, args, e.id, dest);
|
ret trans_call(bcx, f, args, e.id, dest);
|
||||||
}
|
}
|
||||||
ast::expr_field(_, _) {
|
ast::expr_field(_, _, _) {
|
||||||
fail "Taking the value of a method does not work yet (issue #435)";
|
fail "Taking the value of a method does not work yet (issue #435)";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -476,7 +476,7 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) {
|
||||||
set_pre_and_post(fcx.ccx, e.id, alts_overall_pp.precondition,
|
set_pre_and_post(fcx.ccx, e.id, alts_overall_pp.precondition,
|
||||||
alts_overall_pp.postcondition);
|
alts_overall_pp.postcondition);
|
||||||
}
|
}
|
||||||
expr_field(operator, _) {
|
expr_field(operator, _, _) {
|
||||||
find_pre_post_expr(fcx, operator);
|
find_pre_post_expr(fcx, operator);
|
||||||
copy_pre_post(fcx.ccx, e.id, operator);
|
copy_pre_post(fcx.ccx, e.id, operator);
|
||||||
}
|
}
|
||||||
|
|
|
@ -551,7 +551,7 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool {
|
||||||
}
|
}
|
||||||
ret changed | set_poststate_ann(fcx.ccx, e.id, a_post);
|
ret changed | set_poststate_ann(fcx.ccx, e.id, a_post);
|
||||||
}
|
}
|
||||||
expr_field(val, _) {
|
expr_field(val, _, _) {
|
||||||
ret find_pre_post_state_sub(fcx, pres, val, e.id, none);
|
ret find_pre_post_state_sub(fcx, pres, val, e.id, none);
|
||||||
}
|
}
|
||||||
expr_unary(_, operand) {
|
expr_unary(_, operand) {
|
||||||
|
|
|
@ -1678,7 +1678,7 @@ fn expr_is_lval(method_map: typeck::method_map, tcx: ty::ctxt,
|
||||||
alt e.node {
|
alt e.node {
|
||||||
ast::expr_path(_) | ast::expr_index(_, _) |
|
ast::expr_path(_) | ast::expr_index(_, _) |
|
||||||
ast::expr_unary(ast::deref., _) { true }
|
ast::expr_unary(ast::deref., _) { true }
|
||||||
ast::expr_field(base, ident) {
|
ast::expr_field(base, ident, _) {
|
||||||
method_map.contains_key(e.id) ? false : {
|
method_map.contains_key(e.id) ? false : {
|
||||||
let basety = type_autoderef(tcx, expr_ty(tcx, base));
|
let basety = type_autoderef(tcx, expr_ty(tcx, base));
|
||||||
alt struct(tcx, basety) {
|
alt struct(tcx, basety) {
|
||||||
|
|
|
@ -2132,15 +2132,20 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::expr_field(base, field) {
|
ast::expr_field(base, field, tys) {
|
||||||
bot |= check_expr(fcx, base);
|
bot |= check_expr(fcx, base);
|
||||||
let expr_t = expr_ty(tcx, base);
|
let expr_t = expr_ty(tcx, base);
|
||||||
let base_t = do_autoderef(fcx, expr.span, expr_t);
|
let base_t = do_autoderef(fcx, expr.span, expr_t);
|
||||||
let handled = false;
|
let handled = false, n_tys = vec::len(tys);
|
||||||
alt structure_of(fcx, expr.span, base_t) {
|
alt structure_of(fcx, expr.span, base_t) {
|
||||||
ty::ty_rec(fields) {
|
ty::ty_rec(fields) {
|
||||||
alt ty::field_idx(field, fields) {
|
alt ty::field_idx(field, fields) {
|
||||||
some(ix) {
|
some(ix) {
|
||||||
|
if n_tys > 0u {
|
||||||
|
tcx.sess.span_err(expr.span,
|
||||||
|
"can't provide type parameters \
|
||||||
|
to a field access");
|
||||||
|
}
|
||||||
write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
|
write::ty_only_fixup(fcx, id, fields[ix].mt.ty);
|
||||||
handled = true;
|
handled = true;
|
||||||
}
|
}
|
||||||
|
@ -2150,6 +2155,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||||
ty::ty_obj(methods) {
|
ty::ty_obj(methods) {
|
||||||
alt ty::method_idx(field, methods) {
|
alt ty::method_idx(field, methods) {
|
||||||
some(ix) {
|
some(ix) {
|
||||||
|
if n_tys > 0u {
|
||||||
|
tcx.sess.span_err(expr.span,
|
||||||
|
"can't provide type parameters \
|
||||||
|
to an obj method");
|
||||||
|
}
|
||||||
let meth = methods[ix];
|
let meth = methods[ix];
|
||||||
let t = ty::mk_fn(tcx, meth.proto, meth.inputs,
|
let t = ty::mk_fn(tcx, meth.proto, meth.inputs,
|
||||||
meth.output, meth.cf, meth.constrs);
|
meth.output, meth.cf, meth.constrs);
|
||||||
|
@ -2181,6 +2191,25 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier,
|
||||||
fty, method.n_tps);
|
fty, method.n_tps);
|
||||||
ids += b.ids;
|
ids += b.ids;
|
||||||
fty = b.ty;
|
fty = b.ty;
|
||||||
|
if n_tys > 0u {
|
||||||
|
if n_tys != method.n_tps {
|
||||||
|
tcx.sess.span_fatal
|
||||||
|
(expr.span, "incorrect number of type \
|
||||||
|
parameters given for this method");
|
||||||
|
|
||||||
|
}
|
||||||
|
let i = 0u;
|
||||||
|
for ty in tys {
|
||||||
|
let tvar = ty::mk_var(fcx.ccx.tcx, b.ids[i]);
|
||||||
|
let t_subst = ast_ty_to_ty_crate(fcx.ccx, ty);
|
||||||
|
demand::simple(fcx, expr.span, tvar, t_subst);
|
||||||
|
i += 1u;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if n_tys > 0u {
|
||||||
|
tcx.sess.span_fatal(expr.span,
|
||||||
|
"this method does not take type \
|
||||||
|
parameters");
|
||||||
}
|
}
|
||||||
let substs = vec::map(ids, {|id| ty::mk_var(tcx, id)});
|
let substs = vec::map(ids, {|id| ty::mk_var(tcx, id)});
|
||||||
write::ty_fixup(fcx, id, {substs: some(substs), ty: fty});
|
write::ty_fixup(fcx, id, {substs: some(substs), ty: fty});
|
||||||
|
|
|
@ -238,7 +238,7 @@ tag expr_ {
|
||||||
expr_assign(@expr, @expr);
|
expr_assign(@expr, @expr);
|
||||||
expr_swap(@expr, @expr);
|
expr_swap(@expr, @expr);
|
||||||
expr_assign_op(binop, @expr, @expr);
|
expr_assign_op(binop, @expr, @expr);
|
||||||
expr_field(@expr, ident);
|
expr_field(@expr, ident, [@ty]);
|
||||||
expr_index(@expr, @expr);
|
expr_index(@expr, @expr);
|
||||||
expr_path(@path);
|
expr_path(@path);
|
||||||
expr_fail(option::t<@expr>);
|
expr_fail(option::t<@expr>);
|
||||||
|
|
|
@ -401,8 +401,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ {
|
||||||
expr_assign_op(op, el, er) {
|
expr_assign_op(op, el, er) {
|
||||||
expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er))
|
expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er))
|
||||||
}
|
}
|
||||||
expr_field(el, id) {
|
expr_field(el, id, tys) {
|
||||||
expr_field(fld.fold_expr(el), fld.fold_ident(id))
|
expr_field(fld.fold_expr(el), fld.fold_ident(id),
|
||||||
|
vec::map(tys, fld.fold_ty))
|
||||||
}
|
}
|
||||||
expr_index(el, er) {
|
expr_index(el, er) {
|
||||||
expr_index(fld.fold_expr(el), fld.fold_expr(er))
|
expr_index(fld.fold_expr(el), fld.fold_expr(er))
|
||||||
|
|
|
@ -1025,7 +1025,12 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr {
|
||||||
token::IDENT(i, _) {
|
token::IDENT(i, _) {
|
||||||
hi = p.get_hi_pos();
|
hi = p.get_hi_pos();
|
||||||
p.bump();
|
p.bump();
|
||||||
e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i)));
|
let tys = if eat(p, token::MOD_SEP) {
|
||||||
|
expect(p, token::LT);
|
||||||
|
parse_seq_to_gt(some(token::COMMA),
|
||||||
|
{|p| parse_ty(p, false)}, p)
|
||||||
|
} else { [] };
|
||||||
|
e = mk_expr(p, lo, hi, ast::expr_field(e, p.get_str(i), tys));
|
||||||
}
|
}
|
||||||
t { unexpected(p, t); }
|
t { unexpected(p, t); }
|
||||||
}
|
}
|
||||||
|
|
|
@ -879,7 +879,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||||
word_space(s, "=");
|
word_space(s, "=");
|
||||||
print_expr(s, rhs);
|
print_expr(s, rhs);
|
||||||
}
|
}
|
||||||
ast::expr_field(expr, id) {
|
ast::expr_field(expr, id, tys) {
|
||||||
// Deal with '10.x'
|
// Deal with '10.x'
|
||||||
if ends_in_lit_int(expr) {
|
if ends_in_lit_int(expr) {
|
||||||
popen(s); print_expr(s, expr); pclose(s);
|
popen(s); print_expr(s, expr); pclose(s);
|
||||||
|
@ -888,6 +888,11 @@ fn print_expr(s: ps, &&expr: @ast::expr) {
|
||||||
}
|
}
|
||||||
word(s.s, ".");
|
word(s.s, ".");
|
||||||
word(s.s, id);
|
word(s.s, id);
|
||||||
|
if vec::len(tys) > 0u {
|
||||||
|
word(s.s, "::<");
|
||||||
|
commasep(s, inconsistent, tys, print_type);
|
||||||
|
word(s.s, ">");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ast::expr_index(expr, index) {
|
ast::expr_index(expr, index) {
|
||||||
print_expr_parens_if_not_bot(s, expr);
|
print_expr_parens_if_not_bot(s, expr);
|
||||||
|
|
|
@ -295,7 +295,10 @@ fn visit_expr<E>(ex: @expr, e: E, v: vt<E>) {
|
||||||
v.visit_expr(b, e, v);
|
v.visit_expr(b, e, v);
|
||||||
v.visit_expr(a, e, v);
|
v.visit_expr(a, e, v);
|
||||||
}
|
}
|
||||||
expr_field(x, _) { v.visit_expr(x, e, v); }
|
expr_field(x, _, tys) {
|
||||||
|
v.visit_expr(x, e, v);
|
||||||
|
for tp in tys { v.visit_ty(tp, e, v); }
|
||||||
|
}
|
||||||
expr_index(a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
|
expr_index(a, b) { v.visit_expr(a, e, v); v.visit_expr(b, e, v); }
|
||||||
expr_path(p) { visit_path(p, e, v); }
|
expr_path(p) { visit_path(p, e, v); }
|
||||||
expr_fail(eo) { visit_expr_opt(eo, e, v); }
|
expr_fail(eo) { visit_expr_opt(eo, e, v); }
|
||||||
|
|
|
@ -35,6 +35,7 @@ fn main() {
|
||||||
|
|
||||||
assert [1].len().str() == "1";
|
assert [1].len().str() == "1";
|
||||||
assert [3, 4].map({|a| a + 4})[0] == 7;
|
assert [3, 4].map({|a| a + 4})[0] == 7;
|
||||||
|
assert [3, 4].map::<uint>({|a| a as uint + 4u})[0] == 7u;
|
||||||
let x = 0u;
|
let x = 0u;
|
||||||
10u.times {|_n| x += 2u;}
|
10u.times {|_n| x += 2u;}
|
||||||
assert x == 20u;
|
assert x == 20u;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue