Replace callee_id with information stored in method_map.
This commit is contained in:
parent
7a588ceff2
commit
05e4d944a9
43 changed files with 478 additions and 550 deletions
|
@ -255,7 +255,7 @@ impl Visitor<()> for Context {
|
||||||
|
|
||||||
fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
|
fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
|
||||||
match e.node {
|
match e.node {
|
||||||
ast::ExprUnary(_, ast::UnBox, _) => {
|
ast::ExprUnary(ast::UnBox, _) => {
|
||||||
self.gate_box(e.span);
|
self.gate_box(e.span);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -21,7 +21,7 @@ use metadata::tydecode;
|
||||||
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
|
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
|
||||||
RegionParameter};
|
RegionParameter};
|
||||||
use metadata::tyencode;
|
use metadata::tyencode;
|
||||||
use middle::typeck::method_origin;
|
use middle::typeck::{MethodCallee, MethodOrigin};
|
||||||
use middle::{ty, typeck, moves};
|
use middle::{ty, typeck, moves};
|
||||||
use middle;
|
use middle;
|
||||||
use util::ppaux::ty_to_str;
|
use util::ppaux::ty_to_str;
|
||||||
|
@ -574,10 +574,50 @@ impl tr for moves::CaptureVar {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ______________________________________________________________________
|
// ______________________________________________________________________
|
||||||
// Encoding and decoding of method_origin
|
// Encoding and decoding of MethodCallee
|
||||||
|
|
||||||
impl tr for method_origin {
|
trait read_method_callee_helper {
|
||||||
fn tr(&self, xcx: @ExtendedDecodeContext) -> method_origin {
|
fn read_method_callee(&mut self, xcx: @ExtendedDecodeContext) -> MethodCallee;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn encode_method_callee(ecx: &e::EncodeContext,
|
||||||
|
ebml_w: &mut writer::Encoder,
|
||||||
|
method: &MethodCallee) {
|
||||||
|
ebml_w.emit_struct("MethodCallee", 3, |ebml_w| {
|
||||||
|
ebml_w.emit_struct_field("origin", 0u, |ebml_w| {
|
||||||
|
method.origin.encode(ebml_w);
|
||||||
|
});
|
||||||
|
ebml_w.emit_struct_field("ty", 1u, |ebml_w| {
|
||||||
|
ebml_w.emit_ty(ecx, method.ty);
|
||||||
|
});
|
||||||
|
ebml_w.emit_struct_field("substs", 2u, |ebml_w| {
|
||||||
|
ebml_w.emit_substs(ecx, &method.substs);
|
||||||
|
});
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> read_method_callee_helper for reader::Decoder<'a> {
|
||||||
|
fn read_method_callee(&mut self, xcx: @ExtendedDecodeContext) -> MethodCallee {
|
||||||
|
self.read_struct("MethodCallee", 3, |this| {
|
||||||
|
MethodCallee {
|
||||||
|
origin: this.read_struct_field("origin", 0, |this| {
|
||||||
|
let method_origin: MethodOrigin =
|
||||||
|
Decodable::decode(this);
|
||||||
|
method_origin.tr(xcx)
|
||||||
|
}),
|
||||||
|
ty: this.read_struct_field("ty", 1, |this| {
|
||||||
|
this.read_ty(xcx)
|
||||||
|
}),
|
||||||
|
substs: this.read_struct_field("substs", 2, |this| {
|
||||||
|
this.read_substs(xcx)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl tr for MethodOrigin {
|
||||||
|
fn tr(&self, xcx: @ExtendedDecodeContext) -> MethodOrigin {
|
||||||
match *self {
|
match *self {
|
||||||
typeck::MethodStatic(did) => typeck::MethodStatic(did.tr(xcx)),
|
typeck::MethodStatic(did) => typeck::MethodStatic(did.tr(xcx)),
|
||||||
typeck::MethodParam(ref mp) => {
|
typeck::MethodParam(ref mp) => {
|
||||||
|
@ -991,17 +1031,13 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
for &method in maps.method_map.borrow().get().find(&id).iter() {
|
||||||
let method_map = maps.method_map.borrow();
|
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
|
||||||
let r = method_map.get().find(&id);
|
ebml_w.id(id);
|
||||||
for &origin in r.iter() {
|
ebml_w.tag(c::tag_table_val, |ebml_w| {
|
||||||
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
|
encode_method_callee(ecx, ebml_w, method)
|
||||||
ebml_w.id(id);
|
|
||||||
ebml_w.tag(c::tag_table_val, |ebml_w| {
|
|
||||||
origin.encode(ebml_w);
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
{
|
{
|
||||||
|
@ -1335,9 +1371,8 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
|
||||||
ty_param_defs.get().insert(id, bounds);
|
ty_param_defs.get().insert(id, bounds);
|
||||||
}
|
}
|
||||||
c::tag_table_method_map => {
|
c::tag_table_method_map => {
|
||||||
let origin: method_origin = Decodable::decode(val_dsr);
|
let method = val_dsr.read_method_callee(xcx);
|
||||||
let mut method_map = dcx.maps.method_map.borrow_mut();
|
dcx.maps.method_map.borrow_mut().get().insert(id, method);
|
||||||
method_map.get().insert(id, origin.tr(xcx));
|
|
||||||
}
|
}
|
||||||
c::tag_table_vtable_map => {
|
c::tag_table_vtable_map => {
|
||||||
let vtable_res =
|
let vtable_res =
|
||||||
|
|
|
@ -784,7 +784,6 @@ impl<'a> CheckLoanCtxt<'a> {
|
||||||
pub fn check_call(&self,
|
pub fn check_call(&self,
|
||||||
_expr: &ast::Expr,
|
_expr: &ast::Expr,
|
||||||
_callee: Option<@ast::Expr>,
|
_callee: Option<@ast::Expr>,
|
||||||
_callee_id: ast::NodeId,
|
|
||||||
_callee_span: Span,
|
_callee_span: Span,
|
||||||
_args: &[@ast::Expr]) {
|
_args: &[@ast::Expr]) {
|
||||||
// NB: This call to check for conflicting loans is not truly
|
// NB: This call to check for conflicting loans is not truly
|
||||||
|
@ -828,23 +827,22 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>,
|
||||||
this.check_captured_variables(expr.id, expr.span)
|
this.check_captured_variables(expr.id, expr.span)
|
||||||
}
|
}
|
||||||
ast::ExprAssign(dest, _) |
|
ast::ExprAssign(dest, _) |
|
||||||
ast::ExprAssignOp(_, _, dest, _) => {
|
ast::ExprAssignOp(_, dest, _) => {
|
||||||
this.check_assignment(dest);
|
this.check_assignment(dest);
|
||||||
}
|
}
|
||||||
ast::ExprCall(f, ref args) => {
|
ast::ExprCall(f, ref args) => {
|
||||||
this.check_call(expr, Some(f), f.id, f.span, *args);
|
this.check_call(expr, Some(f), f.span, *args);
|
||||||
}
|
}
|
||||||
ast::ExprMethodCall(callee_id, _, _, ref args) => {
|
ast::ExprMethodCall(_, _, ref args) => {
|
||||||
this.check_call(expr, None, callee_id, expr.span, *args);
|
this.check_call(expr, None, expr.span, *args);
|
||||||
}
|
}
|
||||||
ast::ExprIndex(callee_id, _, rval) |
|
ast::ExprIndex(_, rval) | ast::ExprBinary(_, _, rval)
|
||||||
ast::ExprBinary(callee_id, _, _, rval)
|
|
||||||
if method_map.get().contains_key(&expr.id) => {
|
if method_map.get().contains_key(&expr.id) => {
|
||||||
this.check_call(expr, None, callee_id, expr.span, [rval]);
|
this.check_call(expr, None, expr.span, [rval]);
|
||||||
}
|
}
|
||||||
ast::ExprUnary(callee_id, _, _) | ast::ExprIndex(callee_id, _, _)
|
ast::ExprUnary(_, _) | ast::ExprIndex(_, _)
|
||||||
if method_map.get().contains_key(&expr.id) => {
|
if method_map.get().contains_key(&expr.id) => {
|
||||||
this.check_call(expr, None, callee_id, expr.span, []);
|
this.check_call(expr, None, expr.span, []);
|
||||||
}
|
}
|
||||||
ast::ExprInlineAsm(ref ia) => {
|
ast::ExprInlineAsm(ref ia) => {
|
||||||
for &(_, out) in ia.outputs.iter() {
|
for &(_, out) in ia.outputs.iter() {
|
||||||
|
|
|
@ -181,20 +181,9 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
|
||||||
|
|
||||||
this.id_range.add(ex.id);
|
this.id_range.add(ex.id);
|
||||||
|
|
||||||
{
|
|
||||||
let r = ex.get_callee_id();
|
|
||||||
for callee_id in r.iter() {
|
|
||||||
this.id_range.add(*callee_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If this expression is borrowed, have to ensure it remains valid:
|
// If this expression is borrowed, have to ensure it remains valid:
|
||||||
{
|
for &adjustments in tcx.adjustments.borrow().get().find(&ex.id).iter() {
|
||||||
let adjustments = tcx.adjustments.borrow();
|
this.guarantee_adjustments(ex, *adjustments);
|
||||||
let r = adjustments.get().find(&ex.id);
|
|
||||||
for &adjustments in r.iter() {
|
|
||||||
this.guarantee_adjustments(ex, *adjustments);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If this expression is a move, gather it:
|
// If this expression is a move, gather it:
|
||||||
|
@ -225,7 +214,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
|
||||||
visit::walk_expr(this, ex, ());
|
visit::walk_expr(this, ex, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprAssign(l, _) | ast::ExprAssignOp(_, _, l, _) => {
|
ast::ExprAssign(l, _) | ast::ExprAssignOp(_, l, _) => {
|
||||||
let l_cmt = this.bccx.cat_expr(l);
|
let l_cmt = this.bccx.cat_expr(l);
|
||||||
match opt_loan_path(l_cmt) {
|
match opt_loan_path(l_cmt) {
|
||||||
Some(l_lp) => {
|
Some(l_lp) => {
|
||||||
|
@ -252,8 +241,8 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
|
||||||
visit::walk_expr(this, ex, ());
|
visit::walk_expr(this, ex, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(_, _, arg) |
|
ast::ExprIndex(_, arg) |
|
||||||
ast::ExprBinary(_, _, _, arg)
|
ast::ExprBinary(_, _, arg)
|
||||||
if method_map.get().contains_key(&ex.id) => {
|
if method_map.get().contains_key(&ex.id) => {
|
||||||
// Arguments in method calls are always passed by ref.
|
// Arguments in method calls are always passed by ref.
|
||||||
//
|
//
|
||||||
|
|
|
@ -305,7 +305,7 @@ impl CFGBuilder {
|
||||||
expr_exit
|
expr_exit
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprBinary(_, op, l, r) if ast_util::lazy_binop(op) => {
|
ast::ExprBinary(op, l, r) if ast_util::lazy_binop(op) => {
|
||||||
//
|
//
|
||||||
// [pred]
|
// [pred]
|
||||||
// |
|
// |
|
||||||
|
@ -355,16 +355,16 @@ impl CFGBuilder {
|
||||||
self.call(expr, pred, func, *args)
|
self.call(expr, pred, func, *args)
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprMethodCall(_, _, _, ref args) => {
|
ast::ExprMethodCall(_, _, ref args) => {
|
||||||
self.call(expr, pred, args[0], args.slice_from(1))
|
self.call(expr, pred, args[0], args.slice_from(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(_, l, r) |
|
ast::ExprIndex(l, r) |
|
||||||
ast::ExprBinary(_, _, l, r) if self.is_method_call(expr) => {
|
ast::ExprBinary(_, l, r) if self.is_method_call(expr) => {
|
||||||
self.call(expr, pred, l, [r])
|
self.call(expr, pred, l, [r])
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprUnary(_, _, e) if self.is_method_call(expr) => {
|
ast::ExprUnary(_, e) if self.is_method_call(expr) => {
|
||||||
self.call(expr, pred, e, [])
|
self.call(expr, pred, e, [])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -384,12 +384,12 @@ impl CFGBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprAssign(l, r) |
|
ast::ExprAssign(l, r) |
|
||||||
ast::ExprAssignOp(_, _, l, r) => {
|
ast::ExprAssignOp(_, l, r) => {
|
||||||
self.straightline(expr, pred, [r, l])
|
self.straightline(expr, pred, [r, l])
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(_, l, r) |
|
ast::ExprIndex(l, r) |
|
||||||
ast::ExprBinary(_, _, l, r) => { // NB: && and || handled earlier
|
ast::ExprBinary(_, l, r) => { // NB: && and || handled earlier
|
||||||
self.straightline(expr, pred, [l, r])
|
self.straightline(expr, pred, [l, r])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -399,7 +399,7 @@ impl CFGBuilder {
|
||||||
|
|
||||||
ast::ExprAddrOf(_, e) |
|
ast::ExprAddrOf(_, e) |
|
||||||
ast::ExprCast(e, _) |
|
ast::ExprCast(e, _) |
|
||||||
ast::ExprUnary(_, _, e) |
|
ast::ExprUnary(_, e) |
|
||||||
ast::ExprParen(e) |
|
ast::ExprParen(e) |
|
||||||
ast::ExprVstore(e, _) |
|
ast::ExprVstore(e, _) |
|
||||||
ast::ExprField(e, _, _) => {
|
ast::ExprField(e, _, _) => {
|
||||||
|
|
|
@ -108,8 +108,8 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
|
||||||
is_const: bool) {
|
is_const: bool) {
|
||||||
if is_const {
|
if is_const {
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprUnary(_, UnDeref, _) => { }
|
ExprUnary(UnDeref, _) => { }
|
||||||
ExprUnary(_, UnBox, _) | ExprUnary(_, UnUniq, _) => {
|
ExprUnary(UnBox, _) | ExprUnary(UnUniq, _) => {
|
||||||
sess.span_err(e.span,
|
sess.span_err(e.span,
|
||||||
"cannot do allocations in constant expressions");
|
"cannot do allocations in constant expressions");
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -225,10 +225,10 @@ impl ConstEvalVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprUnary(_, _, inner) | ast::ExprParen(inner) =>
|
ast::ExprUnary(_, inner) | ast::ExprParen(inner) =>
|
||||||
self.classify(inner),
|
self.classify(inner),
|
||||||
|
|
||||||
ast::ExprBinary(_, _, a, b) =>
|
ast::ExprBinary(_, a, b) =>
|
||||||
join(self.classify(a), self.classify(b)),
|
join(self.classify(a), self.classify(b)),
|
||||||
|
|
||||||
ast::ExprTup(ref es) |
|
ast::ExprTup(ref es) |
|
||||||
|
@ -262,7 +262,7 @@ impl ConstEvalVisitor {
|
||||||
|
|
||||||
ast::ExprField(base, _, _) => self.classify(base),
|
ast::ExprField(base, _, _) => self.classify(base),
|
||||||
|
|
||||||
ast::ExprIndex(_, base, idx) =>
|
ast::ExprIndex(base, idx) =>
|
||||||
join(self.classify(base), self.classify(idx)),
|
join(self.classify(base), self.classify(idx)),
|
||||||
|
|
||||||
ast::ExprAddrOf(ast::MutImmutable, base) => self.classify(base),
|
ast::ExprAddrOf(ast::MutImmutable, base) => self.classify(base),
|
||||||
|
@ -336,7 +336,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
|
||||||
use middle::ty;
|
use middle::ty;
|
||||||
fn fromb(b: bool) -> Result<const_val, ~str> { Ok(const_int(b as i64)) }
|
fn fromb(b: bool) -> Result<const_val, ~str> { Ok(const_int(b as i64)) }
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprUnary(_, UnNeg, inner) => {
|
ExprUnary(UnNeg, inner) => {
|
||||||
match eval_const_expr_partial(tcx, inner) {
|
match eval_const_expr_partial(tcx, inner) {
|
||||||
Ok(const_float(f)) => Ok(const_float(-f)),
|
Ok(const_float(f)) => Ok(const_float(-f)),
|
||||||
Ok(const_int(i)) => Ok(const_int(-i)),
|
Ok(const_int(i)) => Ok(const_int(-i)),
|
||||||
|
@ -346,7 +346,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
|
||||||
ref err => ((*err).clone())
|
ref err => ((*err).clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprUnary(_, UnNot, inner) => {
|
ExprUnary(UnNot, inner) => {
|
||||||
match eval_const_expr_partial(tcx, inner) {
|
match eval_const_expr_partial(tcx, inner) {
|
||||||
Ok(const_int(i)) => Ok(const_int(!i)),
|
Ok(const_int(i)) => Ok(const_int(!i)),
|
||||||
Ok(const_uint(i)) => Ok(const_uint(!i)),
|
Ok(const_uint(i)) => Ok(const_uint(!i)),
|
||||||
|
@ -354,7 +354,7 @@ pub fn eval_const_expr_partial<T: ty::ExprTyProvider>(tcx: &T, e: &Expr)
|
||||||
_ => Err(~"not on float or string")
|
_ => Err(~"not on float or string")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprBinary(_, op, a, b) => {
|
ExprBinary(op, a, b) => {
|
||||||
match (eval_const_expr_partial(tcx, a),
|
match (eval_const_expr_partial(tcx, a),
|
||||||
eval_const_expr_partial(tcx, b)) {
|
eval_const_expr_partial(tcx, b)) {
|
||||||
(Ok(const_float(a)), Ok(const_float(b))) => {
|
(Ok(const_float(a)), Ok(const_float(b))) => {
|
||||||
|
|
|
@ -556,7 +556,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprAssign(l, r) |
|
ast::ExprAssign(l, r) |
|
||||||
ast::ExprAssignOp(_, _, l, r) => {
|
ast::ExprAssignOp(_, l, r) => {
|
||||||
self.walk_expr(r, in_out, loop_scopes);
|
self.walk_expr(r, in_out, loop_scopes);
|
||||||
self.walk_expr(l, in_out, loop_scopes);
|
self.walk_expr(l, in_out, loop_scopes);
|
||||||
}
|
}
|
||||||
|
@ -579,35 +579,35 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
|
||||||
|
|
||||||
ast::ExprCall(f, ref args) => {
|
ast::ExprCall(f, ref args) => {
|
||||||
self.walk_expr(f, in_out, loop_scopes);
|
self.walk_expr(f, in_out, loop_scopes);
|
||||||
self.walk_call(f.id, expr.id, *args, in_out, loop_scopes);
|
self.walk_call(expr.id, *args, in_out, loop_scopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprMethodCall(callee_id, _, _, ref args) => {
|
ast::ExprMethodCall(_, _, ref args) => {
|
||||||
self.walk_call(callee_id, expr.id, *args, in_out, loop_scopes);
|
self.walk_call(expr.id, *args, in_out, loop_scopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(callee_id, l, r) |
|
ast::ExprIndex(l, r) |
|
||||||
ast::ExprBinary(callee_id, _, l, r) if self.is_method_call(expr) => {
|
ast::ExprBinary(_, l, r) if self.is_method_call(expr) => {
|
||||||
self.walk_call(callee_id, expr.id, [l, r], in_out, loop_scopes);
|
self.walk_call(expr.id, [l, r], in_out, loop_scopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprUnary(callee_id, _, e) if self.is_method_call(expr) => {
|
ast::ExprUnary(_, e) if self.is_method_call(expr) => {
|
||||||
self.walk_call(callee_id, expr.id, [e], in_out, loop_scopes);
|
self.walk_call(expr.id, [e], in_out, loop_scopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprTup(ref exprs) => {
|
ast::ExprTup(ref exprs) => {
|
||||||
self.walk_exprs(*exprs, in_out, loop_scopes);
|
self.walk_exprs(*exprs, in_out, loop_scopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprBinary(_, op, l, r) if ast_util::lazy_binop(op) => {
|
ast::ExprBinary(op, l, r) if ast_util::lazy_binop(op) => {
|
||||||
self.walk_expr(l, in_out, loop_scopes);
|
self.walk_expr(l, in_out, loop_scopes);
|
||||||
let temp = in_out.to_owned();
|
let temp = in_out.to_owned();
|
||||||
self.walk_expr(r, in_out, loop_scopes);
|
self.walk_expr(r, in_out, loop_scopes);
|
||||||
join_bits(&self.dfcx.oper, temp, in_out);
|
join_bits(&self.dfcx.oper, temp, in_out);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(_, l, r) |
|
ast::ExprIndex(l, r) |
|
||||||
ast::ExprBinary(_, _, l, r) => {
|
ast::ExprBinary(_, l, r) => {
|
||||||
self.walk_exprs([l, r], in_out, loop_scopes);
|
self.walk_exprs([l, r], in_out, loop_scopes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -617,7 +617,7 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
|
||||||
|
|
||||||
ast::ExprAddrOf(_, e) |
|
ast::ExprAddrOf(_, e) |
|
||||||
ast::ExprCast(e, _) |
|
ast::ExprCast(e, _) |
|
||||||
ast::ExprUnary(_, _, e) |
|
ast::ExprUnary(_, e) |
|
||||||
ast::ExprParen(e) |
|
ast::ExprParen(e) |
|
||||||
ast::ExprVstore(e, _) |
|
ast::ExprVstore(e, _) |
|
||||||
ast::ExprField(e, _, _) => {
|
ast::ExprField(e, _, _) => {
|
||||||
|
@ -715,7 +715,6 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn walk_call(&mut self,
|
fn walk_call(&mut self,
|
||||||
_callee_id: ast::NodeId,
|
|
||||||
call_id: ast::NodeId,
|
call_id: ast::NodeId,
|
||||||
args: &[@ast::Expr],
|
args: &[@ast::Expr],
|
||||||
in_out: &mut [uint],
|
in_out: &mut [uint],
|
||||||
|
@ -723,8 +722,8 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
|
||||||
self.walk_exprs(args, in_out, loop_scopes);
|
self.walk_exprs(args, in_out, loop_scopes);
|
||||||
|
|
||||||
// FIXME(#6268) nested method calls
|
// FIXME(#6268) nested method calls
|
||||||
// self.merge_with_entry_set(callee_id, in_out);
|
// self.merge_with_entry_set(in_out);
|
||||||
// self.dfcx.apply_gen_kill(callee_id, in_out);
|
// self.dfcx.apply_gen_kill(in_out);
|
||||||
|
|
||||||
let return_ty = ty::node_id_to_type(self.tcx(), call_id);
|
let return_ty = ty::node_id_to_type(self.tcx(), call_id);
|
||||||
let fails = ty::type_is_bot(return_ty);
|
let fails = ty::type_is_bot(return_ty);
|
||||||
|
|
|
@ -92,10 +92,9 @@ impl MarkSymbolVisitor {
|
||||||
|
|
||||||
fn lookup_and_handle_method(&mut self, id: &ast::NodeId,
|
fn lookup_and_handle_method(&mut self, id: &ast::NodeId,
|
||||||
span: codemap::Span) {
|
span: codemap::Span) {
|
||||||
let method_map = self.method_map.borrow();
|
match self.method_map.borrow().get().find(id) {
|
||||||
match method_map.get().find(id) {
|
Some(method) => {
|
||||||
Some(&origin) => {
|
match method.origin {
|
||||||
match origin {
|
|
||||||
typeck::MethodStatic(def_id) => {
|
typeck::MethodStatic(def_id) => {
|
||||||
match ty::provided_source(self.tcx, def_id) {
|
match ty::provided_source(self.tcx, def_id) {
|
||||||
Some(p_did) => self.check_def_id(p_did),
|
Some(p_did) => self.check_def_id(p_did),
|
||||||
|
|
|
@ -65,7 +65,7 @@ impl EffectCheckVisitor {
|
||||||
|
|
||||||
fn check_str_index(&mut self, e: @ast::Expr) {
|
fn check_str_index(&mut self, e: @ast::Expr) {
|
||||||
let base_type = match e.node {
|
let base_type = match e.node {
|
||||||
ast::ExprIndex(_, base, _) => ty::node_id_to_type(self.tcx, base.id),
|
ast::ExprIndex(base, _) => ty::node_id_to_type(self.tcx, base.id),
|
||||||
_ => return
|
_ => return
|
||||||
};
|
};
|
||||||
debug!("effect: checking index with base type {}",
|
debug!("effect: checking index with base type {}",
|
||||||
|
@ -137,8 +137,8 @@ impl Visitor<()> for EffectCheckVisitor {
|
||||||
|
|
||||||
fn visit_expr(&mut self, expr: &ast::Expr, _:()) {
|
fn visit_expr(&mut self, expr: &ast::Expr, _:()) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::ExprMethodCall(callee_id, _, _, _) => {
|
ast::ExprMethodCall(_, _, _) => {
|
||||||
let base_type = ty::node_id_to_type(self.tcx, callee_id);
|
let base_type = self.method_map.borrow().get().get(&expr.id).ty;
|
||||||
debug!("effect: method call case, base type is {}",
|
debug!("effect: method call case, base type is {}",
|
||||||
ppaux::ty_to_str(self.tcx, base_type));
|
ppaux::ty_to_str(self.tcx, base_type));
|
||||||
if type_is_unsafe_function(base_type) {
|
if type_is_unsafe_function(base_type) {
|
||||||
|
@ -154,7 +154,7 @@ impl Visitor<()> for EffectCheckVisitor {
|
||||||
self.require_unsafe(expr.span, "call to unsafe function")
|
self.require_unsafe(expr.span, "call to unsafe function")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprUnary(_, ast::UnDeref, base) => {
|
ast::ExprUnary(ast::UnDeref, base) => {
|
||||||
let base_type = ty::node_id_to_type(self.tcx, base.id);
|
let base_type = ty::node_id_to_type(self.tcx, base.id);
|
||||||
debug!("effect: unary case, base type is {}",
|
debug!("effect: unary case, base type is {}",
|
||||||
ppaux::ty_to_str(self.tcx, base_type));
|
ppaux::ty_to_str(self.tcx, base_type));
|
||||||
|
@ -166,7 +166,7 @@ impl Visitor<()> for EffectCheckVisitor {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprAssign(base, _) | ast::ExprAssignOp(_, _, base, _) => {
|
ast::ExprAssign(base, _) | ast::ExprAssignOp(_, base, _) => {
|
||||||
self.check_str_index(base);
|
self.check_str_index(base);
|
||||||
}
|
}
|
||||||
ast::ExprAddrOf(ast::MutMutable, base) => {
|
ast::ExprAddrOf(ast::MutMutable, base) => {
|
||||||
|
|
|
@ -264,13 +264,14 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
|
||||||
debug!("kind::check_expr({})", expr_to_str(e));
|
debug!("kind::check_expr({})", expr_to_str(e));
|
||||||
|
|
||||||
// Handle any kind bounds on type parameters
|
// Handle any kind bounds on type parameters
|
||||||
let type_parameter_id = match e.get_callee_id() {
|
|
||||||
Some(callee_id) => callee_id,
|
|
||||||
None => e.id,
|
|
||||||
};
|
|
||||||
{
|
{
|
||||||
|
let method_map = cx.method_map.borrow();
|
||||||
|
let method = method_map.get().find(&e.id);
|
||||||
let node_type_substs = cx.tcx.node_type_substs.borrow();
|
let node_type_substs = cx.tcx.node_type_substs.borrow();
|
||||||
let r = node_type_substs.get().find(&type_parameter_id);
|
let r = match method {
|
||||||
|
Some(method) => Some(&method.substs.tps),
|
||||||
|
None => node_type_substs.get().find(&e.id)
|
||||||
|
};
|
||||||
for ts in r.iter() {
|
for ts in r.iter() {
|
||||||
let def_map = cx.tcx.def_map.borrow();
|
let def_map = cx.tcx.def_map.borrow();
|
||||||
let type_param_defs = match e.node {
|
let type_param_defs = match e.node {
|
||||||
|
@ -285,9 +286,9 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
|
||||||
|
|
||||||
// Even though the callee_id may have been the id with
|
// Even though the callee_id may have been the id with
|
||||||
// node_type_substs, e.id is correct here.
|
// node_type_substs, e.id is correct here.
|
||||||
match cx.method_map.borrow().get().find(&e.id) {
|
match method {
|
||||||
Some(origin) => {
|
Some(method) => {
|
||||||
ty::method_call_type_param_defs(cx.tcx, *origin)
|
ty::method_call_type_param_defs(cx.tcx, method.origin)
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
cx.tcx.sess.span_bug(e.span,
|
cx.tcx.sess.span_bug(e.span,
|
||||||
|
@ -306,13 +307,13 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
|
||||||
type_param_defs.repr(cx.tcx));
|
type_param_defs.repr(cx.tcx));
|
||||||
}
|
}
|
||||||
for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
|
for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
|
||||||
check_typaram_bounds(cx, type_parameter_id, e.span, ty, type_param_def)
|
check_typaram_bounds(cx, e.span, ty, type_param_def)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
match e.node {
|
match e.node {
|
||||||
ExprUnary(_, UnBox, interior) => {
|
ExprUnary(UnBox, interior) => {
|
||||||
let interior_type = ty::expr_ty(cx.tcx, interior);
|
let interior_type = ty::expr_ty(cx.tcx, interior);
|
||||||
let _ = check_durable(cx.tcx, interior_type, interior.span);
|
let _ = check_durable(cx.tcx, interior_type, interior.span);
|
||||||
}
|
}
|
||||||
|
@ -373,7 +374,7 @@ fn check_ty(cx: &mut Context, aty: &Ty) {
|
||||||
let generics = ty::lookup_item_type(cx.tcx, did).generics;
|
let generics = ty::lookup_item_type(cx.tcx, did).generics;
|
||||||
let type_param_defs = generics.type_param_defs();
|
let type_param_defs = generics.type_param_defs();
|
||||||
for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
|
for (&ty, type_param_def) in ts.iter().zip(type_param_defs.iter()) {
|
||||||
check_typaram_bounds(cx, aty.id, aty.span, ty, type_param_def)
|
check_typaram_bounds(cx, aty.span, ty, type_param_def)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -400,11 +401,9 @@ pub fn check_builtin_bounds(cx: &Context,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn check_typaram_bounds(cx: &Context,
|
pub fn check_typaram_bounds(cx: &Context,
|
||||||
_type_parameter_id: NodeId,
|
sp: Span,
|
||||||
sp: Span,
|
ty: ty::t,
|
||||||
ty: ty::t,
|
type_param_def: &ty::TypeParameterDef) {
|
||||||
type_param_def: &ty::TypeParameterDef)
|
|
||||||
{
|
|
||||||
check_builtin_bounds(cx,
|
check_builtin_bounds(cx,
|
||||||
ty,
|
ty,
|
||||||
type_param_def.bounds.builtin_bounds,
|
type_param_def.bounds.builtin_bounds,
|
||||||
|
|
|
@ -674,7 +674,7 @@ fn check_unused_casts(cx: &Context, e: &ast::Expr) {
|
||||||
|
|
||||||
fn check_type_limits(cx: &Context, e: &ast::Expr) {
|
fn check_type_limits(cx: &Context, e: &ast::Expr) {
|
||||||
return match e.node {
|
return match e.node {
|
||||||
ast::ExprBinary(_, binop, l, r) => {
|
ast::ExprBinary(binop, l, r) => {
|
||||||
if is_comparison(binop) && !check_limits(cx.tcx, binop, l, r) {
|
if is_comparison(binop) && !check_limits(cx.tcx, binop, l, r) {
|
||||||
cx.span_lint(TypeLimits, e.span,
|
cx.span_lint(TypeLimits, e.span,
|
||||||
"comparison is useless due to type limits");
|
"comparison is useless due to type limits");
|
||||||
|
@ -1176,7 +1176,7 @@ fn check_unnecessary_parens_expr(cx: &Context, e: &ast::Expr) {
|
||||||
ast::ExprMatch(head, _) => (head, "`match` head expression"),
|
ast::ExprMatch(head, _) => (head, "`match` head expression"),
|
||||||
ast::ExprRet(Some(value)) => (value, "`return` value"),
|
ast::ExprRet(Some(value)) => (value, "`return` value"),
|
||||||
ast::ExprAssign(_, value) => (value, "assigned value"),
|
ast::ExprAssign(_, value) => (value, "assigned value"),
|
||||||
ast::ExprAssignOp(_, _, _, value) => (value, "assigned value"),
|
ast::ExprAssignOp(_, _, value) => (value, "assigned value"),
|
||||||
_ => return
|
_ => return
|
||||||
};
|
};
|
||||||
check_unnecessary_parens_core(cx, value, msg);
|
check_unnecessary_parens_core(cx, value, msg);
|
||||||
|
@ -1263,8 +1263,8 @@ fn check_unnecessary_allocation(cx: &Context, e: &ast::Expr) {
|
||||||
_ => return
|
_ => return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprUnary(_, ast::UnUniq, _) |
|
ast::ExprUnary(ast::UnUniq, _) |
|
||||||
ast::ExprUnary(_, ast::UnBox, _) => BoxAllocation,
|
ast::ExprUnary(ast::UnBox, _) => BoxAllocation,
|
||||||
|
|
||||||
_ => return
|
_ => return
|
||||||
};
|
};
|
||||||
|
@ -1411,10 +1411,9 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprMethodCall(..) => {
|
ast::ExprMethodCall(..) => {
|
||||||
let method_map = cx.method_map.borrow();
|
match cx.method_map.borrow().get().find(&e.id) {
|
||||||
match method_map.get().find(&e.id) {
|
Some(method) => {
|
||||||
Some(&origin) => {
|
match method.origin {
|
||||||
match origin {
|
|
||||||
typeck::MethodStatic(def_id) => {
|
typeck::MethodStatic(def_id) => {
|
||||||
// If this implements a trait method, get def_id
|
// If this implements a trait method, get def_id
|
||||||
// of the method inside trait definition.
|
// of the method inside trait definition.
|
||||||
|
@ -1531,7 +1530,7 @@ impl<'a> Visitor<()> for Context<'a> {
|
||||||
|
|
||||||
fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
|
fn visit_expr(&mut self, e: &ast::Expr, _: ()) {
|
||||||
match e.node {
|
match e.node {
|
||||||
ast::ExprUnary(_, ast::UnNeg, expr) => {
|
ast::ExprUnary(ast::UnNeg, expr) => {
|
||||||
// propagate negation, if the negation itself isn't negated
|
// propagate negation, if the negation itself isn't negated
|
||||||
if self.negated_expr_id != e.id {
|
if self.negated_expr_id != e.id {
|
||||||
self.negated_expr_id = expr.id;
|
self.negated_expr_id = expr.id;
|
||||||
|
|
|
@ -534,7 +534,7 @@ fn visit_expr(v: &mut LivenessVisitor, expr: &Expr, this: @IrMaps) {
|
||||||
visit::walk_expr(v, expr, this);
|
visit::walk_expr(v, expr, this);
|
||||||
}
|
}
|
||||||
ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
|
ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
|
||||||
ExprBinary(_, op, _, _) if ast_util::lazy_binop(op) => {
|
ExprBinary(op, _, _) if ast_util::lazy_binop(op) => {
|
||||||
this.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
this.add_live_node_for_node(expr.id, ExprNode(expr.span));
|
||||||
visit::walk_expr(v, expr, this);
|
visit::walk_expr(v, expr, this);
|
||||||
}
|
}
|
||||||
|
@ -1179,7 +1179,7 @@ impl Liveness {
|
||||||
self.propagate_through_expr(r, succ)
|
self.propagate_through_expr(r, succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprAssignOp(_, _, l, r) => {
|
ExprAssignOp(_, l, r) => {
|
||||||
// see comment on lvalues in
|
// see comment on lvalues in
|
||||||
// propagate_through_lvalue_components()
|
// propagate_through_lvalue_components()
|
||||||
let succ = self.write_lvalue(l, succ, ACC_WRITE|ACC_READ);
|
let succ = self.write_lvalue(l, succ, ACC_WRITE|ACC_READ);
|
||||||
|
@ -1219,10 +1219,10 @@ impl Liveness {
|
||||||
self.propagate_through_expr(f, succ)
|
self.propagate_through_expr(f, succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprMethodCall(callee_id, _, _, ref args) => {
|
ExprMethodCall(_, _, ref args) => {
|
||||||
// calling a method with bot return type means that the method
|
// calling a method with bot return type means that the method
|
||||||
// will fail, and hence the successors can be ignored
|
// will fail, and hence the successors can be ignored
|
||||||
let t_ret = ty::ty_fn_ret(ty::node_id_to_type(self.tcx, callee_id));
|
let t_ret = ty::node_id_to_type(self.tcx, expr.id);
|
||||||
let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
|
let succ = if ty::type_is_bot(t_ret) {self.s.exit_ln}
|
||||||
else {succ};
|
else {succ};
|
||||||
self.propagate_through_exprs(*args, succ)
|
self.propagate_through_exprs(*args, succ)
|
||||||
|
@ -1232,7 +1232,7 @@ impl Liveness {
|
||||||
self.propagate_through_exprs(*exprs, succ)
|
self.propagate_through_exprs(*exprs, succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprBinary(_, op, l, r) if ast_util::lazy_binop(op) => {
|
ExprBinary(op, l, r) if ast_util::lazy_binop(op) => {
|
||||||
let r_succ = self.propagate_through_expr(r, succ);
|
let r_succ = self.propagate_through_expr(r, succ);
|
||||||
|
|
||||||
let ln = self.live_node(expr.id, expr.span);
|
let ln = self.live_node(expr.id, expr.span);
|
||||||
|
@ -1242,15 +1242,15 @@ impl Liveness {
|
||||||
self.propagate_through_expr(l, ln)
|
self.propagate_through_expr(l, ln)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprIndex(_, l, r) |
|
ExprIndex(l, r) |
|
||||||
ExprBinary(_, _, l, r) |
|
ExprBinary(_, l, r) |
|
||||||
ExprBox(l, r) => {
|
ExprBox(l, r) => {
|
||||||
self.propagate_through_exprs([l, r], succ)
|
self.propagate_through_exprs([l, r], succ)
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprAddrOf(_, e) |
|
ExprAddrOf(_, e) |
|
||||||
ExprCast(e, _) |
|
ExprCast(e, _) |
|
||||||
ExprUnary(_, _, e) |
|
ExprUnary(_, e) |
|
||||||
ExprParen(e) => {
|
ExprParen(e) => {
|
||||||
self.propagate_through_expr(e, succ)
|
self.propagate_through_expr(e, succ)
|
||||||
}
|
}
|
||||||
|
@ -1508,7 +1508,7 @@ fn check_expr(this: &mut Liveness, expr: &Expr) {
|
||||||
visit::walk_expr(this, expr, ());
|
visit::walk_expr(this, expr, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprAssignOp(_, _, l, _) => {
|
ExprAssignOp(_, l, _) => {
|
||||||
this.check_lvalue(l);
|
this.check_lvalue(l);
|
||||||
|
|
||||||
visit::walk_expr(this, expr, ());
|
visit::walk_expr(this, expr, ());
|
||||||
|
|
|
@ -432,7 +432,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
|
||||||
|
|
||||||
let expr_ty = if_ok!(self.expr_ty(expr));
|
let expr_ty = if_ok!(self.expr_ty(expr));
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::ExprUnary(_, ast::UnDeref, e_base) => {
|
ast::ExprUnary(ast::UnDeref, e_base) => {
|
||||||
if self.typer.is_method_call(expr.id) {
|
if self.typer.is_method_call(expr.id) {
|
||||||
return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
|
return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
|
||||||
}
|
}
|
||||||
|
@ -450,7 +450,7 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
|
||||||
Ok(self.cat_field(expr, base_cmt, f_name, expr_ty))
|
Ok(self.cat_field(expr, base_cmt, f_name, expr_ty))
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(_, base, _) => {
|
ast::ExprIndex(base, _) => {
|
||||||
if self.typer.is_method_call(expr.id) {
|
if self.typer.is_method_call(expr.id) {
|
||||||
return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
|
return Ok(self.cat_rvalue_node(expr.id(), expr.span(), expr_ty));
|
||||||
}
|
}
|
||||||
|
|
|
@ -361,7 +361,7 @@ impl VisitContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprUnary(_, UnDeref, base) => { // *base
|
ExprUnary(UnDeref, base) => { // *base
|
||||||
if !self.use_overloaded_operator(expr, base, [])
|
if !self.use_overloaded_operator(expr, base, [])
|
||||||
{
|
{
|
||||||
// Moving out of *base moves out of base.
|
// Moving out of *base moves out of base.
|
||||||
|
@ -369,12 +369,12 @@ impl VisitContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprField(base, _, _) => { // base.f
|
ExprField(base, _, _) => { // base.f
|
||||||
// Moving out of base.f moves out of base.
|
// Moving out of base.f moves out of base.
|
||||||
self.use_expr(base, comp_mode);
|
self.use_expr(base, comp_mode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprIndex(_, lhs, rhs) => { // lhs[rhs]
|
ExprIndex(lhs, rhs) => { // lhs[rhs]
|
||||||
if !self.use_overloaded_operator(expr, lhs, [rhs])
|
if !self.use_overloaded_operator(expr, lhs, [rhs])
|
||||||
{
|
{
|
||||||
self.use_expr(lhs, comp_mode);
|
self.use_expr(lhs, comp_mode);
|
||||||
|
@ -409,11 +409,11 @@ impl VisitContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
self.use_expr(callee, mode);
|
self.use_expr(callee, mode);
|
||||||
self.use_fn_args(callee.id, *args);
|
self.use_fn_args(*args);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprMethodCall(callee_id, _, _, ref args) => { // callee.m(args)
|
ExprMethodCall(_, _, ref args) => { // callee.m(args)
|
||||||
self.use_fn_args(callee_id, *args);
|
self.use_fn_args(*args);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprStruct(_, ref fields, opt_with) => {
|
ExprStruct(_, ref fields, opt_with) => {
|
||||||
|
@ -521,14 +521,14 @@ impl VisitContext {
|
||||||
|
|
||||||
ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
|
ExprForLoop(..) => fail!("non-desugared expr_for_loop"),
|
||||||
|
|
||||||
ExprUnary(_, _, lhs) => {
|
ExprUnary(_, lhs) => {
|
||||||
if !self.use_overloaded_operator(expr, lhs, [])
|
if !self.use_overloaded_operator(expr, lhs, [])
|
||||||
{
|
{
|
||||||
self.consume_expr(lhs);
|
self.consume_expr(lhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprBinary(_, _, lhs, rhs) => {
|
ExprBinary(_, lhs, rhs) => {
|
||||||
if !self.use_overloaded_operator(expr, lhs, [rhs])
|
if !self.use_overloaded_operator(expr, lhs, [rhs])
|
||||||
{
|
{
|
||||||
self.consume_expr(lhs);
|
self.consume_expr(lhs);
|
||||||
|
@ -555,7 +555,7 @@ impl VisitContext {
|
||||||
self.consume_expr(base);
|
self.consume_expr(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExprAssignOp(_, _, lhs, rhs) => {
|
ExprAssignOp(_, lhs, rhs) => {
|
||||||
// FIXME(#4712) --- Overloaded operators?
|
// FIXME(#4712) --- Overloaded operators?
|
||||||
//
|
//
|
||||||
// if !self.use_overloaded_operator(expr, DoDerefArgs, lhs, [rhs])
|
// if !self.use_overloaded_operator(expr, DoDerefArgs, lhs, [rhs])
|
||||||
|
@ -668,7 +668,6 @@ impl VisitContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn use_fn_args(&mut self,
|
pub fn use_fn_args(&mut self,
|
||||||
_: NodeId,
|
|
||||||
arg_exprs: &[@Expr]) {
|
arg_exprs: &[@Expr]) {
|
||||||
//! Uses the argument expressions.
|
//! Uses the argument expressions.
|
||||||
for arg_expr in arg_exprs.iter() {
|
for arg_expr in arg_exprs.iter() {
|
||||||
|
|
|
@ -785,7 +785,7 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprMethodCall(_, ident, _, ref args) => {
|
ast::ExprMethodCall(ident, _, ref args) => {
|
||||||
// see above
|
// see above
|
||||||
let t = ty::type_autoderef(ty::expr_ty(self.tcx, args[0]));
|
let t = ty::type_autoderef(ty::expr_ty(self.tcx, args[0]));
|
||||||
match ty::get(t).sty {
|
match ty::get(t).sty {
|
||||||
|
@ -796,9 +796,9 @@ impl<'a> Visitor<()> for PrivacyVisitor<'a> {
|
||||||
"method call not in \
|
"method call not in \
|
||||||
method map");
|
method map");
|
||||||
}
|
}
|
||||||
Some(origin) => {
|
Some(method) => {
|
||||||
debug!("(privacy checking) checking impl method");
|
debug!("(privacy checking) checking impl method");
|
||||||
self.check_method(expr.span, origin, ident);
|
self.check_method(expr.span, method.origin, ident);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -147,9 +147,8 @@ impl Visitor<()> for MarkSymbolVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprMethodCall(..) => {
|
ast::ExprMethodCall(..) => {
|
||||||
let method_map = self.method_map.borrow();
|
match self.method_map.borrow().get().get(&expr.id).origin {
|
||||||
match method_map.get().find(&expr.id) {
|
typeck::MethodStatic(def_id) => {
|
||||||
Some(&typeck::method_static(def_id)) => {
|
|
||||||
if is_local(def_id) {
|
if is_local(def_id) {
|
||||||
if ReachableContext::
|
if ReachableContext::
|
||||||
def_id_represents_local_inlined_item(
|
def_id_represents_local_inlined_item(
|
||||||
|
@ -168,11 +167,7 @@ impl Visitor<()> for MarkSymbolVisitor {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(_) => {}
|
_ => {}
|
||||||
None => {
|
|
||||||
self.tcx.sess.span_bug(expr.span,
|
|
||||||
"method call expression not in method map?!")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
|
|
|
@ -512,8 +512,8 @@ fn resolve_expr(visitor: &mut RegionResolutionVisitor,
|
||||||
// scopes, meaning that temporaries cannot outlive them.
|
// scopes, meaning that temporaries cannot outlive them.
|
||||||
// This ensures fixed size stacks.
|
// This ensures fixed size stacks.
|
||||||
|
|
||||||
ast::ExprBinary(_, ast::BiAnd, _, r) |
|
ast::ExprBinary(ast::BiAnd, _, r) |
|
||||||
ast::ExprBinary(_, ast::BiOr, _, r) => {
|
ast::ExprBinary(ast::BiOr, _, r) => {
|
||||||
// For shortcircuiting operators, mark the RHS as a terminating
|
// For shortcircuiting operators, mark the RHS as a terminating
|
||||||
// scope since it only executes conditionally.
|
// scope since it only executes conditionally.
|
||||||
visitor.region_maps.mark_as_terminating_scope(r.id);
|
visitor.region_maps.mark_as_terminating_scope(r.id);
|
||||||
|
@ -756,7 +756,7 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
|
||||||
visitor, subexpr, blk_id);
|
visitor, subexpr, blk_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprUnary(_, ast::UnUniq, subexpr) => {
|
ast::ExprUnary(ast::UnUniq, subexpr) => {
|
||||||
record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
|
record_rvalue_scope_if_borrow_expr(visitor, subexpr, blk_id);
|
||||||
}
|
}
|
||||||
ast::ExprCast(subexpr, _) |
|
ast::ExprCast(subexpr, _) |
|
||||||
|
@ -811,9 +811,9 @@ fn resolve_local(visitor: &mut RegionResolutionVisitor,
|
||||||
|
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::ExprAddrOf(_, ref subexpr) |
|
ast::ExprAddrOf(_, ref subexpr) |
|
||||||
ast::ExprUnary(_, ast::UnDeref, ref subexpr) |
|
ast::ExprUnary(ast::UnDeref, ref subexpr) |
|
||||||
ast::ExprField(ref subexpr, _, _) |
|
ast::ExprField(ref subexpr, _, _) |
|
||||||
ast::ExprIndex(_, ref subexpr, _) |
|
ast::ExprIndex(ref subexpr, _) |
|
||||||
ast::ExprParen(ref subexpr) => {
|
ast::ExprParen(ref subexpr) => {
|
||||||
let subexpr: &'a @Expr = subexpr; // FIXME(#11586)
|
let subexpr: &'a @Expr = subexpr; // FIXME(#11586)
|
||||||
expr = &**subexpr;
|
expr = &**subexpr;
|
||||||
|
|
|
@ -5257,7 +5257,7 @@ impl Resolver {
|
||||||
let traits = self.search_for_traits_containing_method(ident);
|
let traits = self.search_for_traits_containing_method(ident);
|
||||||
self.trait_map.insert(expr.id, traits);
|
self.trait_map.insert(expr.id, traits);
|
||||||
}
|
}
|
||||||
ExprMethodCall(_, ident, _, _) => {
|
ExprMethodCall(ident, _, _) => {
|
||||||
debug!("(recording candidate traits for expr) recording \
|
debug!("(recording candidate traits for expr) recording \
|
||||||
traits for {}",
|
traits for {}",
|
||||||
expr.id);
|
expr.id);
|
||||||
|
|
|
@ -118,7 +118,7 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
|
||||||
match def {
|
match def {
|
||||||
ast::DefFn(did, _) |
|
ast::DefFn(did, _) |
|
||||||
ast::DefStaticMethod(did, ast::FromImpl(_), _) => {
|
ast::DefStaticMethod(did, ast::FromImpl(_), _) => {
|
||||||
fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id))
|
fn_callee(bcx, trans_fn_ref(bcx, did, ref_expr.id, false))
|
||||||
}
|
}
|
||||||
ast::DefStaticMethod(impl_did,
|
ast::DefStaticMethod(impl_did,
|
||||||
ast::FromTrait(trait_did),
|
ast::FromTrait(trait_did),
|
||||||
|
@ -132,10 +132,10 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
|
||||||
assert!(ty::enum_variant_with_id(bcx.tcx(),
|
assert!(ty::enum_variant_with_id(bcx.tcx(),
|
||||||
tid,
|
tid,
|
||||||
vid).args.len() > 0u);
|
vid).args.len() > 0u);
|
||||||
fn_callee(bcx, trans_fn_ref(bcx, vid, ref_expr.id))
|
fn_callee(bcx, trans_fn_ref(bcx, vid, ref_expr.id, false))
|
||||||
}
|
}
|
||||||
ast::DefStruct(def_id) => {
|
ast::DefStruct(def_id) => {
|
||||||
fn_callee(bcx, trans_fn_ref(bcx, def_id, ref_expr.id))
|
fn_callee(bcx, trans_fn_ref(bcx, def_id, ref_expr.id, false))
|
||||||
}
|
}
|
||||||
ast::DefStatic(..) |
|
ast::DefStatic(..) |
|
||||||
ast::DefArg(..) |
|
ast::DefArg(..) |
|
||||||
|
@ -158,16 +158,8 @@ fn trans<'a>(bcx: &'a Block<'a>, expr: &ast::Expr) -> Callee<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_fn_ref_to_callee<'a>(
|
pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId,
|
||||||
bcx: &'a Block<'a>,
|
ref_id: ast::NodeId, is_method: bool)
|
||||||
def_id: ast::DefId,
|
|
||||||
ref_id: ast::NodeId)
|
|
||||||
-> Callee<'a> {
|
|
||||||
Callee {bcx: bcx,
|
|
||||||
data: Fn(trans_fn_ref(bcx, def_id, ref_id))}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, ref_id: ast::NodeId)
|
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
|
@ -177,23 +169,22 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, ref_id: ast::NodeId)
|
||||||
|
|
||||||
let _icx = push_ctxt("trans_fn_ref");
|
let _icx = push_ctxt("trans_fn_ref");
|
||||||
|
|
||||||
let type_params = node_id_type_params(bcx, ref_id);
|
let type_params = node_id_type_params(bcx, ref_id, is_method);
|
||||||
let vtables = node_vtables(bcx, ref_id);
|
let vtables = node_vtables(bcx, ref_id);
|
||||||
debug!("trans_fn_ref(def_id={}, ref_id={:?}, type_params={}, vtables={})",
|
debug!("trans_fn_ref(def_id={}, ref_id={:?}, type_params={}, vtables={})",
|
||||||
def_id.repr(bcx.tcx()), ref_id, type_params.repr(bcx.tcx()),
|
def_id.repr(bcx.tcx()), ref_id, type_params.repr(bcx.tcx()),
|
||||||
vtables.repr(bcx.tcx()));
|
vtables.repr(bcx.tcx()));
|
||||||
trans_fn_ref_with_vtables(bcx, def_id, ref_id, type_params, vtables)
|
trans_fn_ref_with_vtables(bcx, def_id, ref_id, is_method, type_params, vtables)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_fn_ref_with_vtables_to_callee<'a>(
|
fn trans_fn_ref_with_vtables_to_callee<'a>(bcx: &'a Block<'a>,
|
||||||
bcx: &'a Block<'a>,
|
|
||||||
def_id: ast::DefId,
|
def_id: ast::DefId,
|
||||||
ref_id: ast::NodeId,
|
ref_id: ast::NodeId,
|
||||||
type_params: &[ty::t],
|
type_params: &[ty::t],
|
||||||
vtables: Option<typeck::vtable_res>)
|
vtables: Option<typeck::vtable_res>)
|
||||||
-> Callee<'a> {
|
-> Callee<'a> {
|
||||||
Callee {bcx: bcx,
|
Callee {bcx: bcx,
|
||||||
data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ref_id,
|
data: Fn(trans_fn_ref_with_vtables(bcx, def_id, ref_id, false,
|
||||||
type_params, vtables))}
|
type_params, vtables))}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -243,6 +234,7 @@ pub fn trans_fn_ref_with_vtables(
|
||||||
bcx: &Block, //
|
bcx: &Block, //
|
||||||
def_id: ast::DefId, // def id of fn
|
def_id: ast::DefId, // def id of fn
|
||||||
ref_id: ast::NodeId, // node id of use of fn; may be zero if N/A
|
ref_id: ast::NodeId, // node id of use of fn; may be zero if N/A
|
||||||
|
is_method: bool,
|
||||||
type_params: &[ty::t], // values for fn's ty params
|
type_params: &[ty::t], // values for fn's ty params
|
||||||
vtables: Option<typeck::vtable_res>) // vtables for the call
|
vtables: Option<typeck::vtable_res>) // vtables for the call
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
|
@ -388,7 +380,12 @@ pub fn trans_fn_ref_with_vtables(
|
||||||
if must_cast && ref_id != 0 {
|
if must_cast && ref_id != 0 {
|
||||||
// Monotype of the REFERENCE to the function (type params
|
// Monotype of the REFERENCE to the function (type params
|
||||||
// are subst'd)
|
// are subst'd)
|
||||||
let ref_ty = common::node_id_type(bcx, ref_id);
|
let ref_ty = if is_method {
|
||||||
|
let t = bcx.ccx().maps.method_map.borrow().get().get(&ref_id).ty;
|
||||||
|
monomorphize_type(bcx, t)
|
||||||
|
} else {
|
||||||
|
node_id_type(bcx, ref_id)
|
||||||
|
};
|
||||||
|
|
||||||
val = PointerCast(
|
val = PointerCast(
|
||||||
bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
|
bcx, val, type_of::type_of_fn_from_ty(ccx, ref_ty).ptr_to());
|
||||||
|
@ -461,41 +458,22 @@ pub fn trans_call<'a>(
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_method_call<'a>(
|
pub fn trans_method_call<'a>(
|
||||||
in_cx: &'a Block<'a>,
|
bcx: &'a Block<'a>,
|
||||||
call_ex: &ast::Expr,
|
call_ex: &ast::Expr,
|
||||||
callee_id: ast::NodeId,
|
|
||||||
rcvr: &ast::Expr,
|
rcvr: &ast::Expr,
|
||||||
args: CallArgs,
|
args: CallArgs,
|
||||||
dest: expr::Dest)
|
dest: expr::Dest)
|
||||||
-> &'a Block<'a> {
|
-> &'a Block<'a> {
|
||||||
let _icx = push_ctxt("trans_method_call");
|
let _icx = push_ctxt("trans_method_call");
|
||||||
debug!("trans_method_call(call_ex={})", call_ex.repr(in_cx.tcx()));
|
debug!("trans_method_call(call_ex={})", call_ex.repr(bcx.tcx()));
|
||||||
|
let method_ty = bcx.ccx().maps.method_map.borrow().get().get(&call_ex.id).ty;
|
||||||
trans_call_inner(
|
trans_call_inner(
|
||||||
in_cx,
|
bcx,
|
||||||
Some(common::expr_info(call_ex)),
|
Some(common::expr_info(call_ex)),
|
||||||
node_id_type(in_cx, callee_id),
|
monomorphize_type(bcx, method_ty),
|
||||||
expr_ty(in_cx, call_ex),
|
expr_ty(bcx, call_ex),
|
||||||
|cx, arg_cleanup_scope| {
|
|cx, arg_cleanup_scope| {
|
||||||
let origin_opt = {
|
meth::trans_method_callee(cx, call_ex.id, rcvr, arg_cleanup_scope)
|
||||||
let mut method_map = cx.ccx().maps.method_map.borrow_mut();
|
|
||||||
method_map.get().find_copy(&call_ex.id)
|
|
||||||
};
|
|
||||||
match origin_opt {
|
|
||||||
Some(origin) => {
|
|
||||||
debug!("origin for {}: {}",
|
|
||||||
call_ex.repr(in_cx.tcx()),
|
|
||||||
origin.repr(in_cx.tcx()));
|
|
||||||
|
|
||||||
meth::trans_method_callee(cx,
|
|
||||||
callee_id,
|
|
||||||
rcvr,
|
|
||||||
origin,
|
|
||||||
arg_cleanup_scope)
|
|
||||||
}
|
|
||||||
None => {
|
|
||||||
cx.tcx().sess.span_bug(call_ex.span, "method call expr wasn't in method map")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
args,
|
args,
|
||||||
Some(dest)).bcx
|
Some(dest)).bcx
|
||||||
|
|
|
@ -673,7 +673,7 @@ impl<'a> CleanupHelperMethods<'a> for FunctionContext<'a> {
|
||||||
|
|
||||||
// The exception handling personality function.
|
// The exception handling personality function.
|
||||||
let def_id = common::langcall(pad_bcx, None, "", EhPersonalityLangItem);
|
let def_id = common::langcall(pad_bcx, None, "", EhPersonalityLangItem);
|
||||||
let llpersonality = callee::trans_fn_ref(pad_bcx, def_id, 0);
|
let llpersonality = callee::trans_fn_ref(pad_bcx, def_id, 0, false);
|
||||||
|
|
||||||
// The only landing pad clause will be 'cleanup'
|
// The only landing pad clause will be 'cleanup'
|
||||||
let llretval = build::LandingPad(pad_bcx, llretty, llpersonality, 1u);
|
let llretval = build::LandingPad(pad_bcx, llretty, llpersonality, 1u);
|
||||||
|
|
|
@ -807,9 +807,13 @@ pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
|
||||||
monomorphize_type(bcx, t)
|
monomorphize_type(bcx, t)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_id_type_params(bcx: &Block, id: ast::NodeId) -> ~[ty::t] {
|
pub fn node_id_type_params(bcx: &Block, id: ast::NodeId, is_method: bool) -> ~[ty::t] {
|
||||||
let tcx = bcx.tcx();
|
let tcx = bcx.tcx();
|
||||||
let params = ty::node_id_to_type_params(tcx, id);
|
let params = if is_method {
|
||||||
|
bcx.ccx().maps.method_map.borrow().get().get(&id).substs.tps.clone()
|
||||||
|
} else {
|
||||||
|
ty::node_id_to_type_params(tcx, id)
|
||||||
|
};
|
||||||
|
|
||||||
if !params.iter().all(|t| !ty::type_needs_infer(*t)) {
|
if !params.iter().all(|t| !ty::type_needs_infer(*t)) {
|
||||||
bcx.sess().bug(
|
bcx.sess().bug(
|
||||||
|
|
|
@ -310,7 +310,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
|
||||||
ast::ExprLit(lit) => {
|
ast::ExprLit(lit) => {
|
||||||
(consts::const_lit(cx, e, (*lit).clone()), true)
|
(consts::const_lit(cx, e, (*lit).clone()), true)
|
||||||
}
|
}
|
||||||
ast::ExprBinary(_, b, e1, e2) => {
|
ast::ExprBinary(b, e1, e2) => {
|
||||||
let (te1, _) = const_expr(cx, e1, is_local);
|
let (te1, _) = const_expr(cx, e1, is_local);
|
||||||
let (te2, _) = const_expr(cx, e2, is_local);
|
let (te2, _) = const_expr(cx, e2, is_local);
|
||||||
|
|
||||||
|
@ -392,7 +392,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
|
||||||
},
|
},
|
||||||
}, true)
|
}, true)
|
||||||
},
|
},
|
||||||
ast::ExprUnary(_, u, e) => {
|
ast::ExprUnary(u, e) => {
|
||||||
let (te, _) = const_expr(cx, e, is_local);
|
let (te, _) = const_expr(cx, e, is_local);
|
||||||
let ty = ty::expr_ty(cx.tcx, e);
|
let ty = ty::expr_ty(cx.tcx, e);
|
||||||
let is_float = ty::type_is_fp(ty);
|
let is_float = ty::type_is_fp(ty);
|
||||||
|
@ -429,7 +429,7 @@ fn const_expr_unadjusted(cx: @CrateContext, e: &ast::Expr,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(_, base, index) => {
|
ast::ExprIndex(base, index) => {
|
||||||
let bt = ty::expr_ty_adjusted(cx.tcx, base);
|
let bt = ty::expr_ty_adjusted(cx.tcx, base);
|
||||||
let (bv, inlineable) = const_expr(cx, base, is_local);
|
let (bv, inlineable) = const_expr(cx, base, is_local);
|
||||||
let iv = match const_eval::eval_const_expr(cx.tcx, index) {
|
let iv = match const_eval::eval_const_expr(cx.tcx, index) {
|
||||||
|
|
|
@ -2539,15 +2539,13 @@ fn populate_scope_map(cx: &CrateContext,
|
||||||
None => ()
|
None => ()
|
||||||
},
|
},
|
||||||
|
|
||||||
ast::ExprUnary(node_id, _, sub_exp) => {
|
ast::ExprUnary(_, sub_exp) => {
|
||||||
scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
|
|
||||||
walk_expr(cx, sub_exp, scope_stack, scope_map);
|
walk_expr(cx, sub_exp, scope_stack, scope_map);
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprAssignOp(node_id, _, lhs, rhs) |
|
ast::ExprAssignOp(_, lhs, rhs) |
|
||||||
ast::ExprIndex(node_id, lhs, rhs) |
|
ast::ExprIndex(lhs, rhs) |
|
||||||
ast::ExprBinary(node_id, _, lhs, rhs) => {
|
ast::ExprBinary(_, lhs, rhs) => {
|
||||||
scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
|
|
||||||
walk_expr(cx, lhs, scope_stack, scope_map);
|
walk_expr(cx, lhs, scope_stack, scope_map);
|
||||||
walk_expr(cx, rhs, scope_stack, scope_map);
|
walk_expr(cx, rhs, scope_stack, scope_map);
|
||||||
}
|
}
|
||||||
|
@ -2638,9 +2636,7 @@ fn populate_scope_map(cx: &CrateContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprMethodCall(node_id, _, _, ref args) => {
|
ast::ExprMethodCall(_, _, ref args) => {
|
||||||
scope_map.insert(node_id, scope_stack.last().unwrap().scope_metadata);
|
|
||||||
|
|
||||||
for arg_exp in args.iter() {
|
for arg_exp in args.iter() {
|
||||||
walk_expr(cx, *arg_exp, scope_stack, scope_map);
|
walk_expr(cx, *arg_exp, scope_stack, scope_map);
|
||||||
}
|
}
|
||||||
|
|
|
@ -442,7 +442,7 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
|
||||||
ast::ExprField(base, ident, _) => {
|
ast::ExprField(base, ident, _) => {
|
||||||
trans_rec_field(bcx, base, ident)
|
trans_rec_field(bcx, base, ident)
|
||||||
}
|
}
|
||||||
ast::ExprIndex(_, base, idx) => {
|
ast::ExprIndex(base, idx) => {
|
||||||
trans_index(bcx, expr, base, idx)
|
trans_index(bcx, expr, base, idx)
|
||||||
}
|
}
|
||||||
ast::ExprVstore(contents, ast::ExprVstoreUniq) => {
|
ast::ExprVstore(contents, ast::ExprVstoreUniq) => {
|
||||||
|
@ -461,20 +461,17 @@ fn trans_datum_unadjusted<'a>(bcx: &'a Block<'a>,
|
||||||
return trans_boxed_expr(bcx, box_ty, contents, contents_ty, heap)
|
return trans_boxed_expr(bcx, box_ty, contents, contents_ty, heap)
|
||||||
}
|
}
|
||||||
ast::ExprLit(lit) => trans_immediate_lit(bcx, expr, (*lit).clone()),
|
ast::ExprLit(lit) => trans_immediate_lit(bcx, expr, (*lit).clone()),
|
||||||
ast::ExprBinary(_, op, lhs, rhs) => {
|
ast::ExprBinary(op, lhs, rhs) => {
|
||||||
// if overloaded, would be RvalueDpsExpr
|
// if overloaded, would be RvalueDpsExpr
|
||||||
{
|
assert!(!bcx.ccx().maps.method_map.borrow().get().contains_key(&expr.id));
|
||||||
let method_map = bcx.ccx().maps.method_map.borrow();
|
|
||||||
assert!(!method_map.get().contains_key(&expr.id));
|
|
||||||
}
|
|
||||||
|
|
||||||
trans_binary(bcx, expr, op, lhs, rhs)
|
trans_binary(bcx, expr, op, lhs, rhs)
|
||||||
}
|
}
|
||||||
ast::ExprUnary(_, ast::UnDeref, base) => {
|
ast::ExprUnary(ast::UnDeref, base) => {
|
||||||
let basedatum = unpack_datum!(bcx, trans(bcx, base));
|
let basedatum = unpack_datum!(bcx, trans(bcx, base));
|
||||||
deref_once(bcx, expr, basedatum, 0)
|
deref_once(bcx, expr, basedatum, 0)
|
||||||
}
|
}
|
||||||
ast::ExprUnary(_, op, x) => {
|
ast::ExprUnary(op, x) => {
|
||||||
trans_unary_datum(bcx, expr, op, x)
|
trans_unary_datum(bcx, expr, op, x)
|
||||||
}
|
}
|
||||||
ast::ExprAddrOf(_, x) => {
|
ast::ExprAddrOf(_, x) => {
|
||||||
|
@ -698,8 +695,8 @@ fn trans_rvalue_stmt_unadjusted<'a>(bcx: &'a Block<'a>,
|
||||||
src_datum.store_to(bcx, dst_datum.val)
|
src_datum.store_to(bcx, dst_datum.val)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprAssignOp(callee_id, op, dst, src) => {
|
ast::ExprAssignOp(op, dst, src) => {
|
||||||
trans_assign_op(bcx, expr, callee_id, op, dst, src)
|
trans_assign_op(bcx, expr, op, dst, src)
|
||||||
}
|
}
|
||||||
ast::ExprInlineAsm(ref a) => {
|
ast::ExprInlineAsm(ref a) => {
|
||||||
asm::trans_inline_asm(bcx, a)
|
asm::trans_inline_asm(bcx, a)
|
||||||
|
@ -780,26 +777,24 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
|
||||||
closure::trans_expr_fn(bcx, sigil, decl, body, expr.id, dest)
|
closure::trans_expr_fn(bcx, sigil, decl, body, expr.id, dest)
|
||||||
}
|
}
|
||||||
ast::ExprCall(f, ref args) => {
|
ast::ExprCall(f, ref args) => {
|
||||||
callee::trans_call(bcx, expr, f,
|
callee::trans_call(bcx, expr, f, callee::ArgExprs(*args), expr.id, dest)
|
||||||
callee::ArgExprs(*args), expr.id, dest)
|
|
||||||
}
|
}
|
||||||
ast::ExprMethodCall(callee_id, _, _, ref args) => {
|
ast::ExprMethodCall(_, _, ref args) => {
|
||||||
callee::trans_method_call(bcx, expr, callee_id, args[0],
|
callee::trans_method_call(bcx, expr, args[0], callee::ArgExprs(*args), dest)
|
||||||
callee::ArgExprs(*args), dest)
|
|
||||||
}
|
}
|
||||||
ast::ExprBinary(callee_id, _, lhs, rhs) => {
|
ast::ExprBinary(_, lhs, rhs) => {
|
||||||
// if not overloaded, would be RvalueDatumExpr
|
// if not overloaded, would be RvalueDatumExpr
|
||||||
trans_overloaded_op(bcx, expr, callee_id, lhs,
|
trans_overloaded_op(bcx, expr, lhs,
|
||||||
Some(&*rhs), expr_ty(bcx, expr), dest)
|
Some(&*rhs), expr_ty(bcx, expr), dest)
|
||||||
}
|
}
|
||||||
ast::ExprUnary(callee_id, _, subexpr) => {
|
ast::ExprUnary(_, subexpr) => {
|
||||||
// if not overloaded, would be RvalueDatumExpr
|
// if not overloaded, would be RvalueDatumExpr
|
||||||
trans_overloaded_op(bcx, expr, callee_id, subexpr,
|
trans_overloaded_op(bcx, expr, subexpr,
|
||||||
None, expr_ty(bcx, expr), dest)
|
None, expr_ty(bcx, expr), dest)
|
||||||
}
|
}
|
||||||
ast::ExprIndex(callee_id, base, idx) => {
|
ast::ExprIndex(base, idx) => {
|
||||||
// if not overloaded, would be RvalueDatumExpr
|
// if not overloaded, would be RvalueDatumExpr
|
||||||
trans_overloaded_op(bcx, expr, callee_id, base,
|
trans_overloaded_op(bcx, expr, base,
|
||||||
Some(&*idx), expr_ty(bcx, expr), dest)
|
Some(&*idx), expr_ty(bcx, expr), dest)
|
||||||
}
|
}
|
||||||
ast::ExprCast(val, _) => {
|
ast::ExprCast(val, _) => {
|
||||||
|
@ -815,8 +810,8 @@ fn trans_rvalue_dps_unadjusted<'a>(bcx: &'a Block<'a>,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprAssignOp(callee_id, op, dst, src) => {
|
ast::ExprAssignOp(op, dst, src) => {
|
||||||
trans_assign_op(bcx, expr, callee_id, op, dst, src)
|
trans_assign_op(bcx, expr, op, dst, src)
|
||||||
}
|
}
|
||||||
ast::ExprBox(_, contents) => {
|
ast::ExprBox(_, contents) => {
|
||||||
// Special case for `Gc<T>` for now. The other case, for unique
|
// Special case for `Gc<T>` for now. The other case, for unique
|
||||||
|
@ -851,7 +846,7 @@ fn trans_def_dps_unadjusted<'a>(
|
||||||
let variant_info = ty::enum_variant_with_id(ccx.tcx, tid, vid);
|
let variant_info = ty::enum_variant_with_id(ccx.tcx, tid, vid);
|
||||||
if variant_info.args.len() > 0u {
|
if variant_info.args.len() > 0u {
|
||||||
// N-ary variant.
|
// N-ary variant.
|
||||||
let llfn = callee::trans_fn_ref(bcx, vid, ref_expr.id);
|
let llfn = callee::trans_fn_ref(bcx, vid, ref_expr.id, false);
|
||||||
Store(bcx, llfn, lldest);
|
Store(bcx, llfn, lldest);
|
||||||
return bcx;
|
return bcx;
|
||||||
} else {
|
} else {
|
||||||
|
@ -884,15 +879,14 @@ fn trans_def_dps_unadjusted<'a>(
|
||||||
|
|
||||||
fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>,
|
fn trans_def_fn_unadjusted<'a>(bcx: &'a Block<'a>,
|
||||||
ref_expr: &ast::Expr,
|
ref_expr: &ast::Expr,
|
||||||
def: ast::Def) -> DatumBlock<'a, Expr>
|
def: ast::Def) -> DatumBlock<'a, Expr> {
|
||||||
{
|
|
||||||
let _icx = push_ctxt("trans_def_datum_unadjusted");
|
let _icx = push_ctxt("trans_def_datum_unadjusted");
|
||||||
|
|
||||||
let llfn = match def {
|
let llfn = match def {
|
||||||
ast::DefFn(did, _) |
|
ast::DefFn(did, _) |
|
||||||
ast::DefStruct(did) | ast::DefVariant(_, did, _) |
|
ast::DefStruct(did) | ast::DefVariant(_, did, _) |
|
||||||
ast::DefStaticMethod(did, ast::FromImpl(_), _) => {
|
ast::DefStaticMethod(did, ast::FromImpl(_), _) => {
|
||||||
callee::trans_fn_ref(bcx, did, ref_expr.id)
|
callee::trans_fn_ref(bcx, did, ref_expr.id, false)
|
||||||
}
|
}
|
||||||
ast::DefStaticMethod(impl_did, ast::FromTrait(trait_did), _) => {
|
ast::DefStaticMethod(impl_did, ast::FromTrait(trait_did), _) => {
|
||||||
meth::trans_static_method_callee(bcx, impl_did,
|
meth::trans_static_method_callee(bcx, impl_did,
|
||||||
|
@ -1496,26 +1490,20 @@ fn trans_binary<'a>(
|
||||||
fn trans_overloaded_op<'a, 'b>(
|
fn trans_overloaded_op<'a, 'b>(
|
||||||
bcx: &'a Block<'a>,
|
bcx: &'a Block<'a>,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
callee_id: ast::NodeId,
|
|
||||||
rcvr: &'b ast::Expr,
|
rcvr: &'b ast::Expr,
|
||||||
arg: Option<&'b ast::Expr>,
|
arg: Option<&'b ast::Expr>,
|
||||||
ret_ty: ty::t,
|
ret_ty: ty::t,
|
||||||
dest: Dest)
|
dest: Dest)
|
||||||
-> &'a Block<'a> {
|
-> &'a Block<'a> {
|
||||||
let origin = {
|
let method_ty = bcx.ccx().maps.method_map.borrow().get().get(&expr.id).ty;
|
||||||
let method_map = bcx.ccx().maps.method_map.borrow();
|
|
||||||
method_map.get().get_copy(&expr.id)
|
|
||||||
};
|
|
||||||
let fty = node_id_type(bcx, callee_id);
|
|
||||||
callee::trans_call_inner(bcx,
|
callee::trans_call_inner(bcx,
|
||||||
Some(expr_info(expr)),
|
Some(expr_info(expr)),
|
||||||
fty,
|
monomorphize_type(bcx, method_ty),
|
||||||
ret_ty,
|
ret_ty,
|
||||||
|bcx, arg_cleanup_scope| {
|
|bcx, arg_cleanup_scope| {
|
||||||
meth::trans_method_callee(bcx,
|
meth::trans_method_callee(bcx,
|
||||||
callee_id,
|
expr.id,
|
||||||
rcvr,
|
rcvr,
|
||||||
origin,
|
|
||||||
arg_cleanup_scope)
|
arg_cleanup_scope)
|
||||||
},
|
},
|
||||||
callee::ArgAutorefSecond(rcvr, arg),
|
callee::ArgAutorefSecond(rcvr, arg),
|
||||||
|
@ -1666,7 +1654,6 @@ fn trans_imm_cast<'a>(bcx: &'a Block<'a>,
|
||||||
fn trans_assign_op<'a>(
|
fn trans_assign_op<'a>(
|
||||||
bcx: &'a Block<'a>,
|
bcx: &'a Block<'a>,
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
_callee_id: ast::NodeId,
|
|
||||||
op: ast::BinOp,
|
op: ast::BinOp,
|
||||||
dst: &ast::Expr,
|
dst: &ast::Expr,
|
||||||
src: @ast::Expr)
|
src: @ast::Expr)
|
||||||
|
|
|
@ -93,21 +93,29 @@ pub fn trans_method(ccx: @CrateContext, method: &ast::Method,
|
||||||
|
|
||||||
pub fn trans_method_callee<'a>(
|
pub fn trans_method_callee<'a>(
|
||||||
bcx: &'a Block<'a>,
|
bcx: &'a Block<'a>,
|
||||||
callee_id: ast::NodeId,
|
expr_id: ast::NodeId,
|
||||||
this: &ast::Expr,
|
this: &ast::Expr,
|
||||||
origin: typeck::method_origin,
|
|
||||||
arg_cleanup_scope: cleanup::ScopeId)
|
arg_cleanup_scope: cleanup::ScopeId)
|
||||||
-> Callee<'a> {
|
-> Callee<'a> {
|
||||||
let _icx = push_ctxt("meth::trans_method_callee");
|
let _icx = push_ctxt("meth::trans_method_callee");
|
||||||
|
|
||||||
debug!("trans_method_callee(callee_id={:?}, origin={})",
|
let (origin, method_ty) = match bcx.ccx().maps.method_map
|
||||||
callee_id, origin.repr(bcx.tcx()));
|
.borrow().get().find(&expr_id) {
|
||||||
|
Some(method) => {
|
||||||
|
debug!("trans_method_callee(expr_id={:?}, method={})",
|
||||||
|
expr_id, method.repr(bcx.tcx()));
|
||||||
|
(method.origin, method.ty)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
bcx.tcx().sess.span_bug(this.span, "method call expr wasn't in method map")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
match origin {
|
match origin {
|
||||||
typeck::MethodStatic(did) => {
|
typeck::MethodStatic(did) => {
|
||||||
Callee {
|
Callee {
|
||||||
bcx: bcx,
|
bcx: bcx,
|
||||||
data: Fn(callee::trans_fn_ref(bcx, did, callee_id))
|
data: Fn(callee::trans_fn_ref(bcx, did, expr_id, true))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
typeck::MethodParam(typeck::MethodParam {
|
typeck::MethodParam(typeck::MethodParam {
|
||||||
|
@ -123,7 +131,7 @@ pub fn trans_method_callee<'a>(
|
||||||
trait_id);
|
trait_id);
|
||||||
|
|
||||||
let vtbl = find_vtable(bcx.tcx(), substs, p, b);
|
let vtbl = find_vtable(bcx.tcx(), substs, p, b);
|
||||||
trans_monomorphized_callee(bcx, callee_id,
|
trans_monomorphized_callee(bcx, expr_id,
|
||||||
trait_id, off, vtbl)
|
trait_id, off, vtbl)
|
||||||
}
|
}
|
||||||
// how to get rid of this?
|
// how to get rid of this?
|
||||||
|
@ -133,7 +141,7 @@ pub fn trans_method_callee<'a>(
|
||||||
|
|
||||||
typeck::MethodObject(ref mt) => {
|
typeck::MethodObject(ref mt) => {
|
||||||
trans_trait_callee(bcx,
|
trans_trait_callee(bcx,
|
||||||
callee_id,
|
monomorphize_type(bcx, method_ty),
|
||||||
mt.real_index,
|
mt.real_index,
|
||||||
this,
|
this,
|
||||||
arg_cleanup_scope)
|
arg_cleanup_scope)
|
||||||
|
@ -144,16 +152,16 @@ pub fn trans_method_callee<'a>(
|
||||||
pub fn trans_static_method_callee(bcx: &Block,
|
pub fn trans_static_method_callee(bcx: &Block,
|
||||||
method_id: ast::DefId,
|
method_id: ast::DefId,
|
||||||
trait_id: ast::DefId,
|
trait_id: ast::DefId,
|
||||||
callee_id: ast::NodeId)
|
expr_id: ast::NodeId)
|
||||||
-> ValueRef {
|
-> ValueRef {
|
||||||
let _icx = push_ctxt("meth::trans_static_method_callee");
|
let _icx = push_ctxt("meth::trans_static_method_callee");
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
|
|
||||||
debug!("trans_static_method_callee(method_id={:?}, trait_id={}, \
|
debug!("trans_static_method_callee(method_id={:?}, trait_id={}, \
|
||||||
callee_id={:?})",
|
expr_id={:?})",
|
||||||
method_id,
|
method_id,
|
||||||
ty::item_path_str(bcx.tcx(), trait_id),
|
ty::item_path_str(bcx.tcx(), trait_id),
|
||||||
callee_id);
|
expr_id);
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
|
|
||||||
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trait_id);
|
ty::populate_implementations_for_trait_if_necessary(bcx.tcx(), trait_id);
|
||||||
|
@ -188,13 +196,10 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||||
} else {
|
} else {
|
||||||
csearch::get_item_path(bcx.tcx(), method_id).last().unwrap().name()
|
csearch::get_item_path(bcx.tcx(), method_id).last().unwrap().name()
|
||||||
};
|
};
|
||||||
debug!("trans_static_method_callee: method_id={:?}, callee_id={:?}, \
|
debug!("trans_static_method_callee: method_id={:?}, expr_id={:?}, \
|
||||||
name={}", method_id, callee_id, token::get_name(mname));
|
name={}", method_id, expr_id, token::get_name(mname));
|
||||||
|
|
||||||
let vtbls = {
|
let vtbls = ccx.maps.vtable_map.borrow().get().get_copy(&expr_id);
|
||||||
let vtable_map = ccx.maps.vtable_map.borrow();
|
|
||||||
vtable_map.get().get_copy(&callee_id)
|
|
||||||
};
|
|
||||||
let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls);
|
let vtbls = resolve_vtables_in_fn_ctxt(bcx.fcx, vtbls);
|
||||||
|
|
||||||
match vtbls[bound_index][0] {
|
match vtbls[bound_index][0] {
|
||||||
|
@ -204,14 +209,14 @@ pub fn trans_static_method_callee(bcx: &Block,
|
||||||
let mth_id = method_with_name(ccx, impl_did, mname);
|
let mth_id = method_with_name(ccx, impl_did, mname);
|
||||||
let (callee_substs, callee_origins) =
|
let (callee_substs, callee_origins) =
|
||||||
combine_impl_and_methods_tps(
|
combine_impl_and_methods_tps(
|
||||||
bcx, mth_id, callee_id,
|
bcx, mth_id, expr_id, false,
|
||||||
*rcvr_substs, rcvr_origins);
|
*rcvr_substs, rcvr_origins);
|
||||||
|
|
||||||
let llfn = trans_fn_ref_with_vtables(bcx, mth_id, callee_id,
|
let llfn = trans_fn_ref_with_vtables(bcx, mth_id, expr_id,
|
||||||
callee_substs,
|
false, callee_substs,
|
||||||
Some(callee_origins));
|
Some(callee_origins));
|
||||||
|
|
||||||
let callee_ty = node_id_type(bcx, callee_id);
|
let callee_ty = node_id_type(bcx, expr_id);
|
||||||
let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
|
let llty = type_of_fn_from_ty(ccx, callee_ty).ptr_to();
|
||||||
PointerCast(bcx, llfn, llty)
|
PointerCast(bcx, llfn, llty)
|
||||||
}
|
}
|
||||||
|
@ -246,13 +251,13 @@ pub fn method_with_name(ccx: &CrateContext,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
|
fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
|
||||||
callee_id: ast::NodeId,
|
expr_id: ast::NodeId,
|
||||||
trait_id: ast::DefId,
|
trait_id: ast::DefId,
|
||||||
n_method: uint,
|
n_method: uint,
|
||||||
vtbl: typeck::vtable_origin)
|
vtbl: typeck::vtable_origin)
|
||||||
-> Callee<'a> {
|
-> Callee<'a> {
|
||||||
let _icx = push_ctxt("meth::trans_monomorphized_callee");
|
let _icx = push_ctxt("meth::trans_monomorphized_callee");
|
||||||
return match vtbl {
|
match vtbl {
|
||||||
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
typeck::vtable_static(impl_did, ref rcvr_substs, rcvr_origins) => {
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
|
let mname = ty::trait_method(ccx.tcx, trait_id, n_method).ident;
|
||||||
|
@ -262,13 +267,14 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
|
||||||
// those from the impl and those from the method:
|
// those from the impl and those from the method:
|
||||||
let (callee_substs, callee_origins) =
|
let (callee_substs, callee_origins) =
|
||||||
combine_impl_and_methods_tps(
|
combine_impl_and_methods_tps(
|
||||||
bcx, mth_id, callee_id,
|
bcx, mth_id, expr_id, true,
|
||||||
*rcvr_substs, rcvr_origins);
|
*rcvr_substs, rcvr_origins);
|
||||||
|
|
||||||
// translate the function
|
// translate the function
|
||||||
let llfn = trans_fn_ref_with_vtables(bcx,
|
let llfn = trans_fn_ref_with_vtables(bcx,
|
||||||
mth_id,
|
mth_id,
|
||||||
callee_id,
|
expr_id,
|
||||||
|
true,
|
||||||
callee_substs,
|
callee_substs,
|
||||||
Some(callee_origins));
|
Some(callee_origins));
|
||||||
|
|
||||||
|
@ -277,16 +283,16 @@ fn trans_monomorphized_callee<'a>(bcx: &'a Block<'a>,
|
||||||
typeck::vtable_param(..) => {
|
typeck::vtable_param(..) => {
|
||||||
fail!("vtable_param left in monomorphized function's vtable substs");
|
fail!("vtable_param left in monomorphized function's vtable substs");
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn combine_impl_and_methods_tps(bcx: &Block,
|
fn combine_impl_and_methods_tps(bcx: &Block,
|
||||||
mth_did: ast::DefId,
|
mth_did: ast::DefId,
|
||||||
callee_id: ast::NodeId,
|
expr_id: ast::NodeId,
|
||||||
rcvr_substs: &[ty::t],
|
is_method: bool,
|
||||||
rcvr_origins: typeck::vtable_res)
|
rcvr_substs: &[ty::t],
|
||||||
-> (~[ty::t], typeck::vtable_res) {
|
rcvr_origins: typeck::vtable_res)
|
||||||
|
-> (~[ty::t], typeck::vtable_res) {
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* Creates a concatenated set of substitutions which includes
|
* Creates a concatenated set of substitutions which includes
|
||||||
|
@ -307,7 +313,7 @@ pub fn combine_impl_and_methods_tps(bcx: &Block,
|
||||||
let ccx = bcx.ccx();
|
let ccx = bcx.ccx();
|
||||||
let method = ty::method(ccx.tcx, mth_did);
|
let method = ty::method(ccx.tcx, mth_did);
|
||||||
let n_m_tps = method.generics.type_param_defs().len();
|
let n_m_tps = method.generics.type_param_defs().len();
|
||||||
let node_substs = node_id_type_params(bcx, callee_id);
|
let node_substs = node_id_type_params(bcx, expr_id, is_method);
|
||||||
debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx));
|
debug!("rcvr_substs={:?}", rcvr_substs.repr(ccx.tcx));
|
||||||
let ty_substs
|
let ty_substs
|
||||||
= vec::append(rcvr_substs.to_owned(),
|
= vec::append(rcvr_substs.to_owned(),
|
||||||
|
@ -319,7 +325,7 @@ pub fn combine_impl_and_methods_tps(bcx: &Block,
|
||||||
|
|
||||||
// Now, do the same work for the vtables. The vtables might not
|
// Now, do the same work for the vtables. The vtables might not
|
||||||
// exist, in which case we need to make them.
|
// exist, in which case we need to make them.
|
||||||
let r_m_origins = match node_vtables(bcx, callee_id) {
|
let r_m_origins = match node_vtables(bcx, expr_id) {
|
||||||
Some(vt) => vt,
|
Some(vt) => vt,
|
||||||
None => @vec::from_elem(node_substs.len(), @~[])
|
None => @vec::from_elem(node_substs.len(), @~[])
|
||||||
};
|
};
|
||||||
|
@ -327,11 +333,11 @@ pub fn combine_impl_and_methods_tps(bcx: &Block,
|
||||||
= @vec::append(rcvr_origins.to_owned(),
|
= @vec::append(rcvr_origins.to_owned(),
|
||||||
r_m_origins.tailn(r_m_origins.len() - n_m_tps));
|
r_m_origins.tailn(r_m_origins.len() - n_m_tps));
|
||||||
|
|
||||||
return (ty_substs, vtables);
|
(ty_substs, vtables)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trans_trait_callee<'a>(bcx: &'a Block<'a>,
|
fn trans_trait_callee<'a>(bcx: &'a Block<'a>,
|
||||||
callee_id: ast::NodeId,
|
method_ty: ty::t,
|
||||||
n_method: uint,
|
n_method: uint,
|
||||||
self_expr: &ast::Expr,
|
self_expr: &ast::Expr,
|
||||||
arg_cleanup_scope: cleanup::ScopeId)
|
arg_cleanup_scope: cleanup::ScopeId)
|
||||||
|
@ -371,8 +377,7 @@ fn trans_trait_callee<'a>(bcx: &'a Block<'a>,
|
||||||
self_datum.val
|
self_datum.val
|
||||||
};
|
};
|
||||||
|
|
||||||
let callee_ty = node_id_type(bcx, callee_id);
|
trans_trait_callee_from_llval(bcx, method_ty, n_method, llval)
|
||||||
trans_trait_callee_from_llval(bcx, callee_ty, n_method, llval)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
|
pub fn trans_trait_callee_from_llval<'a>(bcx: &'a Block<'a>,
|
||||||
|
@ -540,7 +545,7 @@ fn emit_vtable_methods(bcx: &Block,
|
||||||
token::get_ident(ident));
|
token::get_ident(ident));
|
||||||
C_null(Type::nil().ptr_to())
|
C_null(Type::nil().ptr_to())
|
||||||
} else {
|
} else {
|
||||||
trans_fn_ref_with_vtables(bcx, m_id, 0, substs, Some(vtables))
|
trans_fn_ref_with_vtables(bcx, m_id, 0, false, substs, Some(vtables))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,7 @@ pub fn monomorphic_fn(ccx: @CrateContext,
|
||||||
vtables: Option<typeck::vtable_res>,
|
vtables: Option<typeck::vtable_res>,
|
||||||
self_vtables: Option<typeck::vtable_param_res>,
|
self_vtables: Option<typeck::vtable_param_res>,
|
||||||
ref_id: Option<ast::NodeId>)
|
ref_id: Option<ast::NodeId>)
|
||||||
-> (ValueRef, bool)
|
-> (ValueRef, bool) {
|
||||||
{
|
|
||||||
debug!("monomorphic_fn(\
|
debug!("monomorphic_fn(\
|
||||||
fn_id={}, \
|
fn_id={}, \
|
||||||
real_substs={}, \
|
real_substs={}, \
|
||||||
|
@ -280,7 +279,6 @@ pub fn monomorphic_fn(ccx: @CrateContext,
|
||||||
ast_map::NodeStmt(..) |
|
ast_map::NodeStmt(..) |
|
||||||
ast_map::NodeArg(..) |
|
ast_map::NodeArg(..) |
|
||||||
ast_map::NodeBlock(..) |
|
ast_map::NodeBlock(..) |
|
||||||
ast_map::NodeCalleeScope(..) |
|
|
||||||
ast_map::NodeLocal(..) => {
|
ast_map::NodeLocal(..) => {
|
||||||
ccx.tcx.sess.bug(format!("can't monomorphize a {:?}", map_node))
|
ccx.tcx.sess.bug(format!("can't monomorphize a {:?}", map_node))
|
||||||
}
|
}
|
||||||
|
|
|
@ -3372,7 +3372,7 @@ pub fn expr_kind(tcx: ctxt,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprUnary(_, ast::UnDeref, _) |
|
ast::ExprUnary(ast::UnDeref, _) |
|
||||||
ast::ExprField(..) |
|
ast::ExprField(..) |
|
||||||
ast::ExprIndex(..) => {
|
ast::ExprIndex(..) => {
|
||||||
LvalueExpr
|
LvalueExpr
|
||||||
|
|
|
@ -89,6 +89,7 @@ use middle::typeck::check::{structurally_resolved_type};
|
||||||
use middle::typeck::check::vtable;
|
use middle::typeck::check::vtable;
|
||||||
use middle::typeck::check;
|
use middle::typeck::check;
|
||||||
use middle::typeck::infer;
|
use middle::typeck::infer;
|
||||||
|
use middle::typeck::MethodCallee;
|
||||||
use middle::typeck::{MethodOrigin, MethodParam};
|
use middle::typeck::{MethodOrigin, MethodParam};
|
||||||
use middle::typeck::{MethodStatic, MethodObject};
|
use middle::typeck::{MethodStatic, MethodObject};
|
||||||
use middle::typeck::{param_numbered, param_self, param_index};
|
use middle::typeck::{param_numbered, param_self, param_index};
|
||||||
|
@ -101,7 +102,7 @@ use collections::HashSet;
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::vec;
|
use std::vec;
|
||||||
use syntax::ast::{DefId, SelfValue, SelfRegion};
|
use syntax::ast::{DefId, SelfValue, SelfRegion};
|
||||||
use syntax::ast::{SelfUniq, SelfStatic, NodeId};
|
use syntax::ast::{SelfUniq, SelfStatic};
|
||||||
use syntax::ast::{MutMutable, MutImmutable};
|
use syntax::ast::{MutMutable, MutImmutable};
|
||||||
use syntax::ast;
|
use syntax::ast;
|
||||||
use syntax::parse::token;
|
use syntax::parse::token;
|
||||||
|
@ -124,20 +125,17 @@ pub fn lookup(
|
||||||
// In a call `a.b::<X, Y, ...>(...)`:
|
// In a call `a.b::<X, Y, ...>(...)`:
|
||||||
expr: &ast::Expr, // The expression `a.b(...)`.
|
expr: &ast::Expr, // The expression `a.b(...)`.
|
||||||
self_expr: &ast::Expr, // The expression `a`.
|
self_expr: &ast::Expr, // The expression `a`.
|
||||||
callee_id: NodeId, /* Where to store `a.b`'s type,
|
|
||||||
* also the scope of the call */
|
|
||||||
m_name: ast::Name, // The name `b`.
|
m_name: ast::Name, // The name `b`.
|
||||||
self_ty: ty::t, // The type of `a`.
|
self_ty: ty::t, // The type of `a`.
|
||||||
supplied_tps: &[ty::t], // The list of types X, Y, ... .
|
supplied_tps: &[ty::t], // The list of types X, Y, ... .
|
||||||
deref_args: check::DerefArgs, // Whether we autopointer first.
|
deref_args: check::DerefArgs, // Whether we autopointer first.
|
||||||
check_traits: CheckTraitsFlag, // Whether we check traits only.
|
check_traits: CheckTraitsFlag, // Whether we check traits only.
|
||||||
autoderef_receiver: AutoderefReceiverFlag)
|
autoderef_receiver: AutoderefReceiverFlag)
|
||||||
-> Option<method_origin> {
|
-> Option<MethodCallee> {
|
||||||
let lcx = LookupContext {
|
let lcx = LookupContext {
|
||||||
fcx: fcx,
|
fcx: fcx,
|
||||||
expr: expr,
|
expr: expr,
|
||||||
self_expr: self_expr,
|
self_expr: self_expr,
|
||||||
callee_id: callee_id,
|
|
||||||
m_name: m_name,
|
m_name: m_name,
|
||||||
supplied_tps: supplied_tps,
|
supplied_tps: supplied_tps,
|
||||||
impl_dups: @RefCell::new(HashSet::new()),
|
impl_dups: @RefCell::new(HashSet::new()),
|
||||||
|
@ -173,19 +171,16 @@ pub fn lookup_in_trait(
|
||||||
// In a call `a.b::<X, Y, ...>(...)`:
|
// In a call `a.b::<X, Y, ...>(...)`:
|
||||||
expr: &ast::Expr, // The expression `a.b(...)`.
|
expr: &ast::Expr, // The expression `a.b(...)`.
|
||||||
self_expr: &ast::Expr, // The expression `a`.
|
self_expr: &ast::Expr, // The expression `a`.
|
||||||
callee_id: NodeId, /* Where to store `a.b`'s type,
|
|
||||||
* also the scope of the call */
|
|
||||||
m_name: ast::Name, // The name `b`.
|
m_name: ast::Name, // The name `b`.
|
||||||
trait_did: DefId, // The trait to limit the lookup to.
|
trait_did: DefId, // The trait to limit the lookup to.
|
||||||
self_ty: ty::t, // The type of `a`.
|
self_ty: ty::t, // The type of `a`.
|
||||||
supplied_tps: &[ty::t], // The list of types X, Y, ... .
|
supplied_tps: &[ty::t], // The list of types X, Y, ... .
|
||||||
autoderef_receiver: AutoderefReceiverFlag)
|
autoderef_receiver: AutoderefReceiverFlag)
|
||||||
-> Option<method_origin> {
|
-> Option<MethodCallee> {
|
||||||
let lcx = LookupContext {
|
let lcx = LookupContext {
|
||||||
fcx: fcx,
|
fcx: fcx,
|
||||||
expr: expr,
|
expr: expr,
|
||||||
self_expr: self_expr,
|
self_expr: self_expr,
|
||||||
callee_id: callee_id,
|
|
||||||
m_name: m_name,
|
m_name: m_name,
|
||||||
supplied_tps: supplied_tps,
|
supplied_tps: supplied_tps,
|
||||||
impl_dups: @RefCell::new(HashSet::new()),
|
impl_dups: @RefCell::new(HashSet::new()),
|
||||||
|
@ -210,7 +205,6 @@ pub struct LookupContext<'a> {
|
||||||
fcx: @FnCtxt,
|
fcx: @FnCtxt,
|
||||||
expr: &'a ast::Expr,
|
expr: &'a ast::Expr,
|
||||||
self_expr: &'a ast::Expr,
|
self_expr: &'a ast::Expr,
|
||||||
callee_id: NodeId,
|
|
||||||
m_name: ast::Name,
|
m_name: ast::Name,
|
||||||
supplied_tps: &'a [ty::t],
|
supplied_tps: &'a [ty::t],
|
||||||
impl_dups: @RefCell<HashSet<DefId>>,
|
impl_dups: @RefCell<HashSet<DefId>>,
|
||||||
|
@ -248,7 +242,7 @@ enum RcvrMatchCondition {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LookupContext<'a> {
|
impl<'a> LookupContext<'a> {
|
||||||
fn search(&self, self_ty: ty::t) -> Option<method_origin> {
|
fn search(&self, self_ty: ty::t) -> Option<MethodCallee> {
|
||||||
let mut self_ty = self_ty;
|
let mut self_ty = self_ty;
|
||||||
let mut autoderefs = 0;
|
let mut autoderefs = 0;
|
||||||
loop {
|
loop {
|
||||||
|
@ -636,7 +630,7 @@ impl<'a> LookupContext<'a> {
|
||||||
fn search_for_autoderefd_method(&self,
|
fn search_for_autoderefd_method(&self,
|
||||||
self_ty: ty::t,
|
self_ty: ty::t,
|
||||||
autoderefs: uint)
|
autoderefs: uint)
|
||||||
-> Option<method_origin> {
|
-> Option<MethodCallee> {
|
||||||
let (self_ty, autoadjust) =
|
let (self_ty, autoadjust) =
|
||||||
self.consider_reborrow(self_ty, autoderefs);
|
self.consider_reborrow(self_ty, autoderefs);
|
||||||
match self.search_for_method(self_ty) {
|
match self.search_for_method(self_ty) {
|
||||||
|
@ -732,7 +726,7 @@ impl<'a> LookupContext<'a> {
|
||||||
fn search_for_autosliced_method(&self,
|
fn search_for_autosliced_method(&self,
|
||||||
self_ty: ty::t,
|
self_ty: ty::t,
|
||||||
autoderefs: uint)
|
autoderefs: uint)
|
||||||
-> Option<method_origin> {
|
-> Option<MethodCallee> {
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* Searches for a candidate by converting things like
|
* Searches for a candidate by converting things like
|
||||||
|
@ -807,7 +801,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
|
fn search_for_autoptrd_method(&self, self_ty: ty::t, autoderefs: uint)
|
||||||
-> Option<method_origin> {
|
-> Option<MethodCallee> {
|
||||||
/*!
|
/*!
|
||||||
*
|
*
|
||||||
* Converts any type `T` to `&M T` where `M` is an
|
* Converts any type `T` to `&M T` where `M` is an
|
||||||
|
@ -843,7 +837,7 @@ impl<'a> LookupContext<'a> {
|
||||||
autoderefs: uint,
|
autoderefs: uint,
|
||||||
mutbls: &[ast::Mutability],
|
mutbls: &[ast::Mutability],
|
||||||
mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
|
mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
|
||||||
-> Option<method_origin> {
|
-> Option<MethodCallee> {
|
||||||
// This is hokey. We should have mutability inference as a
|
// This is hokey. We should have mutability inference as a
|
||||||
// variable. But for now, try &const, then &, then &mut:
|
// variable. But for now, try &const, then &, then &mut:
|
||||||
let region =
|
let region =
|
||||||
|
@ -867,7 +861,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn search_for_method(&self, rcvr_ty: ty::t)
|
fn search_for_method(&self, rcvr_ty: ty::t)
|
||||||
-> Option<method_origin> {
|
-> Option<MethodCallee> {
|
||||||
debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
|
debug!("search_for_method(rcvr_ty={})", self.ty_to_str(rcvr_ty));
|
||||||
let _indenter = indenter();
|
let _indenter = indenter();
|
||||||
|
|
||||||
|
@ -899,7 +893,7 @@ impl<'a> LookupContext<'a> {
|
||||||
fn consider_candidates(&self,
|
fn consider_candidates(&self,
|
||||||
rcvr_ty: ty::t,
|
rcvr_ty: ty::t,
|
||||||
candidates: &mut ~[Candidate])
|
candidates: &mut ~[Candidate])
|
||||||
-> Option<method_origin> {
|
-> Option<MethodCallee> {
|
||||||
// FIXME(pcwalton): Do we need to clone here?
|
// FIXME(pcwalton): Do we need to clone here?
|
||||||
let relevant_candidates: ~[Candidate] =
|
let relevant_candidates: ~[Candidate] =
|
||||||
candidates.iter().map(|c| (*c).clone()).
|
candidates.iter().map(|c| (*c).clone()).
|
||||||
|
@ -970,7 +964,7 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
fn confirm_candidate(&self, rcvr_ty: ty::t, candidate: &Candidate)
|
||||||
-> method_origin {
|
-> MethodCallee {
|
||||||
// This method performs two sets of substitutions, one after the other:
|
// This method performs two sets of substitutions, one after the other:
|
||||||
// 1. Substitute values for any type/lifetime parameters from the impl and
|
// 1. Substitute values for any type/lifetime parameters from the impl and
|
||||||
// method declaration into the method type. This is the function type
|
// method declaration into the method type. This is the function type
|
||||||
|
@ -1079,9 +1073,11 @@ impl<'a> LookupContext<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
self.fcx.write_ty(self.callee_id, fty);
|
MethodCallee {
|
||||||
self.fcx.write_substs(self.callee_id, all_substs);
|
origin: candidate.origin,
|
||||||
candidate.origin
|
ty: fty,
|
||||||
|
substs: all_substs
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn construct_transformed_self_ty_for_object(
|
fn construct_transformed_self_ty_for_object(
|
||||||
|
|
|
@ -1088,8 +1088,7 @@ impl FnCtxt {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
|
pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
|
||||||
let node_types = self.inh.node_types.borrow();
|
match self.inh.node_types.borrow().get().find(&id) {
|
||||||
match node_types.get().find(&id) {
|
|
||||||
Some(&t) => t,
|
Some(&t) => t,
|
||||||
None => {
|
None => {
|
||||||
self.tcx().sess.bug(
|
self.tcx().sess.bug(
|
||||||
|
@ -1100,9 +1099,20 @@ impl FnCtxt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn method_ty(&self, id: ast::NodeId) -> ty::t {
|
||||||
|
match self.inh.method_map.borrow().get().find(&id) {
|
||||||
|
Some(method) => method.ty,
|
||||||
|
None => {
|
||||||
|
self.tcx().sess.bug(
|
||||||
|
format!("no method entry for node {}: {} in fcx {}",
|
||||||
|
id, self.tcx().map.node_to_str(id),
|
||||||
|
self.tag()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn node_ty_substs(&self, id: ast::NodeId) -> ty::substs {
|
pub fn node_ty_substs(&self, id: ast::NodeId) -> ty::substs {
|
||||||
let mut node_type_substs = self.inh.node_type_substs.borrow_mut();
|
match self.inh.node_type_substs.borrow().get().find(&id) {
|
||||||
match node_type_substs.get().find(&id) {
|
|
||||||
Some(ts) => (*ts).clone(),
|
Some(ts) => (*ts).clone(),
|
||||||
None => {
|
None => {
|
||||||
self.tcx().sess.bug(
|
self.tcx().sess.bug(
|
||||||
|
@ -1113,6 +1123,18 @@ impl FnCtxt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn method_ty_substs(&self, id: ast::NodeId) -> ty::substs {
|
||||||
|
match self.inh.method_map.borrow().get().find(&id) {
|
||||||
|
Some(method) => method.substs.clone(),
|
||||||
|
None => {
|
||||||
|
self.tcx().sess.bug(
|
||||||
|
format!("no method entry for node {}: {} in fcx {}",
|
||||||
|
id, self.tcx().map.node_to_str(id),
|
||||||
|
self.tag()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn opt_node_ty_substs(&self,
|
pub fn opt_node_ty_substs(&self,
|
||||||
id: ast::NodeId,
|
id: ast::NodeId,
|
||||||
f: |&ty::substs| -> bool)
|
f: |&ty::substs| -> bool)
|
||||||
|
@ -1776,7 +1798,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
|
|
||||||
// A generic function for doing all of the checking for call expressions
|
// A generic function for doing all of the checking for call expressions
|
||||||
fn check_call(fcx: @FnCtxt,
|
fn check_call(fcx: @FnCtxt,
|
||||||
callee_id: ast::NodeId,
|
|
||||||
call_expr: &ast::Expr,
|
call_expr: &ast::Expr,
|
||||||
f: &ast::Expr,
|
f: &ast::Expr,
|
||||||
args: &[@ast::Expr]) {
|
args: &[@ast::Expr]) {
|
||||||
|
@ -1787,13 +1808,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
// Store the type of `f` as the type of the callee
|
// Store the type of `f` as the type of the callee
|
||||||
let fn_ty = fcx.expr_ty(f);
|
let fn_ty = fcx.expr_ty(f);
|
||||||
|
|
||||||
// FIXME(#6273) should write callee type AFTER regions have
|
|
||||||
// been subst'd. However, it is awkward to deal with this
|
|
||||||
// now. Best thing would I think be to just have a separate
|
|
||||||
// "callee table" that contains the FnSig and not a general
|
|
||||||
// purpose ty::t
|
|
||||||
fcx.write_ty(callee_id, fn_ty);
|
|
||||||
|
|
||||||
// Extract the function signature from `in_fty`.
|
// Extract the function signature from `in_fty`.
|
||||||
let fn_sty = structure_of(fcx, f.span, fn_ty);
|
let fn_sty = structure_of(fcx, f.span, fn_ty);
|
||||||
|
|
||||||
|
@ -1834,7 +1848,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
|
|
||||||
// Checks a method call.
|
// Checks a method call.
|
||||||
fn check_method_call(fcx: @FnCtxt,
|
fn check_method_call(fcx: @FnCtxt,
|
||||||
callee_id: ast::NodeId,
|
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
method_name: ast::Ident,
|
method_name: ast::Ident,
|
||||||
args: &[@ast::Expr],
|
args: &[@ast::Expr],
|
||||||
|
@ -1848,20 +1861,16 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
fcx.expr_ty(rcvr));
|
fcx.expr_ty(rcvr));
|
||||||
|
|
||||||
let tps = tps.map(|&ast_ty| fcx.to_ty(ast_ty));
|
let tps = tps.map(|&ast_ty| fcx.to_ty(ast_ty));
|
||||||
match method::lookup(fcx,
|
let fn_ty = match method::lookup(fcx, expr, rcvr,
|
||||||
expr,
|
method_name.name,
|
||||||
rcvr,
|
expr_t, tps,
|
||||||
callee_id,
|
DontDerefArgs,
|
||||||
method_name.name,
|
CheckTraitsAndInherentMethods,
|
||||||
expr_t,
|
AutoderefReceiver) {
|
||||||
tps,
|
Some(method) => {
|
||||||
DontDerefArgs,
|
let method_ty = method.ty;
|
||||||
CheckTraitsAndInherentMethods,
|
fcx.inh.method_map.borrow_mut().get().insert(expr.id, method);
|
||||||
AutoderefReceiver) {
|
method_ty
|
||||||
Some(ref entry) => {
|
|
||||||
let method_map = fcx.inh.method_map;
|
|
||||||
let mut method_map = method_map.borrow_mut();
|
|
||||||
method_map.get().insert(expr.id, (*entry));
|
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
debug!("(checking method call) failing expr is {}", expr.id);
|
debug!("(checking method call) failing expr is {}", expr.id);
|
||||||
|
@ -1877,12 +1886,11 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
|
|
||||||
// Add error type for the result
|
// Add error type for the result
|
||||||
fcx.write_error(expr.id);
|
fcx.write_error(expr.id);
|
||||||
fcx.write_error(callee_id);
|
ty::mk_err()
|
||||||
}
|
}
|
||||||
}
|
};
|
||||||
|
|
||||||
// Call the generic checker.
|
// Call the generic checker.
|
||||||
let fn_ty = fcx.node_ty(callee_id);
|
|
||||||
let ret_ty = check_method_argument_types(fcx, expr.span,
|
let ret_ty = check_method_argument_types(fcx, expr.span,
|
||||||
fn_ty, expr, args,
|
fn_ty, expr, args,
|
||||||
DontDerefArgs);
|
DontDerefArgs);
|
||||||
|
@ -1932,7 +1940,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn lookup_op_method(fcx: @FnCtxt,
|
fn lookup_op_method(fcx: @FnCtxt,
|
||||||
callee_id: ast::NodeId,
|
|
||||||
op_ex: &ast::Expr,
|
op_ex: &ast::Expr,
|
||||||
self_t: ty::t,
|
self_t: ty::t,
|
||||||
opname: ast::Name,
|
opname: ast::Name,
|
||||||
|
@ -1940,18 +1947,17 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
args: &[@ast::Expr],
|
args: &[@ast::Expr],
|
||||||
autoderef_receiver: AutoderefReceiverFlag,
|
autoderef_receiver: AutoderefReceiverFlag,
|
||||||
unbound_method: ||) -> ty::t {
|
unbound_method: ||) -> ty::t {
|
||||||
let origin = match trait_did {
|
let method = match trait_did {
|
||||||
Some(trait_did) => {
|
Some(trait_did) => {
|
||||||
method::lookup_in_trait(fcx, op_ex, args[0], callee_id, opname,
|
method::lookup_in_trait(fcx, op_ex, args[0], opname, trait_did,
|
||||||
trait_did, self_t, [], autoderef_receiver)
|
self_t, [], autoderef_receiver)
|
||||||
}
|
}
|
||||||
None => None
|
None => None
|
||||||
};
|
};
|
||||||
match origin {
|
match method {
|
||||||
Some(origin) => {
|
Some(method) => {
|
||||||
let method_ty = fcx.node_ty(callee_id);
|
let method_ty = method.ty;
|
||||||
let method_map = fcx.inh.method_map;
|
fcx.inh.method_map.borrow_mut().get().insert(op_ex.id, method);
|
||||||
method_map.borrow_mut().get().insert(op_ex.id, origin);
|
|
||||||
check_method_argument_types(fcx, op_ex.span,
|
check_method_argument_types(fcx, op_ex.span,
|
||||||
method_ty, op_ex,
|
method_ty, op_ex,
|
||||||
args, DoDerefArgs)
|
args, DoDerefArgs)
|
||||||
|
@ -1971,7 +1977,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
|
|
||||||
// could be either an expr_binop or an expr_assign_binop
|
// could be either an expr_binop or an expr_assign_binop
|
||||||
fn check_binop(fcx: @FnCtxt,
|
fn check_binop(fcx: @FnCtxt,
|
||||||
callee_id: ast::NodeId,
|
|
||||||
expr: &ast::Expr,
|
expr: &ast::Expr,
|
||||||
op: ast::BinOp,
|
op: ast::BinOp,
|
||||||
lhs: @ast::Expr,
|
lhs: @ast::Expr,
|
||||||
|
@ -2023,7 +2028,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
|
|
||||||
// Check for overloaded operators if not an assignment.
|
// Check for overloaded operators if not an assignment.
|
||||||
let result_t = if is_binop_assignment == SimpleBinop {
|
let result_t = if is_binop_assignment == SimpleBinop {
|
||||||
check_user_binop(fcx, callee_id, expr, lhs, lhs_t, op, rhs)
|
check_user_binop(fcx, expr, lhs, lhs_t, op, rhs)
|
||||||
} else {
|
} else {
|
||||||
fcx.type_error_message(expr.span,
|
fcx.type_error_message(expr.span,
|
||||||
|actual| {
|
|actual| {
|
||||||
|
@ -2045,7 +2050,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_user_binop(fcx: @FnCtxt,
|
fn check_user_binop(fcx: @FnCtxt,
|
||||||
callee_id: ast::NodeId,
|
|
||||||
ex: &ast::Expr,
|
ex: &ast::Expr,
|
||||||
lhs_expr: @ast::Expr,
|
lhs_expr: @ast::Expr,
|
||||||
lhs_resolved_t: ty::t,
|
lhs_resolved_t: ty::t,
|
||||||
|
@ -2075,7 +2079,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
return ty::mk_err();
|
return ty::mk_err();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
lookup_op_method(fcx, callee_id, ex, lhs_resolved_t, token::intern(name),
|
lookup_op_method(fcx, ex, lhs_resolved_t, token::intern(name),
|
||||||
trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
|
trait_did, [lhs_expr, rhs], DontAutoderefReceiver, || {
|
||||||
fcx.type_error_message(ex.span, |actual| {
|
fcx.type_error_message(ex.span, |actual| {
|
||||||
format!("binary operation `{}` cannot be applied to type `{}`",
|
format!("binary operation `{}` cannot be applied to type `{}`",
|
||||||
|
@ -2085,14 +2089,13 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_user_unop(fcx: @FnCtxt,
|
fn check_user_unop(fcx: @FnCtxt,
|
||||||
callee_id: ast::NodeId,
|
|
||||||
op_str: &str,
|
op_str: &str,
|
||||||
mname: &str,
|
mname: &str,
|
||||||
trait_did: Option<ast::DefId>,
|
trait_did: Option<ast::DefId>,
|
||||||
ex: &ast::Expr,
|
ex: &ast::Expr,
|
||||||
rhs_expr: @ast::Expr,
|
rhs_expr: @ast::Expr,
|
||||||
rhs_t: ty::t) -> ty::t {
|
rhs_t: ty::t) -> ty::t {
|
||||||
lookup_op_method(fcx, callee_id, ex, rhs_t, token::intern(mname),
|
lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
|
||||||
trait_did, [rhs_expr], DontAutoderefReceiver, || {
|
trait_did, [rhs_expr], DontAutoderefReceiver, || {
|
||||||
fcx.type_error_message(ex.span, |actual| {
|
fcx.type_error_message(ex.span, |actual| {
|
||||||
format!("cannot apply unary operator `{}` to type `{}`", op_str, actual)
|
format!("cannot apply unary operator `{}` to type `{}`", op_str, actual)
|
||||||
|
@ -2264,7 +2267,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
match method::lookup(fcx,
|
match method::lookup(fcx,
|
||||||
expr,
|
expr,
|
||||||
base,
|
base,
|
||||||
expr.id,
|
|
||||||
field,
|
field,
|
||||||
expr_t,
|
expr_t,
|
||||||
tps,
|
tps,
|
||||||
|
@ -2620,8 +2622,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
let typ = check_lit(fcx, lit);
|
let typ = check_lit(fcx, lit);
|
||||||
fcx.write_ty(id, typ);
|
fcx.write_ty(id, typ);
|
||||||
}
|
}
|
||||||
ast::ExprBinary(callee_id, op, lhs, rhs) => {
|
ast::ExprBinary(op, lhs, rhs) => {
|
||||||
check_binop(fcx, callee_id, expr, op, lhs, rhs, SimpleBinop);
|
check_binop(fcx, expr, op, lhs, rhs, SimpleBinop);
|
||||||
|
|
||||||
let lhs_ty = fcx.expr_ty(lhs);
|
let lhs_ty = fcx.expr_ty(lhs);
|
||||||
let rhs_ty = fcx.expr_ty(rhs);
|
let rhs_ty = fcx.expr_ty(rhs);
|
||||||
|
@ -2634,8 +2636,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
fcx.write_bot(id);
|
fcx.write_bot(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprAssignOp(callee_id, op, lhs, rhs) => {
|
ast::ExprAssignOp(op, lhs, rhs) => {
|
||||||
check_binop(fcx, callee_id, expr, op, lhs, rhs, BinopAssignment);
|
check_binop(fcx, expr, op, lhs, rhs, BinopAssignment);
|
||||||
|
|
||||||
let lhs_t = fcx.expr_ty(lhs);
|
let lhs_t = fcx.expr_ty(lhs);
|
||||||
let result_t = fcx.expr_ty(expr);
|
let result_t = fcx.expr_ty(expr);
|
||||||
|
@ -2654,7 +2656,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
fcx.write_nil(expr.id);
|
fcx.write_nil(expr.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprUnary(callee_id, unop, oprnd) => {
|
ast::ExprUnary(unop, oprnd) => {
|
||||||
let exp_inner = unpack_expected(fcx, expected, |sty| {
|
let exp_inner = unpack_expected(fcx, expected, |sty| {
|
||||||
match unop {
|
match unop {
|
||||||
ast::UnBox | ast::UnUniq => match *sty {
|
ast::UnBox | ast::UnUniq => match *sty {
|
||||||
|
@ -2710,7 +2712,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
oprnd_t);
|
oprnd_t);
|
||||||
if !(ty::type_is_integral(oprnd_t) ||
|
if !(ty::type_is_integral(oprnd_t) ||
|
||||||
ty::get(oprnd_t).sty == ty::ty_bool) {
|
ty::get(oprnd_t).sty == ty::ty_bool) {
|
||||||
oprnd_t = check_user_unop(fcx, callee_id, "!", "not",
|
oprnd_t = check_user_unop(fcx, "!", "not",
|
||||||
tcx.lang_items.not_trait(),
|
tcx.lang_items.not_trait(),
|
||||||
expr, oprnd, oprnd_t);
|
expr, oprnd, oprnd_t);
|
||||||
}
|
}
|
||||||
|
@ -2720,7 +2722,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
oprnd_t);
|
oprnd_t);
|
||||||
if !(ty::type_is_integral(oprnd_t) ||
|
if !(ty::type_is_integral(oprnd_t) ||
|
||||||
ty::type_is_fp(oprnd_t)) {
|
ty::type_is_fp(oprnd_t)) {
|
||||||
oprnd_t = check_user_unop(fcx, callee_id, "-", "neg",
|
oprnd_t = check_user_unop(fcx, "-", "neg",
|
||||||
tcx.lang_items.neg_trait(),
|
tcx.lang_items.neg_trait(),
|
||||||
expr, oprnd, oprnd_t);
|
expr, oprnd, oprnd_t);
|
||||||
}
|
}
|
||||||
|
@ -2883,7 +2885,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
fcx.write_ty(id, fcx.node_ty(b.id));
|
fcx.write_ty(id, fcx.node_ty(b.id));
|
||||||
}
|
}
|
||||||
ast::ExprCall(f, ref args) => {
|
ast::ExprCall(f, ref args) => {
|
||||||
check_call(fcx, expr.id, expr, f, *args);
|
check_call(fcx, expr, f, *args);
|
||||||
let f_ty = fcx.expr_ty(f);
|
let f_ty = fcx.expr_ty(f);
|
||||||
let (args_bot, args_err) = args.iter().fold((false, false),
|
let (args_bot, args_err) = args.iter().fold((false, false),
|
||||||
|(rest_bot, rest_err), a| {
|
|(rest_bot, rest_err), a| {
|
||||||
|
@ -2898,8 +2900,8 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
fcx.write_bot(id);
|
fcx.write_bot(id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprMethodCall(callee_id, ident, ref tps, ref args) => {
|
ast::ExprMethodCall(ident, ref tps, ref args) => {
|
||||||
check_method_call(fcx, callee_id, expr, ident, *args, *tps);
|
check_method_call(fcx, expr, ident, *args, *tps);
|
||||||
let arg_tys = args.map(|a| fcx.expr_ty(*a));
|
let arg_tys = args.map(|a| fcx.expr_ty(*a));
|
||||||
let (args_bot, args_err) = arg_tys.iter().fold((false, false),
|
let (args_bot, args_err) = arg_tys.iter().fold((false, false),
|
||||||
|(rest_bot, rest_err), a| {
|
|(rest_bot, rest_err), a| {
|
||||||
|
@ -3100,7 +3102,7 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
ast::ExprField(base, field, ref tys) => {
|
ast::ExprField(base, field, ref tys) => {
|
||||||
check_field(fcx, expr, base, field.name, *tys);
|
check_field(fcx, expr, base, field.name, *tys);
|
||||||
}
|
}
|
||||||
ast::ExprIndex(callee_id, base, idx) => {
|
ast::ExprIndex(base, idx) => {
|
||||||
check_expr(fcx, base);
|
check_expr(fcx, base);
|
||||||
check_expr(fcx, idx);
|
check_expr(fcx, idx);
|
||||||
let raw_base_t = fcx.expr_ty(base);
|
let raw_base_t = fcx.expr_ty(base);
|
||||||
|
@ -3133,7 +3135,6 @@ pub fn check_expr_with_unifier(fcx: @FnCtxt,
|
||||||
None);
|
None);
|
||||||
};
|
};
|
||||||
let ret_ty = lookup_op_method(fcx,
|
let ret_ty = lookup_op_method(fcx,
|
||||||
callee_id,
|
|
||||||
expr,
|
expr,
|
||||||
resolved,
|
resolved,
|
||||||
token::intern("index"),
|
token::intern("index"),
|
||||||
|
|
|
@ -226,6 +226,12 @@ impl Rcx {
|
||||||
self.resolve_type(t)
|
self.resolve_type(t)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Try to resolve the callee type for the given method call.
|
||||||
|
pub fn resolve_method_type(&mut self, id: ast::NodeId) -> ty::t {
|
||||||
|
let t = self.fcx.method_ty(id);
|
||||||
|
self.resolve_type(t)
|
||||||
|
}
|
||||||
|
|
||||||
/// Try to resolve the type for the given node.
|
/// Try to resolve the type for the given node.
|
||||||
pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> ty::t {
|
pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> ty::t {
|
||||||
let ty_unadjusted = self.resolve_node_type(expr.id);
|
let ty_unadjusted = self.resolve_node_type(expr.id);
|
||||||
|
@ -378,10 +384,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
||||||
debug!("regionck::visit_expr(e={}, repeating_scope={:?})",
|
debug!("regionck::visit_expr(e={}, repeating_scope={:?})",
|
||||||
expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
|
expr.repr(rcx.fcx.tcx()), rcx.repeating_scope);
|
||||||
|
|
||||||
let has_method_map = {
|
let has_method_map = rcx.fcx.inh.method_map.get().contains_key(&expr.id);
|
||||||
let method_map = rcx.fcx.inh.method_map;
|
|
||||||
method_map.get().contains_key(&expr.id)
|
|
||||||
};
|
|
||||||
|
|
||||||
// Check any autoderefs or autorefs that appear.
|
// Check any autoderefs or autorefs that appear.
|
||||||
{
|
{
|
||||||
|
@ -434,13 +437,13 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::ExprCall(callee, ref args) => {
|
ast::ExprCall(callee, ref args) => {
|
||||||
constrain_callee(rcx, callee.id, expr, callee);
|
constrain_callee(rcx, callee.id, expr, callee);
|
||||||
constrain_call(rcx, callee.id, expr, None, *args, false);
|
constrain_call(rcx, Some(callee.id), expr, None, *args, false);
|
||||||
|
|
||||||
visit::walk_expr(rcx, expr, ());
|
visit::walk_expr(rcx, expr, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprMethodCall(callee_id, _, _, ref args) => {
|
ast::ExprMethodCall(_, _, ref args) => {
|
||||||
constrain_call(rcx, callee_id, expr, Some(args[0]),
|
constrain_call(rcx, None, expr, Some(args[0]),
|
||||||
args.slice_from(1), false);
|
args.slice_from(1), false);
|
||||||
|
|
||||||
visit::walk_expr(rcx, expr, ());
|
visit::walk_expr(rcx, expr, ());
|
||||||
|
@ -451,9 +454,9 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
||||||
visit::walk_expr(rcx, expr, ());
|
visit::walk_expr(rcx, expr, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprAssignOp(callee_id, _, lhs, rhs) => {
|
ast::ExprAssignOp(_, lhs, rhs) => {
|
||||||
if has_method_map {
|
if has_method_map {
|
||||||
constrain_call(rcx, callee_id, expr, Some(lhs), [rhs], true);
|
constrain_call(rcx, None, expr, Some(lhs), [rhs], true);
|
||||||
}
|
}
|
||||||
|
|
||||||
adjust_borrow_kind_for_assignment_lhs(rcx, lhs);
|
adjust_borrow_kind_for_assignment_lhs(rcx, lhs);
|
||||||
|
@ -461,25 +464,25 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
||||||
visit::walk_expr(rcx, expr, ());
|
visit::walk_expr(rcx, expr, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(callee_id, lhs, rhs) |
|
ast::ExprIndex(lhs, rhs) |
|
||||||
ast::ExprBinary(callee_id, _, lhs, rhs) if has_method_map => {
|
ast::ExprBinary(_, lhs, rhs) if has_method_map => {
|
||||||
// As `expr_method_call`, but the call is via an
|
// As `expr_method_call`, but the call is via an
|
||||||
// overloaded op. Note that we (sadly) currently use an
|
// overloaded op. Note that we (sadly) currently use an
|
||||||
// implicit "by ref" sort of passing style here. This
|
// implicit "by ref" sort of passing style here. This
|
||||||
// should be converted to an adjustment!
|
// should be converted to an adjustment!
|
||||||
constrain_call(rcx, callee_id, expr, Some(lhs), [rhs], true);
|
constrain_call(rcx, None, expr, Some(lhs), [rhs], true);
|
||||||
|
|
||||||
visit::walk_expr(rcx, expr, ());
|
visit::walk_expr(rcx, expr, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprUnary(callee_id, _, lhs) if has_method_map => {
|
ast::ExprUnary(_, lhs) if has_method_map => {
|
||||||
// As above.
|
// As above.
|
||||||
constrain_call(rcx, callee_id, expr, Some(lhs), [], true);
|
constrain_call(rcx, None, expr, Some(lhs), [], true);
|
||||||
|
|
||||||
visit::walk_expr(rcx, expr, ());
|
visit::walk_expr(rcx, expr, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprUnary(_, ast::UnDeref, base) => {
|
ast::ExprUnary(ast::UnDeref, base) => {
|
||||||
// For *a, the lifetime of a must enclose the deref
|
// For *a, the lifetime of a must enclose the deref
|
||||||
let base_ty = rcx.resolve_node_type(base.id);
|
let base_ty = rcx.resolve_node_type(base.id);
|
||||||
constrain_derefs(rcx, expr, 1, base_ty);
|
constrain_derefs(rcx, expr, 1, base_ty);
|
||||||
|
@ -487,7 +490,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
|
||||||
visit::walk_expr(rcx, expr, ());
|
visit::walk_expr(rcx, expr, ());
|
||||||
}
|
}
|
||||||
|
|
||||||
ast::ExprIndex(_, vec_expr, _) => {
|
ast::ExprIndex(vec_expr, _) => {
|
||||||
// For a[b], the lifetime of a must enclose the deref
|
// For a[b], the lifetime of a must enclose the deref
|
||||||
let vec_type = rcx.resolve_expr_type_adjusted(vec_expr);
|
let vec_type = rcx.resolve_expr_type_adjusted(vec_expr);
|
||||||
constrain_index(rcx, expr, vec_type);
|
constrain_index(rcx, expr, vec_type);
|
||||||
|
@ -711,8 +714,7 @@ fn check_expr_fn_block(rcx: &mut Rcx,
|
||||||
fn constrain_callee(rcx: &mut Rcx,
|
fn constrain_callee(rcx: &mut Rcx,
|
||||||
callee_id: ast::NodeId,
|
callee_id: ast::NodeId,
|
||||||
call_expr: &ast::Expr,
|
call_expr: &ast::Expr,
|
||||||
callee_expr: &ast::Expr)
|
callee_expr: &ast::Expr) {
|
||||||
{
|
|
||||||
let call_region = ty::ReScope(call_expr.id);
|
let call_region = ty::ReScope(call_expr.id);
|
||||||
|
|
||||||
let callee_ty = rcx.resolve_node_type(callee_id);
|
let callee_ty = rcx.resolve_node_type(callee_id);
|
||||||
|
@ -736,12 +738,11 @@ fn constrain_callee(rcx: &mut Rcx,
|
||||||
fn constrain_call(rcx: &mut Rcx,
|
fn constrain_call(rcx: &mut Rcx,
|
||||||
// might be expr_call, expr_method_call, or an overloaded
|
// might be expr_call, expr_method_call, or an overloaded
|
||||||
// operator
|
// operator
|
||||||
callee_id: ast::NodeId,
|
fn_expr_id: Option<ast::NodeId>,
|
||||||
call_expr: &ast::Expr,
|
call_expr: &ast::Expr,
|
||||||
receiver: Option<@ast::Expr>,
|
receiver: Option<@ast::Expr>,
|
||||||
arg_exprs: &[@ast::Expr],
|
arg_exprs: &[@ast::Expr],
|
||||||
implicitly_ref_args: bool)
|
implicitly_ref_args: bool) {
|
||||||
{
|
|
||||||
//! Invoked on every call site (i.e., normal calls, method calls,
|
//! Invoked on every call site (i.e., normal calls, method calls,
|
||||||
//! and overloaded operators). Constrains the regions which appear
|
//! and overloaded operators). Constrains the regions which appear
|
||||||
//! in the type of the function. Also constrains the regions that
|
//! in the type of the function. Also constrains the regions that
|
||||||
|
@ -756,7 +757,10 @@ fn constrain_call(rcx: &mut Rcx,
|
||||||
receiver.repr(tcx),
|
receiver.repr(tcx),
|
||||||
arg_exprs.repr(tcx),
|
arg_exprs.repr(tcx),
|
||||||
implicitly_ref_args);
|
implicitly_ref_args);
|
||||||
let callee_ty = rcx.resolve_node_type(callee_id);
|
let callee_ty = match fn_expr_id {
|
||||||
|
Some(id) => rcx.resolve_node_type(id),
|
||||||
|
None => rcx.resolve_method_type(call_expr.id)
|
||||||
|
};
|
||||||
if ty::type_is_error(callee_ty) {
|
if ty::type_is_error(callee_ty) {
|
||||||
// Bail, as function type is unknown
|
// Bail, as function type is unknown
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -537,11 +537,10 @@ fn connect_trait_tps(vcx: &VtableContext,
|
||||||
relate_trait_refs(vcx, location_info, impl_trait_ref, trait_ref);
|
relate_trait_refs(vcx, location_info, impl_trait_ref, trait_ref);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn insert_vtables(fcx: &FnCtxt, callee_id: ast::NodeId, vtables: vtable_res) {
|
fn insert_vtables(fcx: &FnCtxt, expr_id: ast::NodeId, vtables: vtable_res) {
|
||||||
debug!("insert_vtables(callee_id={}, vtables={:?})",
|
debug!("insert_vtables(expr_id={}, vtables={:?})",
|
||||||
callee_id, vtables.repr(fcx.tcx()));
|
expr_id, vtables.repr(fcx.tcx()));
|
||||||
let mut vtable_map = fcx.inh.vtable_map.borrow_mut();
|
fcx.inh.vtable_map.borrow_mut().get().insert(expr_id, vtables);
|
||||||
vtable_map.get().insert(callee_id, vtables);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn location_info_for_expr(expr: &ast::Expr) -> LocationInfo {
|
pub fn location_info_for_expr(expr: &ast::Expr) -> LocationInfo {
|
||||||
|
@ -692,23 +691,23 @@ pub fn early_resolve_expr(ex: &ast::Expr, fcx: &FnCtxt, is_early: bool) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Must resolve bounds on methods with bounded params
|
// Must resolve bounds on methods with bounded params
|
||||||
ast::ExprBinary(callee_id, _, _, _) |
|
ast::ExprBinary(_, _, _) |
|
||||||
ast::ExprUnary(callee_id, _, _) |
|
ast::ExprUnary(_, _) |
|
||||||
ast::ExprAssignOp(callee_id, _, _, _) |
|
ast::ExprAssignOp(_, _, _) |
|
||||||
ast::ExprIndex(callee_id, _, _) |
|
ast::ExprIndex(_, _) |
|
||||||
ast::ExprMethodCall(callee_id, _, _, _) => {
|
ast::ExprMethodCall(_, _, _) => {
|
||||||
match fcx.inh.method_map.borrow().get().find(&ex.id) {
|
match fcx.inh.method_map.borrow().get().find(&ex.id) {
|
||||||
Some(origin) => {
|
Some(method) => {
|
||||||
debug!("vtable resolution on parameter bounds for method call {}",
|
debug!("vtable resolution on parameter bounds for method call {}",
|
||||||
ex.repr(fcx.tcx()));
|
ex.repr(fcx.tcx()));
|
||||||
let type_param_defs = ty::method_call_type_param_defs(cx.tcx, *origin);
|
let type_param_defs = ty::method_call_type_param_defs(cx.tcx, method.origin);
|
||||||
if has_trait_bounds(*type_param_defs.borrow()) {
|
if has_trait_bounds(*type_param_defs.borrow()) {
|
||||||
let substs = fcx.node_ty_substs(callee_id);
|
let substs = fcx.method_ty_substs(ex.id);
|
||||||
let vcx = fcx.vtable_context();
|
let vcx = fcx.vtable_context();
|
||||||
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
|
let vtbls = lookup_vtables(&vcx, &location_info_for_expr(ex),
|
||||||
*type_param_defs.borrow(), &substs, is_early);
|
*type_param_defs.borrow(), &substs, is_early);
|
||||||
if !is_early {
|
if !is_early {
|
||||||
insert_vtables(fcx, callee_id, vtbls);
|
insert_vtables(fcx, ex.id, vtbls);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ use middle::typeck::check::FnCtxt;
|
||||||
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
|
use middle::typeck::infer::{force_all, resolve_all, resolve_region};
|
||||||
use middle::typeck::infer::resolve_type;
|
use middle::typeck::infer::resolve_type;
|
||||||
use middle::typeck::infer;
|
use middle::typeck::infer;
|
||||||
|
use middle::typeck::MethodCallee;
|
||||||
use middle::typeck::{vtable_res, vtable_origin};
|
use middle::typeck::{vtable_res, vtable_origin};
|
||||||
use middle::typeck::{vtable_static, vtable_param};
|
use middle::typeck::{vtable_static, vtable_param};
|
||||||
use middle::typeck::write_substs_to_tcx;
|
use middle::typeck::write_substs_to_tcx;
|
||||||
|
@ -61,39 +62,54 @@ fn resolve_type_vars_in_types(fcx: @FnCtxt, sp: Span, tys: &[ty::t])
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_method_map_entry(fcx: @FnCtxt, id: ast::NodeId) {
|
fn resolve_method_map_entry(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId) {
|
||||||
|
let fcx = wbcx.fcx;
|
||||||
|
let tcx = fcx.ccx.tcx;
|
||||||
|
|
||||||
// Resolve any method map entry
|
// Resolve any method map entry
|
||||||
let method_map_entry_opt = {
|
match fcx.inh.method_map.borrow().get().find(&id) {
|
||||||
let method_map = fcx.inh.method_map.borrow();
|
Some(method) => {
|
||||||
method_map.get().find_copy(&id)
|
debug!("writeback::resolve_method_map_entry(id={:?}, entry={:?})",
|
||||||
};
|
id, method.repr(tcx));
|
||||||
match method_map_entry_opt {
|
let method_ty = match resolve_type_vars_in_type(fcx, sp, method.ty) {
|
||||||
None => {}
|
Some(t) => t,
|
||||||
Some(mme) => {
|
None => {
|
||||||
debug!("writeback::resolve_method_map_entry(id={:?}, entry={:?})", id, mme);
|
wbcx.success = false;
|
||||||
let mut method_map = fcx.ccx.method_map.borrow_mut();
|
return;
|
||||||
method_map.get().insert(id, mme);
|
}
|
||||||
|
};
|
||||||
|
let mut new_tps = ~[];
|
||||||
|
for &subst in method.substs.tps.iter() {
|
||||||
|
match resolve_type_vars_in_type(fcx, sp, subst) {
|
||||||
|
Some(t) => new_tps.push(t),
|
||||||
|
None => { wbcx.success = false; return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let new_method = MethodCallee {
|
||||||
|
origin: method.origin,
|
||||||
|
ty: method_ty,
|
||||||
|
substs: ty::substs {
|
||||||
|
tps: new_tps,
|
||||||
|
regions: ty::ErasedRegions,
|
||||||
|
self_ty: None
|
||||||
|
}
|
||||||
|
};
|
||||||
|
fcx.ccx.method_map.borrow_mut().get().insert(id, new_method);
|
||||||
}
|
}
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_vtable_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) {
|
fn resolve_vtable_map_entry(fcx: @FnCtxt, sp: Span, id: ast::NodeId) {
|
||||||
// Resolve any method map entry
|
// Resolve any vtable map entry
|
||||||
{
|
match fcx.inh.vtable_map.borrow().get().find_copy(&id) {
|
||||||
let origins_opt = {
|
Some(origins) => {
|
||||||
let vtable_map = fcx.inh.vtable_map.borrow();
|
let r_origins = resolve_origins(fcx, sp, origins);
|
||||||
vtable_map.get().find_copy(&id)
|
fcx.ccx.vtable_map.borrow_mut().get().insert(id, r_origins);
|
||||||
};
|
debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})",
|
||||||
match origins_opt {
|
id, r_origins.repr(fcx.tcx()));
|
||||||
None => {}
|
|
||||||
Some(origins) => {
|
|
||||||
let r_origins = resolve_origins(fcx, sp, origins);
|
|
||||||
let mut vtable_map = fcx.ccx.vtable_map.borrow_mut();
|
|
||||||
vtable_map.get().insert(id, r_origins);
|
|
||||||
debug!("writeback::resolve_vtable_map_entry(id={}, vtables={:?})",
|
|
||||||
id, r_origins.repr(fcx.tcx()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
None => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn resolve_origins(fcx: @FnCtxt, sp: Span,
|
fn resolve_origins(fcx: @FnCtxt, sp: Span,
|
||||||
|
@ -241,21 +257,6 @@ fn resolve_type_vars_for_node(wbcx: &mut WbCtxt, sp: Span, id: ast::NodeId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn maybe_resolve_type_vars_for_node(wbcx: &mut WbCtxt,
|
|
||||||
sp: Span,
|
|
||||||
id: ast::NodeId)
|
|
||||||
-> Option<ty::t> {
|
|
||||||
let contained = {
|
|
||||||
let node_types = wbcx.fcx.inh.node_types.borrow();
|
|
||||||
node_types.get().contains_key(&id)
|
|
||||||
};
|
|
||||||
if contained {
|
|
||||||
resolve_type_vars_for_node(wbcx, sp, id)
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct WbCtxt {
|
struct WbCtxt {
|
||||||
fcx: @FnCtxt,
|
fcx: @FnCtxt,
|
||||||
|
|
||||||
|
@ -276,22 +277,8 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
|
||||||
}
|
}
|
||||||
|
|
||||||
resolve_type_vars_for_node(wbcx, e.span, e.id);
|
resolve_type_vars_for_node(wbcx, e.span, e.id);
|
||||||
|
resolve_method_map_entry(wbcx, e.span, e.id);
|
||||||
resolve_method_map_entry(wbcx.fcx, e.id);
|
|
||||||
{
|
|
||||||
let r = e.get_callee_id();
|
|
||||||
for callee_id in r.iter() {
|
|
||||||
resolve_method_map_entry(wbcx.fcx, *callee_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
|
resolve_vtable_map_entry(wbcx.fcx, e.span, e.id);
|
||||||
{
|
|
||||||
let r = e.get_callee_id();
|
|
||||||
for callee_id in r.iter() {
|
|
||||||
resolve_vtable_map_entry(wbcx.fcx, e.span, *callee_id);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
match e.node {
|
match e.node {
|
||||||
ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => {
|
ast::ExprFnBlock(ref decl, _) | ast::ExprProc(ref decl, _) => {
|
||||||
|
@ -299,20 +286,7 @@ fn visit_expr(e: &ast::Expr, wbcx: &mut WbCtxt) {
|
||||||
let _ = resolve_type_vars_for_node(wbcx, e.span, input.id);
|
let _ = resolve_type_vars_for_node(wbcx, e.span, input.id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
_ => {}
|
||||||
ast::ExprBinary(callee_id, _, _, _) |
|
|
||||||
ast::ExprUnary(callee_id, _, _) |
|
|
||||||
ast::ExprAssignOp(callee_id, _, _, _) |
|
|
||||||
ast::ExprIndex(callee_id, _, _) => {
|
|
||||||
maybe_resolve_type_vars_for_node(wbcx, e.span, callee_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
ast::ExprMethodCall(callee_id, _, _, _) => {
|
|
||||||
// We must always have written in a callee ID type for these.
|
|
||||||
resolve_type_vars_for_node(wbcx, e.span, callee_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
visit::walk_expr(wbcx, e, ());
|
visit::walk_expr(wbcx, e, ());
|
||||||
|
|
|
@ -142,9 +142,16 @@ pub struct MethodObject {
|
||||||
real_index: uint,
|
real_index: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[deriving(Clone)]
|
||||||
|
pub struct MethodCallee {
|
||||||
|
origin: MethodOrigin,
|
||||||
|
ty: ty::t,
|
||||||
|
substs: ty::substs
|
||||||
|
}
|
||||||
|
|
||||||
// maps from an expression id that corresponds to a method call to the details
|
// maps from an expression id that corresponds to a method call to the details
|
||||||
// of the method to be invoked
|
// of the method to be invoked
|
||||||
pub type method_map = @RefCell<HashMap<ast::NodeId, method_origin>>;
|
pub type MethodMap = @RefCell<HashMap<ast::NodeId, MethodCallee>>;
|
||||||
|
|
||||||
pub type vtable_param_res = @~[vtable_origin];
|
pub type vtable_param_res = @~[vtable_origin];
|
||||||
// Resolutions for bounds of all parameters, left to right, for a given path.
|
// Resolutions for bounds of all parameters, left to right, for a given path.
|
||||||
|
|
|
@ -74,9 +74,6 @@ pub fn explain_region_and_span(cx: ctxt, region: ty::Region)
|
||||||
Some(ast_map::NodeBlock(ref blk)) => {
|
Some(ast_map::NodeBlock(ref blk)) => {
|
||||||
explain_span(cx, "block", blk.span)
|
explain_span(cx, "block", blk.span)
|
||||||
}
|
}
|
||||||
Some(ast_map::NodeCalleeScope(expr)) => {
|
|
||||||
explain_span(cx, "callee", expr.span)
|
|
||||||
}
|
|
||||||
Some(ast_map::NodeExpr(expr)) => {
|
Some(ast_map::NodeExpr(expr)) => {
|
||||||
match expr.node {
|
match expr.node {
|
||||||
ast::ExprCall(..) => explain_span(cx, "call", expr.span),
|
ast::ExprCall(..) => explain_span(cx, "call", expr.span),
|
||||||
|
@ -870,6 +867,15 @@ impl Repr for ty::FnSig {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Repr for typeck::MethodCallee {
|
||||||
|
fn repr(&self, tcx: ctxt) -> ~str {
|
||||||
|
format!("MethodCallee \\{origin: {}, ty: {}, {}\\}",
|
||||||
|
self.origin.repr(tcx),
|
||||||
|
self.ty.repr(tcx),
|
||||||
|
self.substs.repr(tcx))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Repr for typeck::MethodOrigin {
|
impl Repr for typeck::MethodOrigin {
|
||||||
fn repr(&self, tcx: ctxt) -> ~str {
|
fn repr(&self, tcx: ctxt) -> ~str {
|
||||||
match self {
|
match self {
|
||||||
|
|
|
@ -521,19 +521,6 @@ pub struct Expr {
|
||||||
span: Span,
|
span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Expr {
|
|
||||||
pub fn get_callee_id(&self) -> Option<NodeId> {
|
|
||||||
match self.node {
|
|
||||||
ExprMethodCall(callee_id, _, _, _) |
|
|
||||||
ExprIndex(callee_id, _, _) |
|
|
||||||
ExprBinary(callee_id, _, _, _) |
|
|
||||||
ExprAssignOp(callee_id, _, _, _) |
|
|
||||||
ExprUnary(callee_id, _, _) => Some(callee_id),
|
|
||||||
_ => None,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[deriving(Clone, Eq, Encodable, Decodable, Hash)]
|
#[deriving(Clone, Eq, Encodable, Decodable, Hash)]
|
||||||
pub enum Expr_ {
|
pub enum Expr_ {
|
||||||
ExprVstore(@Expr, ExprVstore),
|
ExprVstore(@Expr, ExprVstore),
|
||||||
|
@ -541,10 +528,10 @@ pub enum Expr_ {
|
||||||
ExprBox(@Expr, @Expr),
|
ExprBox(@Expr, @Expr),
|
||||||
ExprVec(~[@Expr], Mutability),
|
ExprVec(~[@Expr], Mutability),
|
||||||
ExprCall(@Expr, ~[@Expr]),
|
ExprCall(@Expr, ~[@Expr]),
|
||||||
ExprMethodCall(NodeId, Ident, ~[P<Ty>], ~[@Expr]),
|
ExprMethodCall(Ident, ~[P<Ty>], ~[@Expr]),
|
||||||
ExprTup(~[@Expr]),
|
ExprTup(~[@Expr]),
|
||||||
ExprBinary(NodeId, BinOp, @Expr, @Expr),
|
ExprBinary(BinOp, @Expr, @Expr),
|
||||||
ExprUnary(NodeId, UnOp, @Expr),
|
ExprUnary(UnOp, @Expr),
|
||||||
ExprLit(@Lit),
|
ExprLit(@Lit),
|
||||||
ExprCast(@Expr, P<Ty>),
|
ExprCast(@Expr, P<Ty>),
|
||||||
ExprIf(@Expr, P<Block>, Option<@Expr>),
|
ExprIf(@Expr, P<Block>, Option<@Expr>),
|
||||||
|
@ -560,9 +547,9 @@ pub enum Expr_ {
|
||||||
ExprBlock(P<Block>),
|
ExprBlock(P<Block>),
|
||||||
|
|
||||||
ExprAssign(@Expr, @Expr),
|
ExprAssign(@Expr, @Expr),
|
||||||
ExprAssignOp(NodeId, BinOp, @Expr, @Expr),
|
ExprAssignOp(BinOp, @Expr, @Expr),
|
||||||
ExprField(@Expr, Ident, ~[P<Ty>]),
|
ExprField(@Expr, Ident, ~[P<Ty>]),
|
||||||
ExprIndex(NodeId, @Expr, @Expr),
|
ExprIndex(@Expr, @Expr),
|
||||||
|
|
||||||
/// Expression that looks like a "name". For example,
|
/// Expression that looks like a "name". For example,
|
||||||
/// `std::vec::from_elem::<uint>` is an ExprPath that's the "name" part
|
/// `std::vec::from_elem::<uint>` is an ExprPath that's the "name" part
|
||||||
|
|
|
@ -107,7 +107,6 @@ pub enum Node {
|
||||||
|
|
||||||
/// NodeStructCtor represents a tuple struct.
|
/// NodeStructCtor represents a tuple struct.
|
||||||
NodeStructCtor(@StructDef),
|
NodeStructCtor(@StructDef),
|
||||||
NodeCalleeScope(@Expr),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The odd layout is to bring down the total size.
|
// The odd layout is to bring down the total size.
|
||||||
|
@ -128,7 +127,6 @@ enum MapEntry {
|
||||||
EntryLocal(NodeId, @Pat),
|
EntryLocal(NodeId, @Pat),
|
||||||
EntryBlock(NodeId, P<Block>),
|
EntryBlock(NodeId, P<Block>),
|
||||||
EntryStructCtor(NodeId, @StructDef),
|
EntryStructCtor(NodeId, @StructDef),
|
||||||
EntryCalleeScope(NodeId, @Expr),
|
|
||||||
|
|
||||||
// Roots for node trees.
|
// Roots for node trees.
|
||||||
RootCrate,
|
RootCrate,
|
||||||
|
@ -155,7 +153,6 @@ impl MapEntry {
|
||||||
EntryLocal(id, _) => id,
|
EntryLocal(id, _) => id,
|
||||||
EntryBlock(id, _) => id,
|
EntryBlock(id, _) => id,
|
||||||
EntryStructCtor(id, _) => id,
|
EntryStructCtor(id, _) => id,
|
||||||
EntryCalleeScope(id, _) => id,
|
|
||||||
_ => return None
|
_ => return None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -173,7 +170,6 @@ impl MapEntry {
|
||||||
EntryLocal(_, p) => NodeLocal(p),
|
EntryLocal(_, p) => NodeLocal(p),
|
||||||
EntryBlock(_, p) => NodeBlock(p),
|
EntryBlock(_, p) => NodeBlock(p),
|
||||||
EntryStructCtor(_, p) => NodeStructCtor(p),
|
EntryStructCtor(_, p) => NodeStructCtor(p),
|
||||||
EntryCalleeScope(_, p) => NodeCalleeScope(p),
|
|
||||||
_ => return None
|
_ => return None
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -368,7 +364,6 @@ impl Map {
|
||||||
Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
|
Some(NodeArg(pat)) | Some(NodeLocal(pat)) => pat.span,
|
||||||
Some(NodeBlock(block)) => block.span,
|
Some(NodeBlock(block)) => block.span,
|
||||||
Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
|
Some(NodeStructCtor(_)) => self.expect_item(self.get_parent(id)).span,
|
||||||
Some(NodeCalleeScope(expr)) => expr.span,
|
|
||||||
_ => fail!("node_span: could not find span for id {}", id),
|
_ => fail!("node_span: could not find span for id {}", id),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -493,11 +488,6 @@ impl<'a, F: FoldOps> Folder for Ctx<'a, F> {
|
||||||
|
|
||||||
self.insert(expr.id, EntryExpr(self.parent, expr));
|
self.insert(expr.id, EntryExpr(self.parent, expr));
|
||||||
|
|
||||||
// Expressions which are or might be calls:
|
|
||||||
for callee_id in expr.get_callee_id().iter() {
|
|
||||||
self.insert(*callee_id, EntryCalleeScope(self.parent, expr));
|
|
||||||
}
|
|
||||||
|
|
||||||
expr
|
expr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -650,9 +640,6 @@ fn node_id_to_str(map: &Map, id: NodeId) -> ~str {
|
||||||
Some(NodeExpr(expr)) => {
|
Some(NodeExpr(expr)) => {
|
||||||
format!("expr {} (id={})", pprust::expr_to_str(expr), id)
|
format!("expr {} (id={})", pprust::expr_to_str(expr), id)
|
||||||
}
|
}
|
||||||
Some(NodeCalleeScope(expr)) => {
|
|
||||||
format!("callee_scope {} (id={})", pprust::expr_to_str(expr), id)
|
|
||||||
}
|
|
||||||
Some(NodeStmt(stmt)) => {
|
Some(NodeStmt(stmt)) => {
|
||||||
format!("stmt {} (id={})", pprust::stmt_to_str(stmt), id)
|
format!("stmt {} (id={})", pprust::stmt_to_str(stmt), id)
|
||||||
}
|
}
|
||||||
|
|
|
@ -450,12 +450,6 @@ impl<'a, O: IdVisitingOperation> Visitor<()> for IdVisitor<'a, O> {
|
||||||
|
|
||||||
|
|
||||||
fn visit_expr(&mut self, expression: &Expr, env: ()) {
|
fn visit_expr(&mut self, expression: &Expr, env: ()) {
|
||||||
{
|
|
||||||
let optional_callee_id = expression.get_callee_id();
|
|
||||||
for callee_id in optional_callee_id.iter() {
|
|
||||||
self.operation.visit_id(*callee_id)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.operation.visit_id(expression.id);
|
self.operation.visit_id(expression.id);
|
||||||
visit::walk_expr(self, expression, env)
|
visit::walk_expr(self, expression, env)
|
||||||
}
|
}
|
||||||
|
|
|
@ -502,15 +502,14 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
|
|
||||||
fn expr_binary(&self, sp: Span, op: ast::BinOp,
|
fn expr_binary(&self, sp: Span, op: ast::BinOp,
|
||||||
lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr {
|
lhs: @ast::Expr, rhs: @ast::Expr) -> @ast::Expr {
|
||||||
self.expr(sp, ast::ExprBinary(ast::DUMMY_NODE_ID, op, lhs, rhs))
|
self.expr(sp, ast::ExprBinary(op, lhs, rhs))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
|
fn expr_deref(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
|
||||||
self.expr_unary(sp, ast::UnDeref, e)
|
self.expr_unary(sp, ast::UnDeref, e)
|
||||||
}
|
}
|
||||||
fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr)
|
fn expr_unary(&self, sp: Span, op: ast::UnOp, e: @ast::Expr) -> @ast::Expr {
|
||||||
-> @ast::Expr {
|
self.expr(sp, ast::ExprUnary(op, e))
|
||||||
self.expr(sp, ast::ExprUnary(ast::DUMMY_NODE_ID, op, e))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
|
fn expr_managed(&self, sp: Span, e: @ast::Expr) -> @ast::Expr {
|
||||||
|
@ -543,7 +542,7 @@ impl<'a> AstBuilder for ExtCtxt<'a> {
|
||||||
ident: ast::Ident,
|
ident: ast::Ident,
|
||||||
mut args: ~[@ast::Expr]) -> @ast::Expr {
|
mut args: ~[@ast::Expr]) -> @ast::Expr {
|
||||||
args.unshift(expr);
|
args.unshift(expr);
|
||||||
self.expr(span, ast::ExprMethodCall(ast::DUMMY_NODE_ID, ident, ~[], args))
|
self.expr(span, ast::ExprMethodCall(ident, ~[], args))
|
||||||
}
|
}
|
||||||
fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr {
|
fn expr_block(&self, b: P<ast::Block>) -> @ast::Expr {
|
||||||
self.expr(b.span, ast::ExprBlock(b))
|
self.expr(b.span, ast::ExprBlock(b))
|
||||||
|
|
|
@ -749,21 +749,19 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
|
||||||
ExprCall(folder.fold_expr(f),
|
ExprCall(folder.fold_expr(f),
|
||||||
args.map(|&x| folder.fold_expr(x)))
|
args.map(|&x| folder.fold_expr(x)))
|
||||||
}
|
}
|
||||||
ExprMethodCall(callee_id, i, ref tps, ref args) => {
|
ExprMethodCall(i, ref tps, ref args) => {
|
||||||
ExprMethodCall(
|
ExprMethodCall(
|
||||||
folder.new_id(callee_id),
|
|
||||||
folder.fold_ident(i),
|
folder.fold_ident(i),
|
||||||
tps.map(|&x| folder.fold_ty(x)),
|
tps.map(|&x| folder.fold_ty(x)),
|
||||||
args.map(|&x| folder.fold_expr(x)))
|
args.map(|&x| folder.fold_expr(x)))
|
||||||
}
|
}
|
||||||
ExprBinary(callee_id, binop, lhs, rhs) => {
|
ExprBinary(binop, lhs, rhs) => {
|
||||||
ExprBinary(folder.new_id(callee_id),
|
ExprBinary(binop,
|
||||||
binop,
|
|
||||||
folder.fold_expr(lhs),
|
folder.fold_expr(lhs),
|
||||||
folder.fold_expr(rhs))
|
folder.fold_expr(rhs))
|
||||||
}
|
}
|
||||||
ExprUnary(callee_id, binop, ohs) => {
|
ExprUnary(binop, ohs) => {
|
||||||
ExprUnary(folder.new_id(callee_id), binop, folder.fold_expr(ohs))
|
ExprUnary(binop, folder.fold_expr(ohs))
|
||||||
}
|
}
|
||||||
ExprLit(_) => e.node.clone(),
|
ExprLit(_) => e.node.clone(),
|
||||||
ExprCast(expr, ty) => {
|
ExprCast(expr, ty) => {
|
||||||
|
@ -802,9 +800,8 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
|
||||||
ExprAssign(el, er) => {
|
ExprAssign(el, er) => {
|
||||||
ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
|
ExprAssign(folder.fold_expr(el), folder.fold_expr(er))
|
||||||
}
|
}
|
||||||
ExprAssignOp(callee_id, op, el, er) => {
|
ExprAssignOp(op, el, er) => {
|
||||||
ExprAssignOp(folder.new_id(callee_id),
|
ExprAssignOp(op,
|
||||||
op,
|
|
||||||
folder.fold_expr(el),
|
folder.fold_expr(el),
|
||||||
folder.fold_expr(er))
|
folder.fold_expr(er))
|
||||||
}
|
}
|
||||||
|
@ -813,10 +810,8 @@ pub fn noop_fold_expr<T: Folder>(e: @Expr, folder: &mut T) -> @Expr {
|
||||||
folder.fold_ident(id),
|
folder.fold_ident(id),
|
||||||
tys.map(|&x| folder.fold_ty(x)))
|
tys.map(|&x| folder.fold_ty(x)))
|
||||||
}
|
}
|
||||||
ExprIndex(callee_id, el, er) => {
|
ExprIndex(el, er) => {
|
||||||
ExprIndex(folder.new_id(callee_id),
|
ExprIndex(folder.fold_expr(el), folder.fold_expr(er))
|
||||||
folder.fold_expr(el),
|
|
||||||
folder.fold_expr(er))
|
|
||||||
}
|
}
|
||||||
ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
|
ExprPath(ref pth) => ExprPath(folder.fold_path(pth)),
|
||||||
ExprLogLevel => ExprLogLevel,
|
ExprLogLevel => ExprLogLevel,
|
||||||
|
|
|
@ -1683,11 +1683,11 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_unary(&mut self, unop: ast::UnOp, expr: @Expr) -> ast::Expr_ {
|
pub fn mk_unary(&mut self, unop: ast::UnOp, expr: @Expr) -> ast::Expr_ {
|
||||||
ExprUnary(ast::DUMMY_NODE_ID, unop, expr)
|
ExprUnary(unop, expr)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_binary(&mut self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
|
pub fn mk_binary(&mut self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
|
||||||
ExprBinary(ast::DUMMY_NODE_ID, binop, lhs, rhs)
|
ExprBinary(binop, lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_call(&mut self, f: @Expr, args: ~[@Expr]) -> ast::Expr_ {
|
pub fn mk_call(&mut self, f: @Expr, args: ~[@Expr]) -> ast::Expr_ {
|
||||||
|
@ -1695,11 +1695,11 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mk_method_call(&mut self, ident: Ident, tps: ~[P<Ty>], args: ~[@Expr]) -> ast::Expr_ {
|
fn mk_method_call(&mut self, ident: Ident, tps: ~[P<Ty>], args: ~[@Expr]) -> ast::Expr_ {
|
||||||
ExprMethodCall(ast::DUMMY_NODE_ID, ident, tps, args)
|
ExprMethodCall(ident, tps, args)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_index(&mut self, expr: @Expr, idx: @Expr) -> ast::Expr_ {
|
pub fn mk_index(&mut self, expr: @Expr, idx: @Expr) -> ast::Expr_ {
|
||||||
ExprIndex(ast::DUMMY_NODE_ID, expr, idx)
|
ExprIndex(expr, idx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_field(&mut self, expr: @Expr, ident: Ident, tys: ~[P<Ty>]) -> ast::Expr_ {
|
pub fn mk_field(&mut self, expr: @Expr, ident: Ident, tys: ~[P<Ty>]) -> ast::Expr_ {
|
||||||
|
@ -1707,7 +1707,7 @@ impl Parser {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_assign_op(&mut self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
|
pub fn mk_assign_op(&mut self, binop: ast::BinOp, lhs: @Expr, rhs: @Expr) -> ast::Expr_ {
|
||||||
ExprAssignOp(ast::DUMMY_NODE_ID, binop, lhs, rhs)
|
ExprAssignOp(binop, lhs, rhs)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos, m: Mac_) -> @Expr {
|
pub fn mk_mac_expr(&mut self, lo: BytePos, hi: BytePos, m: Mac_) -> @Expr {
|
||||||
|
|
|
@ -1235,7 +1235,7 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
|
||||||
try!(print_expr(s, func));
|
try!(print_expr(s, func));
|
||||||
try!(print_call_post(s, *args));
|
try!(print_call_post(s, *args));
|
||||||
}
|
}
|
||||||
ast::ExprMethodCall(_, ident, ref tys, ref args) => {
|
ast::ExprMethodCall(ident, ref tys, ref args) => {
|
||||||
let base_args = args.slice_from(1);
|
let base_args = args.slice_from(1);
|
||||||
try!(print_expr(s, args[0]));
|
try!(print_expr(s, args[0]));
|
||||||
try!(word(&mut s.s, "."));
|
try!(word(&mut s.s, "."));
|
||||||
|
@ -1247,13 +1247,13 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
|
||||||
}
|
}
|
||||||
try!(print_call_post(s, base_args));
|
try!(print_call_post(s, base_args));
|
||||||
}
|
}
|
||||||
ast::ExprBinary(_, op, lhs, rhs) => {
|
ast::ExprBinary(op, lhs, rhs) => {
|
||||||
try!(print_expr(s, lhs));
|
try!(print_expr(s, lhs));
|
||||||
try!(space(&mut s.s));
|
try!(space(&mut s.s));
|
||||||
try!(word_space(s, ast_util::binop_to_str(op)));
|
try!(word_space(s, ast_util::binop_to_str(op)));
|
||||||
try!(print_expr(s, rhs));
|
try!(print_expr(s, rhs));
|
||||||
}
|
}
|
||||||
ast::ExprUnary(_, op, expr) => {
|
ast::ExprUnary(op, expr) => {
|
||||||
try!(word(&mut s.s, ast_util::unop_to_str(op)));
|
try!(word(&mut s.s, ast_util::unop_to_str(op)));
|
||||||
try!(print_expr(s, expr));
|
try!(print_expr(s, expr));
|
||||||
}
|
}
|
||||||
|
@ -1442,7 +1442,7 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
|
||||||
try!(word_space(s, "="));
|
try!(word_space(s, "="));
|
||||||
try!(print_expr(s, rhs));
|
try!(print_expr(s, rhs));
|
||||||
}
|
}
|
||||||
ast::ExprAssignOp(_, op, lhs, rhs) => {
|
ast::ExprAssignOp(op, lhs, rhs) => {
|
||||||
try!(print_expr(s, lhs));
|
try!(print_expr(s, lhs));
|
||||||
try!(space(&mut s.s));
|
try!(space(&mut s.s));
|
||||||
try!(word(&mut s.s, ast_util::binop_to_str(op)));
|
try!(word(&mut s.s, ast_util::binop_to_str(op)));
|
||||||
|
@ -1459,7 +1459,7 @@ pub fn print_expr(s: &mut State, expr: &ast::Expr) -> io::IoResult<()> {
|
||||||
try!(word(&mut s.s, ">"));
|
try!(word(&mut s.s, ">"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast::ExprIndex(_, expr, index) => {
|
ast::ExprIndex(expr, index) => {
|
||||||
try!(print_expr(s, expr));
|
try!(print_expr(s, expr));
|
||||||
try!(word(&mut s.s, "["));
|
try!(word(&mut s.s, "["));
|
||||||
try!(print_expr(s, index));
|
try!(print_expr(s, index));
|
||||||
|
|
|
@ -658,18 +658,17 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
|
||||||
}
|
}
|
||||||
visitor.visit_expr(callee_expression, env.clone())
|
visitor.visit_expr(callee_expression, env.clone())
|
||||||
}
|
}
|
||||||
ExprMethodCall(_, _, ref types, ref arguments) => {
|
ExprMethodCall(_, ref types, ref arguments) => {
|
||||||
walk_exprs(visitor, *arguments, env.clone());
|
walk_exprs(visitor, *arguments, env.clone());
|
||||||
for &typ in types.iter() {
|
for &typ in types.iter() {
|
||||||
visitor.visit_ty(typ, env.clone())
|
visitor.visit_ty(typ, env.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprBinary(_, _, left_expression, right_expression) => {
|
ExprBinary(_, left_expression, right_expression) => {
|
||||||
visitor.visit_expr(left_expression, env.clone());
|
visitor.visit_expr(left_expression, env.clone());
|
||||||
visitor.visit_expr(right_expression, env.clone())
|
visitor.visit_expr(right_expression, env.clone())
|
||||||
}
|
}
|
||||||
ExprAddrOf(_, subexpression) |
|
ExprAddrOf(_, subexpression) | ExprUnary(_, subexpression) => {
|
||||||
ExprUnary(_, _, subexpression) => {
|
|
||||||
visitor.visit_expr(subexpression, env.clone())
|
visitor.visit_expr(subexpression, env.clone())
|
||||||
}
|
}
|
||||||
ExprLit(_) => {}
|
ExprLit(_) => {}
|
||||||
|
@ -719,7 +718,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
|
||||||
visitor.visit_expr(right_hand_expression, env.clone());
|
visitor.visit_expr(right_hand_expression, env.clone());
|
||||||
visitor.visit_expr(left_hand_expression, env.clone())
|
visitor.visit_expr(left_hand_expression, env.clone())
|
||||||
}
|
}
|
||||||
ExprAssignOp(_, _, left_expression, right_expression) => {
|
ExprAssignOp(_, left_expression, right_expression) => {
|
||||||
visitor.visit_expr(right_expression, env.clone());
|
visitor.visit_expr(right_expression, env.clone());
|
||||||
visitor.visit_expr(left_expression, env.clone())
|
visitor.visit_expr(left_expression, env.clone())
|
||||||
}
|
}
|
||||||
|
@ -729,7 +728,7 @@ pub fn walk_expr<E: Clone, V: Visitor<E>>(visitor: &mut V, expression: &Expr, en
|
||||||
visitor.visit_ty(typ, env.clone())
|
visitor.visit_ty(typ, env.clone())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ExprIndex(_, main_expression, index_expression) => {
|
ExprIndex(main_expression, index_expression) => {
|
||||||
visitor.visit_expr(main_expression, env.clone());
|
visitor.visit_expr(main_expression, env.clone());
|
||||||
visitor.visit_expr(index_expression, env.clone())
|
visitor.visit_expr(index_expression, env.clone())
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue