diff --git a/src/comp/middle/mut.rs b/src/comp/middle/mut.rs index d3856f4bd2d2..d9b78d27cfbb 100644 --- a/src/comp/middle/mut.rs +++ b/src/comp/middle/mut.rs @@ -47,7 +47,7 @@ fn expr_root(tcx: ty::ctxt, ex: @expr, autoderef: bool) -> let ds: [deref] = [], ex = ex; while true { 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 is_mut = false; alt ty::struct(tcx, auto_unbox.t) { diff --git a/src/comp/middle/resolve.rs b/src/comp/middle/resolve.rs index c00bd711eb0e..fa0e67fa22ae 100644 --- a/src/comp/middle/resolve.rs +++ b/src/comp/middle/resolve.rs @@ -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) { 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); diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 8a37d27d973c..f9237199ba16 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -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 { alt e.node { 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 if !expr_is_lval(bcx, e) { 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); 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); } 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, _) { 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)"; } diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index d341e90f8166..33ab3da4f39e 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -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, alts_overall_pp.postcondition); } - expr_field(operator, _) { + expr_field(operator, _, _) { find_pre_post_expr(fcx, operator); copy_pre_post(fcx.ccx, e.id, operator); } diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index db020ec1bb07..701ac5e04b01 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -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); } - expr_field(val, _) { + expr_field(val, _, _) { ret find_pre_post_state_sub(fcx, pres, val, e.id, none); } expr_unary(_, operand) { diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index 521b73f3c11d..bf317b3b5900 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1678,7 +1678,7 @@ fn expr_is_lval(method_map: typeck::method_map, tcx: ty::ctxt, alt e.node { ast::expr_path(_) | ast::expr_index(_, _) | ast::expr_unary(ast::deref., _) { true } - ast::expr_field(base, ident) { + ast::expr_field(base, ident, _) { method_map.contains_key(e.id) ? false : { let basety = type_autoderef(tcx, expr_ty(tcx, base)); alt struct(tcx, basety) { diff --git a/src/comp/middle/typeck.rs b/src/comp/middle/typeck.rs index 0dbd052241f0..4beb93d0bfab 100644 --- a/src/comp/middle/typeck.rs +++ b/src/comp/middle/typeck.rs @@ -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); let expr_t = expr_ty(tcx, base); 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) { ty::ty_rec(fields) { alt ty::field_idx(field, fields) { 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); handled = true; } @@ -2150,6 +2155,11 @@ fn check_expr_with_unifier(fcx: @fn_ctxt, expr: @ast::expr, unify: unifier, ty::ty_obj(methods) { alt ty::method_idx(field, methods) { 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 t = ty::mk_fn(tcx, meth.proto, meth.inputs, 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); ids += b.ids; 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)}); write::ty_fixup(fcx, id, {substs: some(substs), ty: fty}); diff --git a/src/comp/syntax/ast.rs b/src/comp/syntax/ast.rs index b7af23e9dd5c..0b3a03c6b1ac 100644 --- a/src/comp/syntax/ast.rs +++ b/src/comp/syntax/ast.rs @@ -238,7 +238,7 @@ tag expr_ { expr_assign(@expr, @expr); expr_swap(@expr, @expr); expr_assign_op(binop, @expr, @expr); - expr_field(@expr, ident); + expr_field(@expr, ident, [@ty]); expr_index(@expr, @expr); expr_path(@path); expr_fail(option::t<@expr>); diff --git a/src/comp/syntax/fold.rs b/src/comp/syntax/fold.rs index 5f4ebbf3da3d..e55326dbdcea 100644 --- a/src/comp/syntax/fold.rs +++ b/src/comp/syntax/fold.rs @@ -401,8 +401,9 @@ fn noop_fold_expr(e: expr_, fld: ast_fold) -> expr_ { expr_assign_op(op, el, er) { expr_assign_op(op, fld.fold_expr(el), fld.fold_expr(er)) } - expr_field(el, id) { - expr_field(fld.fold_expr(el), fld.fold_ident(id)) + expr_field(el, id, tys) { + expr_field(fld.fold_expr(el), fld.fold_ident(id), + vec::map(tys, fld.fold_ty)) } expr_index(el, er) { expr_index(fld.fold_expr(el), fld.fold_expr(er)) diff --git a/src/comp/syntax/parse/parser.rs b/src/comp/syntax/parse/parser.rs index 752a433e9536..f1db62e24e20 100644 --- a/src/comp/syntax/parse/parser.rs +++ b/src/comp/syntax/parse/parser.rs @@ -1025,7 +1025,12 @@ fn parse_dot_or_call_expr_with(p: parser, e: @ast::expr) -> @ast::expr { token::IDENT(i, _) { hi = p.get_hi_pos(); 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); } } diff --git a/src/comp/syntax/print/pprust.rs b/src/comp/syntax/print/pprust.rs index 9b3d047d4357..92a5d228c26e 100644 --- a/src/comp/syntax/print/pprust.rs +++ b/src/comp/syntax/print/pprust.rs @@ -879,7 +879,7 @@ fn print_expr(s: ps, &&expr: @ast::expr) { word_space(s, "="); print_expr(s, rhs); } - ast::expr_field(expr, id) { + ast::expr_field(expr, id, tys) { // Deal with '10.x' if ends_in_lit_int(expr) { 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, id); + if vec::len(tys) > 0u { + word(s.s, "::<"); + commasep(s, inconsistent, tys, print_type); + word(s.s, ">"); + } } ast::expr_index(expr, index) { print_expr_parens_if_not_bot(s, expr); diff --git a/src/comp/syntax/visit.rs b/src/comp/syntax/visit.rs index a1feec5bec91..7ca54272edf3 100644 --- a/src/comp/syntax/visit.rs +++ b/src/comp/syntax/visit.rs @@ -295,7 +295,10 @@ fn visit_expr(ex: @expr, e: E, v: vt) { v.visit_expr(b, 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_path(p) { visit_path(p, e, v); } expr_fail(eo) { visit_expr_opt(eo, e, v); } diff --git a/src/test/run-pass/static-impl.rs b/src/test/run-pass/static-impl.rs index 9d245a22bb7a..8f9acab6128d 100644 --- a/src/test/run-pass/static-impl.rs +++ b/src/test/run-pass/static-impl.rs @@ -35,6 +35,7 @@ fn main() { assert [1].len().str() == "1"; assert [3, 4].map({|a| a + 4})[0] == 7; + assert [3, 4].map::({|a| a as uint + 4u})[0] == 7u; let x = 0u; 10u.times {|_n| x += 2u;} assert x == 20u;