Skip to content

Commit 20b4e15

Browse files
committed
Implement automatic overloaded dereference.
Closes #7141.
1 parent cdc18b9 commit 20b4e15

33 files changed

+871
-921
lines changed

src/libnum/complex.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,7 @@ impl<T: Clone + Float> Cmplx<T> {
101101
/// Convert a polar representation into a complex number.
102102
#[inline]
103103
pub fn from_polar(r: &T, theta: &T) -> Cmplx<T> {
104-
Cmplx::new(r * theta.cos(), r * theta.sin())
104+
Cmplx::new(*r * theta.cos(), *r * theta.sin())
105105
}
106106
}
107107

src/librustc/middle/astencode.rs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ use metadata::tydecode;
2121
use metadata::tydecode::{DefIdSource, NominalType, TypeWithId, TypeParameter,
2222
RegionParameter};
2323
use metadata::tyencode;
24-
use middle::typeck::{MethodCallee, MethodOrigin};
24+
use middle::typeck::{MethodCall, MethodCallee, MethodOrigin};
2525
use middle::{ty, typeck, moves};
2626
use middle;
2727
use util::ppaux::ty_to_str;
@@ -1039,7 +1039,8 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
10391039
}
10401040
}
10411041

1042-
for &method in maps.method_map.borrow().get().find(&id).iter() {
1042+
let method_call = MethodCall::expr(id);
1043+
for &method in maps.method_map.borrow().get().find(&method_call).iter() {
10431044
ebml_w.tag(c::tag_table_method_map, |ebml_w| {
10441045
ebml_w.id(id);
10451046
ebml_w.tag(c::tag_table_val, |ebml_w| {
@@ -1385,7 +1386,8 @@ fn decode_side_tables(xcx: @ExtendedDecodeContext,
13851386
}
13861387
c::tag_table_method_map => {
13871388
let method = val_dsr.read_method_callee(xcx);
1388-
dcx.maps.method_map.borrow_mut().get().insert(id, method);
1389+
let method_call = MethodCall::expr(id);
1390+
dcx.maps.method_map.borrow_mut().get().insert(method_call, method);
13891391
}
13901392
c::tag_table_vtable_map => {
13911393
let vtable_res =

src/librustc/middle/borrowck/check_loans.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use mc = middle::mem_categorization;
2222
use middle::borrowck::*;
2323
use middle::moves;
2424
use middle::ty;
25+
use middle::typeck::MethodCall;
2526
use std::vec_ng::Vec;
2627
use syntax::ast;
2728
use syntax::ast_util;
@@ -838,11 +839,11 @@ fn check_loans_in_expr<'a>(this: &mut CheckLoanCtxt<'a>,
838839
this.check_call(expr, None, expr.span, args.as_slice());
839840
}
840841
ast::ExprIndex(_, rval) | ast::ExprBinary(_, _, rval)
841-
if method_map.get().contains_key(&expr.id) => {
842+
if method_map.get().contains_key(&MethodCall::expr(expr.id)) => {
842843
this.check_call(expr, None, expr.span, [rval]);
843844
}
844845
ast::ExprUnary(_, _) | ast::ExprIndex(_, _)
845-
if method_map.get().contains_key(&expr.id) => {
846+
if method_map.get().contains_key(&MethodCall::expr(expr.id)) => {
846847
this.check_call(expr, None, expr.span, []);
847848
}
848849
ast::ExprInlineAsm(ref ia) => {

src/librustc/middle/borrowck/gather_loans/mod.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ use middle::moves;
2323
use middle::pat_util;
2424
use middle::ty::{ty_region};
2525
use middle::ty;
26+
use middle::typeck::MethodCall;
2627
use util::common::indenter;
2728
use util::ppaux::{Repr};
2829

@@ -242,7 +243,7 @@ fn gather_loans_in_expr(this: &mut GatherLoanCtxt,
242243

243244
ast::ExprIndex(_, arg) |
244245
ast::ExprBinary(_, _, arg)
245-
if method_map.get().contains_key(&ex.id) => {
246+
if method_map.get().contains_key(&MethodCall::expr(ex.id)) => {
246247
// Arguments in method calls are always passed by ref.
247248
//
248249
// Currently these do not use adjustments, so we have to

src/librustc/middle/borrowck/mod.rs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,8 @@ impl BorrowckCtxt {
556556
move_data::MoveExpr => {
557557
let (expr_ty, expr_span) = match self.tcx.map.find(move.id) {
558558
Some(ast_map::NodeExpr(expr)) => {
559-
(ty::expr_ty_adjusted(self.tcx, expr), expr.span)
559+
(ty::expr_ty_adjusted(self.tcx, expr,
560+
self.method_map.borrow().get()), expr.span)
560561
}
561562
r => self.tcx.sess.bug(format!("MoveExpr({:?}) maps to {:?}, not Expr",
562563
move.id, r))
@@ -582,7 +583,8 @@ impl BorrowckCtxt {
582583
move_data::Captured => {
583584
let (expr_ty, expr_span) = match self.tcx.map.find(move.id) {
584585
Some(ast_map::NodeExpr(expr)) => {
585-
(ty::expr_ty_adjusted(self.tcx, expr), expr.span)
586+
(ty::expr_ty_adjusted(self.tcx, expr,
587+
self.method_map.borrow().get()), expr.span)
586588
}
587589
r => self.tcx.sess.bug(format!("Captured({:?}) maps to {:?}, not Expr",
588590
move.id, r))
@@ -922,8 +924,8 @@ impl mc::Typer for TcxTyper {
922924
Ok(ty::node_id_to_type(self.tcx, id))
923925
}
924926

925-
fn node_method_ty(&mut self, id: ast::NodeId) -> Option<ty::t> {
926-
self.method_map.borrow().get().find(&id).map(|method| method.ty)
927+
fn node_method_ty(&mut self, method_call: typeck::MethodCall) -> Option<ty::t> {
928+
self.method_map.borrow().get().find(&method_call).map(|method| method.ty)
927929
}
928930

929931
fn adjustment(&mut self, id: ast::NodeId) -> Option<@ty::AutoAdjustment> {
@@ -932,7 +934,7 @@ impl mc::Typer for TcxTyper {
932934
}
933935

934936
fn is_method_call(&mut self, id: ast::NodeId) -> bool {
935-
self.method_map.borrow().get().contains_key(&id)
937+
self.method_map.borrow().get().contains_key(&typeck::MethodCall::expr(id))
936938
}
937939

938940
fn temporary_scope(&mut self, id: ast::NodeId) -> Option<ast::NodeId> {

src/librustc/middle/cfg/construct.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -523,7 +523,7 @@ impl CFGBuilder {
523523
}
524524

525525
fn is_method_call(&self, expr: &ast::Expr) -> bool {
526-
let method_map = self.method_map.borrow();
527-
method_map.get().contains_key(&expr.id)
526+
let method_call = typeck::MethodCall::expr(expr.id);
527+
self.method_map.borrow().get().contains_key(&method_call)
528528
}
529529
}

src/librustc/middle/check_const.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -117,8 +117,8 @@ pub fn check_expr(v: &mut CheckCrateVisitor,
117117
}
118118
ExprLit(lit) if ast_util::lit_is_str(lit) => {}
119119
ExprBinary(..) | ExprUnary(..) => {
120-
let method_map = method_map.borrow();
121-
if method_map.get().contains_key(&e.id) {
120+
let method_call = typeck::MethodCall::expr(e.id);
121+
if method_map.borrow().get().contains_key(&method_call) {
122122
sess.span_err(e.span, "user-defined operators are not \
123123
allowed in constant expressions");
124124
}

src/librustc/middle/const_eval.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ use middle::astencode;
1616
use middle::ty;
1717
use middle::typeck::astconv;
1818
use middle;
19-
use util::nodemap::{DefIdMap, NodeMap};
19+
use util::nodemap::{DefIdMap, FnvHashMap, NodeMap};
2020

2121
use syntax::ast::*;
2222
use syntax::parse::token::InternedString;
@@ -136,7 +136,7 @@ pub fn lookup_variant_by_id(tcx: ty::ctxt,
136136
}
137137
let maps = astencode::Maps {
138138
root_map: @RefCell::new(HashMap::new()),
139-
method_map: @RefCell::new(NodeMap::new()),
139+
method_map: @RefCell::new(FnvHashMap::new()),
140140
vtable_map: @RefCell::new(NodeMap::new()),
141141
capture_map: @RefCell::new(NodeMap::new())
142142
};
@@ -186,7 +186,7 @@ pub fn lookup_const_by_id(tcx: ty::ctxt, def_id: ast::DefId)
186186
}
187187
let maps = astencode::Maps {
188188
root_map: @RefCell::new(HashMap::new()),
189-
method_map: @RefCell::new(NodeMap::new()),
189+
method_map: @RefCell::new(FnvHashMap::new()),
190190
vtable_map: @RefCell::new(NodeMap::new()),
191191
capture_map: @RefCell::new(NodeMap::new())
192192
};

src/librustc/middle/dataflow.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -810,8 +810,8 @@ impl<'a, O:DataFlowOperator> PropagationContext<'a, O> {
810810
}
811811

812812
fn is_method_call(&self, expr: &ast::Expr) -> bool {
813-
let method_map = self.dfcx.method_map.borrow();
814-
method_map.get().contains_key(&expr.id)
813+
let method_call = typeck::MethodCall::expr(expr.id);
814+
self.dfcx.method_map.borrow().get().contains_key(&method_call)
815815
}
816816

817817
fn reset(&mut self, bits: &mut [uint]) {

src/librustc/middle/dead.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ impl MarkSymbolVisitor {
9292
}
9393
}
9494

95-
fn lookup_and_handle_method(&mut self, id: &ast::NodeId,
95+
fn lookup_and_handle_method(&mut self, id: ast::NodeId,
9696
span: codemap::Span) {
97-
match self.method_map.borrow().get().find(id) {
97+
let method_call = typeck::MethodCall::expr(id);
98+
match self.method_map.borrow().get().find(&method_call) {
9899
Some(method) => {
99100
match method.origin {
100101
typeck::MethodStatic(def_id) => {
@@ -179,7 +180,7 @@ impl Visitor<()> for MarkSymbolVisitor {
179180
fn visit_expr(&mut self, expr: &ast::Expr, _: ()) {
180181
match expr.node {
181182
ast::ExprMethodCall(..) => {
182-
self.lookup_and_handle_method(&expr.id, expr.span);
183+
self.lookup_and_handle_method(expr.id, expr.span);
183184
}
184185
_ => ()
185186
}

src/librustc/middle/effect.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
/// `unsafe`.
1313
1414
use middle::ty;
15-
use middle::typeck::MethodMap;
15+
use middle::typeck::{MethodCall, MethodMap};
1616
use util::ppaux;
1717

1818
use syntax::ast;
@@ -138,7 +138,8 @@ impl Visitor<()> for EffectCheckVisitor {
138138
fn visit_expr(&mut self, expr: &ast::Expr, _:()) {
139139
match expr.node {
140140
ast::ExprMethodCall(_, _, _) => {
141-
let base_type = self.method_map.borrow().get().get(&expr.id).ty;
141+
let method_call = MethodCall::expr(expr.id);
142+
let base_type = self.method_map.borrow().get().get(&method_call).ty;
142143
debug!("effect: method call case, base type is {}",
143144
ppaux::ty_to_str(self.tcx, base_type));
144145
if type_is_unsafe_function(base_type) {

src/librustc/middle/kind.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,7 +267,7 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
267267
// Handle any kind bounds on type parameters
268268
{
269269
let method_map = cx.method_map.borrow();
270-
let method = method_map.get().find(&e.id);
270+
let method = method_map.get().find(&typeck::MethodCall::expr(e.id));
271271
let node_type_substs = cx.tcx.node_type_substs.borrow();
272272
let r = match method {
273273
Some(method) => Some(&method.substs.tps),
@@ -341,7 +341,8 @@ pub fn check_expr(cx: &mut Context, e: &Expr) {
341341
match **adjustment {
342342
ty::AutoObject(..) => {
343343
let source_ty = ty::expr_ty(cx.tcx, e);
344-
let target_ty = ty::expr_ty_adjusted(cx.tcx, e);
344+
let target_ty = ty::expr_ty_adjusted(cx.tcx, e,
345+
cx.method_map.borrow().get());
345346
check_trait_cast(cx, source_ty, target_ty, e.span);
346347
}
347348
ty::AutoAddEnv(..) |

src/librustc/middle/lint.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1491,7 +1491,8 @@ fn check_stability(cx: &Context, e: &ast::Expr) {
14911491
}
14921492
}
14931493
ast::ExprMethodCall(..) => {
1494-
match cx.method_map.borrow().get().find(&e.id) {
1494+
let method_call = typeck::MethodCall::expr(e.id);
1495+
match cx.method_map.borrow().get().find(&method_call) {
14951496
Some(method) => {
14961497
match method.origin {
14971498
typeck::MethodStatic(def_id) => {

src/librustc/middle/mem_categorization.rs

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
#[allow(non_camel_case_types)];
6464

6565
use middle::ty;
66+
use middle::typeck;
6667
use util::ppaux::{ty_to_str, region_ptr_to_str, Repr};
6768

6869
use std::vec_ng::Vec;
@@ -268,7 +269,7 @@ pub type McResult<T> = Result<T, ()>;
268269
pub trait Typer {
269270
fn tcx(&self) -> ty::ctxt;
270271
fn node_ty(&mut self, id: ast::NodeId) -> McResult<ty::t>;
271-
fn node_method_ty(&mut self, id: ast::NodeId) -> Option<ty::t>;
272+
fn node_method_ty(&mut self, method_call: typeck::MethodCall) -> Option<ty::t>;
272273
fn adjustment(&mut self, node_id: ast::NodeId) -> Option<@ty::AutoAdjustment>;
273274
fn is_method_call(&mut self, id: ast::NodeId) -> bool;
274275
fn temporary_scope(&mut self, rvalue_id: ast::NodeId) -> Option<ast::NodeId>;
@@ -365,7 +366,8 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
365366
fn expr_ty_adjusted(&mut self, expr: &ast::Expr) -> McResult<ty::t> {
366367
let unadjusted_ty = if_ok!(self.expr_ty(expr));
367368
let adjustment = self.adjustment(expr.id);
368-
Ok(ty::adjust_ty(self.tcx(), expr.span, unadjusted_ty, adjustment))
369+
Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty, adjustment,
370+
|method_call| self.typer.node_method_ty(method_call)))
369371
}
370372

371373
fn node_ty(&mut self, id: ast::NodeId) -> McResult<ty::t> {
@@ -435,21 +437,11 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
435437
let expr_ty = if_ok!(self.expr_ty(expr));
436438
match expr.node {
437439
ast::ExprUnary(ast::UnDeref, e_base) => {
438-
let base_cmt = match self.typer.node_method_ty(expr.id) {
439-
Some(method_ty) => {
440-
let ref_ty = ty::ty_fn_ret(method_ty);
441-
self.cat_rvalue_node(expr.id(), expr.span(), ref_ty)
442-
}
443-
None => if_ok!(self.cat_expr(e_base))
444-
};
440+
let base_cmt = if_ok!(self.cat_expr(e_base));
445441
Ok(self.cat_deref(expr, base_cmt, 0))
446442
}
447443

448444
ast::ExprField(base, f_name, _) => {
449-
// Method calls are now a special syntactic form,
450-
// so `a.b` should always be a field.
451-
assert!(!self.typer.is_method_call(expr.id));
452-
453445
let base_cmt = if_ok!(self.cat_expr(base));
454446
Ok(self.cat_field(expr, base_cmt, f_name, expr_ty))
455447
}
@@ -725,59 +717,64 @@ impl<TYPER:Typer> MemCategorizationContext<TYPER> {
725717
// `()` (the empty tuple).
726718

727719
let opaque_ty = ty::mk_tup(self.tcx(), Vec::new());
728-
return self.cat_deref_common(node, base_cmt, deref_cnt, opaque_ty);
720+
self.cat_deref_common(node, base_cmt, deref_cnt, opaque_ty)
729721
}
730722

731-
pub fn cat_deref<N:ast_node>(&mut self,
732-
node: &N,
733-
base_cmt: cmt,
734-
deref_cnt: uint)
735-
-> cmt {
736-
let mt = match ty::deref(base_cmt.ty, true) {
737-
Some(mt) => mt,
723+
fn cat_deref<N:ast_node>(&mut self,
724+
node: &N,
725+
base_cmt: cmt,
726+
deref_cnt: uint)
727+
-> cmt {
728+
let method_call = typeck::MethodCall {
729+
expr_id: node.id(),
730+
autoderef: deref_cnt as u32
731+
};
732+
let method_ty = self.typer.node_method_ty(method_call);
733+
734+
debug!("cat_deref: method_call={:?} method_ty={}",
735+
method_call, method_ty.map(|ty| ty.repr(self.tcx())));
736+
737+
let base_cmt = match method_ty {
738+
Some(method_ty) => {
739+
let ref_ty = ty::ty_fn_ret(method_ty);
740+
self.cat_rvalue_node(node.id(), node.span(), ref_ty)
741+
}
742+
None => base_cmt
743+
};
744+
match ty::deref(base_cmt.ty, true) {
745+
Some(mt) => self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty),
738746
None => {
739747
self.tcx().sess.span_bug(
740748
node.span(),
741749
format!("Explicit deref of non-derefable type: {}",
742750
base_cmt.ty.repr(self.tcx())));
743751
}
744-
};
745-
746-
return self.cat_deref_common(node, base_cmt, deref_cnt, mt.ty);
752+
}
747753
}
748754

749-
pub fn cat_deref_common<N:ast_node>(&mut self,
750-
node: &N,
751-
base_cmt: cmt,
752-
deref_cnt: uint,
753-
deref_ty: ty::t)
754-
-> cmt {
755-
match deref_kind(self.tcx(), base_cmt.ty) {
755+
fn cat_deref_common<N:ast_node>(&mut self,
756+
node: &N,
757+
base_cmt: cmt,
758+
deref_cnt: uint,
759+
deref_ty: ty::t)
760+
-> cmt {
761+
let (m, cat) = match deref_kind(self.tcx(), base_cmt.ty) {
756762
deref_ptr(ptr) => {
757763
// for unique ptrs, we inherit mutability from the
758764
// owning reference.
759-
let m = MutabilityCategory::from_pointer_kind(base_cmt.mutbl,
760-
ptr);
761-
762-
@cmt_ {
763-
id:node.id(),
764-
span:node.span(),
765-
cat:cat_deref(base_cmt, deref_cnt, ptr),
766-
mutbl:m,
767-
ty:deref_ty
768-
}
765+
(MutabilityCategory::from_pointer_kind(base_cmt.mutbl, ptr),
766+
cat_deref(base_cmt, deref_cnt, ptr))
769767
}
770-
771768
deref_interior(interior) => {
772-
let m = base_cmt.mutbl.inherit();
773-
@cmt_ {
774-
id:node.id(),
775-
span:node.span(),
776-
cat:cat_interior(base_cmt, interior),
777-
mutbl:m,
778-
ty:deref_ty
779-
}
769+
(base_cmt.mutbl.inherit(), cat_interior(base_cmt, interior))
780770
}
771+
};
772+
@cmt_ {
773+
id: node.id(),
774+
span: node.span(),
775+
cat: cat,
776+
mutbl: m,
777+
ty: deref_ty
781778
}
782779
}
783780

0 commit comments

Comments
 (0)