Skip to content

Commit feedd37

Browse files
committed
Apply @nikomatsakis' nits and comments patch.
1 parent 26398b4 commit feedd37

File tree

8 files changed

+149
-83
lines changed

8 files changed

+149
-83
lines changed

src/librustc/middle/trans/callee.rs

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -173,10 +173,13 @@ pub fn trans_fn_ref(bcx: &Block, def_id: ast::DefId, node: ExprOrMethodCall) ->
173173
let type_params = node_id_type_params(bcx, node);
174174
let vtables = match node {
175175
ExprId(id) => node_vtables(bcx, id),
176-
MethodCall(method_call) if method_call.autoderef == 0 => {
177-
node_vtables(bcx, method_call.expr_id)
176+
MethodCall(ref method_call) => {
177+
if method_call.autoderef == 0 {
178+
node_vtables(bcx, method_call.expr_id)
179+
} else {
180+
None
181+
}
178182
}
179-
_ => None
180183
};
181184
debug!("trans_fn_ref(def_id={}, node={:?}, type_params={}, vtables={})",
182185
def_id.repr(bcx.tcx()), node, type_params.repr(bcx.tcx()),
@@ -381,15 +384,15 @@ pub fn trans_fn_ref_with_vtables(
381384
// Should be either intra-crate or inlined.
382385
assert_eq!(def_id.krate, ast::LOCAL_CRATE);
383386

384-
let ref_id = match node {
385-
ExprId(id) if id != 0 => Some(id),
386-
_ => None
387+
let opt_ref_id = match node {
388+
ExprId(id) => if id != 0 { Some(id) } else { None },
389+
MethodCall(_) => None,
387390
};
388391

389392
let (val, must_cast) =
390393
monomorphize::monomorphic_fn(ccx, def_id, &substs,
391394
vtables, self_vtables,
392-
ref_id);
395+
opt_ref_id);
393396
let mut val = val;
394397
if must_cast && node != ExprId(0) {
395398
// Monotype of the REFERENCE to the function (type params
@@ -758,9 +761,19 @@ pub fn trans_call_inner<'a>(
758761
}
759762

760763
pub enum CallArgs<'a> {
764+
// Supply value of arguments as a list of expressions that must be
765+
// translated. This is used in the common case of `foo(bar, qux)`.
761766
ArgExprs(&'a [@ast::Expr]),
767+
768+
// Supply value of arguments as a list of LLVM value refs; frequently
769+
// used with lang items and so forth, when the argument is an internal
770+
// value.
771+
ArgVals(&'a [ValueRef]),
772+
773+
// For overloaded operators: `(lhs, Option(rhs, rhs_id))`. `lhs`
774+
// is the left-hand-side and `rhs/rhs_id` is the datum/expr-id of
775+
// the right-hand-side (if any).
762776
ArgOverloadedOp(Datum<Expr>, Option<(Datum<Expr>, ast::NodeId)>),
763-
ArgVals(&'a [ValueRef])
764777
}
765778

766779
fn trans_args<'a>(cx: &'a Block<'a>,

src/librustc/middle/trans/common.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -809,9 +809,13 @@ pub fn expr_ty_adjusted(bcx: &Block, ex: &ast::Expr) -> ty::t {
809809
monomorphize_type(bcx, t)
810810
}
811811

812+
// Key used to lookup values supplied for type parameters in an expr.
812813
#[deriving(Eq)]
813814
pub enum ExprOrMethodCall {
815+
// Type parameters for a path like `None::<int>`
814816
ExprId(ast::NodeId),
817+
818+
// Type parameters for a method call like `a.foo::<int>()`
815819
MethodCall(typeck::MethodCall)
816820
}
817821

src/librustc/middle/trans/expr.rs

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1160,9 +1160,13 @@ fn trans_unary<'a>(bcx: &'a Block<'a>,
11601160
let _icx = push_ctxt("trans_unary_datum");
11611161

11621162
let method_call = MethodCall::expr(expr.id);
1163-
let overloaded = bcx.ccx().maps.method_map.borrow().get().contains_key(&method_call);
1164-
// if overloaded, would be RvalueDpsExpr
1165-
assert!(!overloaded || op == ast::UnDeref);
1163+
1164+
// The only overloaded operator that is translated to a datum
1165+
// is an overloaded deref, since it is always yields a `&T`.
1166+
// Otherwise, we should be in the RvalueDpsExpr path.
1167+
assert!(
1168+
op == ast::UnDeref ||
1169+
!bcx.ccx().maps.method_map.borrow().get().contains_key(&method_call));
11661170

11671171
let un_ty = expr_ty(bcx, expr);
11681172

@@ -1779,6 +1783,7 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
17791783

17801784
let mut bcx = bcx;
17811785

1786+
// Check for overloaded deref.
17821787
let method_call = MethodCall {
17831788
expr_id: expr.id,
17841789
autoderef: derefs as u32
@@ -1787,6 +1792,11 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
17871792
.find(&method_call).map(|method| method.ty);
17881793
let datum = match method_ty {
17891794
Some(method_ty) => {
1795+
// Overloaded. Evaluate `trans_overloaded_op`, which will
1796+
// invoke the user's deref() method, which basically
1797+
// converts from the `Shaht<T>` pointer that we have into
1798+
// a `&T` pointer. We can then proceed down the normal
1799+
// path (below) to dereference that `&T`.
17901800
let datum = if derefs == 0 {
17911801
datum
17921802
} else {
@@ -1798,7 +1808,10 @@ fn deref_once<'a>(bcx: &'a Block<'a>,
17981808
let ref_ty = ty::ty_fn_ret(monomorphize_type(bcx, method_ty));
17991809
Datum(val, ref_ty, RvalueExpr(Rvalue(ByValue)))
18001810
}
1801-
None => datum
1811+
None => {
1812+
// Not overloaded. We already have a pointer we know how to deref.
1813+
datum
1814+
}
18021815
};
18031816

18041817
let r = match ty::get(datum.ty).sty {

src/librustc/middle/trans/meth.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -335,10 +335,13 @@ fn combine_impl_and_methods_tps(bcx: &Block,
335335
// exist, in which case we need to make them.
336336
let vtables = match node {
337337
ExprId(id) => node_vtables(bcx, id),
338-
MethodCall(method_call) if method_call.autoderef == 0 => {
339-
node_vtables(bcx, method_call.expr_id)
338+
MethodCall(method_call) => {
339+
if method_call.autoderef == 0 {
340+
node_vtables(bcx, method_call.expr_id)
341+
} else {
342+
None
343+
}
340344
}
341-
_ => None
342345
};
343346
let r_m_origins = match vtables {
344347
Some(vt) => vt,

src/librustc/middle/ty.rs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ pub struct AutoDerefRef {
229229
autoref: Option<AutoRef>
230230
}
231231

232-
#[deriving(Decodable, Encodable)]
232+
#[deriving(Decodable, Encodable, Eq, Show)]
233233
pub enum AutoRef {
234234
/// Convert from T to &T
235235
AutoPtr(Region, ast::Mutability),
@@ -3271,11 +3271,15 @@ pub fn expr_kind(tcx: ctxt,
32713271
expr: &ast::Expr) -> ExprKind {
32723272
if method_map.borrow().get().contains_key(&MethodCall::expr(expr.id)) {
32733273
// Overloaded operations are generally calls, and hence they are
3274-
// generated via DPS. However, assign_op (e.g., `x += y`) is an
3275-
// exception, as its result is always unit.
3274+
// generated via DPS, but there are two exceptions:
32763275
return match expr.node {
3276+
// `a += b` has a unit result.
32773277
ast::ExprAssignOp(..) => RvalueStmtExpr,
3278+
3279+
// the deref method invoked for `*a` always yields an `&T`
32783280
ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
3281+
3282+
// in the general case, result could be any type, use DPS
32793283
_ => RvalueDpsExpr
32803284
};
32813285
}

src/librustc/middle/typeck/check/method.rs

Lines changed: 78 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,13 @@ pub fn lookup_in_trait<'a>(
201201
struct LookupContext<'a> {
202202
fcx: @FnCtxt,
203203
span: Span,
204+
205+
// The receiver to the method call. Only `None` in the case of
206+
// an overloaded autoderef, where the receiver may be an intermediate
207+
// state like "the expression `x` when it has been autoderef'd
208+
// twice already".
204209
self_expr: Option<&'a ast::Expr>,
210+
205211
m_name: ast::Name,
206212
supplied_tps: &'a [ty::t],
207213
impl_dups: @RefCell<HashSet<DefId>>,
@@ -243,51 +249,69 @@ impl<'a> LookupContext<'a> {
243249
let span = self.self_expr.map_or(self.span, |e| e.span);
244250
let self_expr_id = self.self_expr.map(|e| e.id);
245251
let (self_ty, autoderefs, result) =
246-
check::autoderef(self.fcx, span, self_ty, self_expr_id,
247-
PreferMutLvalue, |self_ty, autoderefs| {
248-
249-
debug!("loop: self_ty={} autoderefs={}",
250-
self.ty_to_str(self_ty), autoderefs);
252+
check::autoderef(
253+
self.fcx, span, self_ty, self_expr_id, PreferMutLvalue,
254+
|self_ty, autoderefs| self.search_step(self_ty, autoderefs));
251255

252-
match self.deref_args {
253-
check::DontDerefArgs => {
254-
match self.search_for_autoderefd_method(self_ty, autoderefs) {
255-
Some(result) => return Some(Some(result)),
256-
None => {}
257-
}
256+
match result {
257+
Some(Some(result)) => Some(result),
258+
_ => {
259+
if self.is_overloaded_deref() {
260+
// If we are searching for an overloaded deref, no
261+
// need to try coercing a `~[T]` to an `&[T]` and
262+
// searching for an overloaded deref on *that*.
263+
None
264+
} else {
265+
self.search_for_autosliced_method(self_ty, autoderefs)
266+
}
267+
}
268+
}
269+
}
258270

259-
match self.search_for_autoptrd_method(self_ty, autoderefs) {
260-
Some(result) => return Some(Some(result)),
261-
None => {}
262-
}
271+
fn search_step(&self,
272+
self_ty: ty::t,
273+
autoderefs: uint)
274+
-> Option<Option<MethodCallee>> {
275+
debug!("search_step: self_ty={} autoderefs={}",
276+
self.ty_to_str(self_ty), autoderefs);
277+
278+
match self.deref_args {
279+
check::DontDerefArgs => {
280+
match self.search_for_autoderefd_method(self_ty, autoderefs) {
281+
Some(result) => return Some(Some(result)),
282+
None => {}
263283
}
264-
check::DoDerefArgs => {
265-
match self.search_for_autoptrd_method(self_ty, autoderefs) {
266-
Some(result) => return Some(Some(result)),
267-
None => {}
268-
}
269284

270-
match self.search_for_autoderefd_method(self_ty, autoderefs) {
271-
Some(result) => return Some(Some(result)),
272-
None => {}
273-
}
285+
match self.search_for_autoptrd_method(self_ty, autoderefs) {
286+
Some(result) => return Some(Some(result)),
287+
None => {}
274288
}
275289
}
290+
check::DoDerefArgs => {
291+
match self.search_for_autoptrd_method(self_ty, autoderefs) {
292+
Some(result) => return Some(Some(result)),
293+
None => {}
294+
}
276295

277-
// Don't autoderef if we aren't supposed to.
278-
if self.autoderef_receiver == DontAutoderefReceiver {
279-
Some(None)
280-
} else {
281-
None
296+
match self.search_for_autoderefd_method(self_ty, autoderefs) {
297+
Some(result) => return Some(Some(result)),
298+
None => {}
299+
}
282300
}
283-
});
301+
}
284302

285-
match result {
286-
Some(Some(result)) => Some(result),
287-
_ => self.search_for_autosliced_method(self_ty, autoderefs)
303+
// Don't autoderef if we aren't supposed to.
304+
if self.autoderef_receiver == DontAutoderefReceiver {
305+
Some(None)
306+
} else {
307+
None
288308
}
289309
}
290310

311+
fn is_overloaded_deref(&self) -> bool {
312+
self.self_expr.is_none()
313+
}
314+
291315
// ______________________________________________________________________
292316
// Candidate collection (see comment at start of file)
293317

@@ -625,17 +649,13 @@ impl<'a> LookupContext<'a> {
625649
let (self_ty, auto_deref_ref) =
626650
self.consider_reborrow(self_ty, autoderefs);
627651

628-
// HACK(eddyb) only overloaded auto-deref calls should be missing
629-
// adjustments, because we imply an AutoPtr adjustment for them.
630-
let adjustment = match auto_deref_ref {
631-
ty::AutoDerefRef {
632-
autoderefs: 0,
633-
autoref: Some(ty::AutoPtr(..))
634-
} => None,
635-
_ => match self.self_expr {
636-
Some(expr) => Some((expr.id, @ty::AutoDerefRef(auto_deref_ref))),
637-
None => return None
638-
}
652+
// Hacky. For overloaded derefs, there may be an adjustment
653+
// added to the expression from the outside context, so we do not store
654+
// an explicit adjustment, but rather we hardwire the single deref
655+
// that occurs in trans and mem_categorization.
656+
let adjustment = match self.self_expr {
657+
Some(expr) => Some((expr.id, @ty::AutoDerefRef(auto_deref_ref))),
658+
None => return None
639659
};
640660

641661
match self.search_for_method(self_ty) {
@@ -733,9 +753,9 @@ impl<'a> LookupContext<'a> {
733753
autoderefs: uint)
734754
-> Option<MethodCallee> {
735755
/*!
736-
*
737756
* Searches for a candidate by converting things like
738-
* `~[]` to `&[]`. */
757+
* `~[]` to `&[]`.
758+
*/
739759

740760
let tcx = self.tcx();
741761
let sty = ty::get(self_ty).sty.clone();
@@ -843,15 +863,20 @@ impl<'a> LookupContext<'a> {
843863
mutbls: &[ast::Mutability],
844864
mk_autoref_ty: |ast::Mutability, ty::Region| -> ty::t)
845865
-> Option<MethodCallee> {
846-
// HACK(eddyb) only overloaded auto-deref calls should be missing
847-
// adjustments, because we imply an AutoPtr adjustment for them.
866+
// Hacky. For overloaded derefs, there may be an adjustment
867+
// added to the expression from the outside context, so we do not store
868+
// an explicit adjustment, but rather we hardwire the single deref
869+
// that occurs in trans and mem_categorization.
848870
let self_expr_id = match self.self_expr {
849871
Some(expr) => Some(expr.id),
850-
None => match kind(ty::ReEmpty, ast::MutImmutable) {
851-
ty::AutoPtr(..) if autoderefs == 0 => None,
852-
_ => return None
872+
None => {
873+
assert_eq!(autoderefs, 0);
874+
assert_eq!(kind(ty::ReEmpty, ast::MutImmutable),
875+
ty::AutoPtr(ty::ReEmpty, ast::MutImmutable));
876+
None
853877
}
854878
};
879+
855880
// This is hokey. We should have mutability inference as a
856881
// variable. But for now, try &const, then &, then &mut:
857882
let region =
@@ -1119,7 +1144,8 @@ impl<'a> LookupContext<'a> {
11191144
&self,
11201145
trait_def_id: ast::DefId,
11211146
rcvr_substs: &ty::substs,
1122-
method_ty: &ty::Method) -> ty::t {
1147+
method_ty: &ty::Method)
1148+
-> ty::t {
11231149
/*!
11241150
* This is a bit tricky. We have a match against a trait method
11251151
* being invoked on an object, and we want to generate the

src/librustc/middle/typeck/check/mod.rs

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1247,11 +1247,14 @@ pub fn autoderef<T>(fcx: @FnCtxt, sp: Span, base_ty: ty::t,
12471247
should_stop: |ty::t, uint| -> Option<T>)
12481248
-> (ty::t, uint, Option<T>) {
12491249
/*!
1250+
* Executes an autoderef loop for the type `t`. At each step, invokes
1251+
* `should_stop` to decide whether to terminate the loop. Returns
1252+
* the final type and number of derefs that it performed.
12501253
*
1251-
* Autoderefs the type `t` as many times as possible, returning a new type
1252-
* and an autoderef count. If the count is not zero, the receiver is
1253-
* responsible for inserting an AutoAdjustment record into `tcx.adjustments`
1254-
* so that trans/borrowck/etc know about this autoderef. */
1254+
* Note: this method does not modify the adjustments table. The caller is
1255+
* responsible for inserting an AutoAdjustment record into the `fcx`
1256+
* using one of the suitable methods.
1257+
*/
12551258

12561259
let mut t = base_ty;
12571260
for autoderefs in range(0, fcx.tcx().sess.recursion_limit.get()) {
@@ -2282,15 +2285,15 @@ fn check_expr_with_unifier(fcx: @FnCtxt,
22822285
// FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
22832286
let (_, autoderefs, field_ty) =
22842287
autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
2285-
match ty::get(base_t).sty {
2286-
ty::ty_struct(base_id, ref substs) => {
2287-
debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2288-
let fields = ty::lookup_struct_fields(tcx, base_id);
2289-
lookup_field_ty(tcx, base_id, fields.as_slice(), field, &(*substs))
2288+
match ty::get(base_t).sty {
2289+
ty::ty_struct(base_id, ref substs) => {
2290+
debug!("struct named {}", ppaux::ty_to_str(tcx, base_t));
2291+
let fields = ty::lookup_struct_fields(tcx, base_id);
2292+
lookup_field_ty(tcx, base_id, fields.as_slice(), field, &(*substs))
2293+
}
2294+
_ => None
22902295
}
2291-
_ => None
2292-
}
2293-
});
2296+
});
22942297
match field_ty {
22952298
Some(field_ty) => {
22962299
fcx.write_ty(expr.id, field_ty);

0 commit comments

Comments
 (0)