Skip to content

Commit c24946e

Browse files
committed
auto merge of #12493 : eddyb/rust/saner-overloads, r=nikomatsakis
Fixes #12402.
2 parents fc1c06d + 3950471 commit c24946e

File tree

5 files changed

+193
-277
lines changed

5 files changed

+193
-277
lines changed

src/librustc/middle/resolve.rs

+3-75
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ struct binding_info {
4646
type BindingMap = HashMap<Name,binding_info>;
4747

4848
// Trait method resolution
49-
pub type TraitMap = HashMap<NodeId,@RefCell<~[DefId]>>;
49+
pub type TraitMap = HashMap<NodeId, ~[DefId]>;
5050

5151
// This is the replacement export map. It maps a module to all of the exports
5252
// within.
@@ -5255,75 +5255,14 @@ impl Resolver {
52555255
// the field name so that we can do some nice error reporting
52565256
// later on in typeck.
52575257
let traits = self.search_for_traits_containing_method(ident);
5258-
self.trait_map.insert(expr.id, @RefCell::new(traits));
5258+
self.trait_map.insert(expr.id, traits);
52595259
}
52605260
ExprMethodCall(_, ident, _, _) => {
52615261
debug!("(recording candidate traits for expr) recording \
52625262
traits for {}",
52635263
expr.id);
52645264
let traits = self.search_for_traits_containing_method(ident);
5265-
self.trait_map.insert(expr.id, @RefCell::new(traits));
5266-
}
5267-
ExprBinary(_, BiAdd, _, _) | ExprAssignOp(_, BiAdd, _, _) => {
5268-
let i = self.lang_items.add_trait();
5269-
self.add_fixed_trait_for_expr(expr.id, i);
5270-
}
5271-
ExprBinary(_, BiSub, _, _) | ExprAssignOp(_, BiSub, _, _) => {
5272-
let i = self.lang_items.sub_trait();
5273-
self.add_fixed_trait_for_expr(expr.id, i);
5274-
}
5275-
ExprBinary(_, BiMul, _, _) | ExprAssignOp(_, BiMul, _, _) => {
5276-
let i = self.lang_items.mul_trait();
5277-
self.add_fixed_trait_for_expr(expr.id, i);
5278-
}
5279-
ExprBinary(_, BiDiv, _, _) | ExprAssignOp(_, BiDiv, _, _) => {
5280-
let i = self.lang_items.div_trait();
5281-
self.add_fixed_trait_for_expr(expr.id, i);
5282-
}
5283-
ExprBinary(_, BiRem, _, _) | ExprAssignOp(_, BiRem, _, _) => {
5284-
let i = self.lang_items.rem_trait();
5285-
self.add_fixed_trait_for_expr(expr.id, i);
5286-
}
5287-
ExprBinary(_, BiBitXor, _, _) | ExprAssignOp(_, BiBitXor, _, _) => {
5288-
let i = self.lang_items.bitxor_trait();
5289-
self.add_fixed_trait_for_expr(expr.id, i);
5290-
}
5291-
ExprBinary(_, BiBitAnd, _, _) | ExprAssignOp(_, BiBitAnd, _, _) => {
5292-
let i = self.lang_items.bitand_trait();
5293-
self.add_fixed_trait_for_expr(expr.id, i);
5294-
}
5295-
ExprBinary(_, BiBitOr, _, _) | ExprAssignOp(_, BiBitOr, _, _) => {
5296-
let i = self.lang_items.bitor_trait();
5297-
self.add_fixed_trait_for_expr(expr.id, i);
5298-
}
5299-
ExprBinary(_, BiShl, _, _) | ExprAssignOp(_, BiShl, _, _) => {
5300-
let i = self.lang_items.shl_trait();
5301-
self.add_fixed_trait_for_expr(expr.id, i);
5302-
}
5303-
ExprBinary(_, BiShr, _, _) | ExprAssignOp(_, BiShr, _, _) => {
5304-
let i = self.lang_items.shr_trait();
5305-
self.add_fixed_trait_for_expr(expr.id, i);
5306-
}
5307-
ExprBinary(_, BiLt, _, _) | ExprBinary(_, BiLe, _, _) |
5308-
ExprBinary(_, BiGe, _, _) | ExprBinary(_, BiGt, _, _) => {
5309-
let i = self.lang_items.ord_trait();
5310-
self.add_fixed_trait_for_expr(expr.id, i);
5311-
}
5312-
ExprBinary(_, BiEq, _, _) | ExprBinary(_, BiNe, _, _) => {
5313-
let i = self.lang_items.eq_trait();
5314-
self.add_fixed_trait_for_expr(expr.id, i);
5315-
}
5316-
ExprUnary(_, UnNeg, _) => {
5317-
let i = self.lang_items.neg_trait();
5318-
self.add_fixed_trait_for_expr(expr.id, i);
5319-
}
5320-
ExprUnary(_, UnNot, _) => {
5321-
let i = self.lang_items.not_trait();
5322-
self.add_fixed_trait_for_expr(expr.id, i);
5323-
}
5324-
ExprIndex(..) => {
5325-
let i = self.lang_items.index_trait();
5326-
self.add_fixed_trait_for_expr(expr.id, i);
5265+
self.trait_map.insert(expr.id, traits);
53275266
}
53285267
_ => {
53295268
// Nothing to do.
@@ -5417,17 +5356,6 @@ impl Resolver {
54175356
found_traits.push(trait_def_id);
54185357
}
54195358

5420-
fn add_fixed_trait_for_expr(&mut self,
5421-
expr_id: NodeId,
5422-
trait_id: Option<DefId>) {
5423-
match trait_id {
5424-
Some(trait_id) => {
5425-
self.trait_map.insert(expr_id, @RefCell::new(~[trait_id]));
5426-
}
5427-
None => {}
5428-
}
5429-
}
5430-
54315359
fn record_def(&mut self, node_id: NodeId, (def, lp): (Def, LastPrivate)) {
54325360
debug!("(recording def) recording {:?} for {:?}, last private {:?}",
54335361
def, node_id, lp);

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

+92-48
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,6 @@ obtained the type `Foo`, we would never match this method.
8181

8282

8383
use middle::subst::Subst;
84-
use middle::resolve;
8584
use middle::ty::*;
8685
use middle::ty;
8786
use middle::typeck::astconv::AstConv;
@@ -134,15 +133,14 @@ pub fn lookup(
134133
check_traits: CheckTraitsFlag, // Whether we check traits only.
135134
autoderef_receiver: AutoderefReceiverFlag)
136135
-> Option<method_origin> {
137-
let impl_dups = @RefCell::new(HashSet::new());
138136
let lcx = LookupContext {
139137
fcx: fcx,
140138
expr: expr,
141139
self_expr: self_expr,
142140
callee_id: callee_id,
143141
m_name: m_name,
144142
supplied_tps: supplied_tps,
145-
impl_dups: impl_dups,
143+
impl_dups: @RefCell::new(HashSet::new()),
146144
inherent_candidates: @RefCell::new(~[]),
147145
extension_candidates: @RefCell::new(~[]),
148146
deref_args: deref_args,
@@ -164,11 +162,50 @@ pub fn lookup(
164162

165163
debug!("searching extension candidates");
166164
lcx.reset_candidates();
167-
lcx.push_bound_candidates(self_ty);
165+
lcx.push_bound_candidates(self_ty, None);
168166
lcx.push_extension_candidates();
169167
return lcx.search(self_ty);
170168
}
171169

170+
pub fn lookup_in_trait(
171+
fcx: @FnCtxt,
172+
173+
// In a call `a.b::<X, Y, ...>(...)`:
174+
expr: &ast::Expr, // The expression `a.b(...)`.
175+
self_expr: &ast::Expr, // The expression `a`.
176+
callee_id: NodeId, /* Where to store `a.b`'s type,
177+
* also the scope of the call */
178+
m_name: ast::Name, // The name `b`.
179+
trait_did: DefId, // The trait to limit the lookup to.
180+
self_ty: ty::t, // The type of `a`.
181+
supplied_tps: &[ty::t], // The list of types X, Y, ... .
182+
autoderef_receiver: AutoderefReceiverFlag)
183+
-> Option<method_origin> {
184+
let lcx = LookupContext {
185+
fcx: fcx,
186+
expr: expr,
187+
self_expr: self_expr,
188+
callee_id: callee_id,
189+
m_name: m_name,
190+
supplied_tps: supplied_tps,
191+
impl_dups: @RefCell::new(HashSet::new()),
192+
inherent_candidates: @RefCell::new(~[]),
193+
extension_candidates: @RefCell::new(~[]),
194+
deref_args: check::DoDerefArgs,
195+
check_traits: CheckTraitsOnly,
196+
autoderef_receiver: autoderef_receiver,
197+
};
198+
199+
let self_ty = structurally_resolved_type(fcx, self_expr.span, self_ty);
200+
debug!("method lookup_in_trait(self_ty={}, expr={}, self_expr={})",
201+
self_ty.repr(fcx.tcx()), expr.repr(fcx.tcx()),
202+
self_expr.repr(fcx.tcx()));
203+
204+
lcx.push_bound_candidates(self_ty, Some(trait_did));
205+
lcx.push_extension_candidate(trait_did);
206+
lcx.search(self_ty)
207+
}
208+
172209
pub struct LookupContext<'a> {
173210
fcx: @FnCtxt,
174211
expr: &'a ast::Expr,
@@ -319,17 +356,17 @@ impl<'a> LookupContext<'a> {
319356
}
320357
}
321358

322-
fn push_bound_candidates(&self, self_ty: ty::t) {
359+
fn push_bound_candidates(&self, self_ty: ty::t, restrict_to: Option<DefId>) {
323360
let mut self_ty = self_ty;
324361
loop {
325362
match get(self_ty).sty {
326363
ty_param(p) => {
327-
self.push_inherent_candidates_from_param(self_ty, p);
364+
self.push_inherent_candidates_from_param(self_ty, restrict_to, p);
328365
}
329366
ty_self(..) => {
330367
// Call is of the form "self.foo()" and appears in one
331368
// of a trait's default method implementations.
332-
self.push_inherent_candidates_from_self(self_ty);
369+
self.push_inherent_candidates_from_self(self_ty, restrict_to);
333370
}
334371
_ => { /* No bound methods in these types */ }
335372
}
@@ -341,32 +378,27 @@ impl<'a> LookupContext<'a> {
341378
}
342379
}
343380

381+
fn push_extension_candidate(&self, trait_did: DefId) {
382+
ty::populate_implementations_for_trait_if_necessary(self.tcx(), trait_did);
383+
384+
// Look for explicit implementations.
385+
let trait_impls = self.tcx().trait_impls.borrow();
386+
for impl_infos in trait_impls.get().find(&trait_did).iter() {
387+
for impl_info in impl_infos.borrow().get().iter() {
388+
self.push_candidates_from_impl(
389+
self.extension_candidates.borrow_mut().get(), *impl_info);
390+
}
391+
}
392+
}
393+
344394
fn push_extension_candidates(&self) {
345395
// If the method being called is associated with a trait, then
346396
// find all the impls of that trait. Each of those are
347397
// candidates.
348-
let trait_map: &resolve::TraitMap = &self.fcx.ccx.trait_map;
349-
let opt_applicable_traits = trait_map.find(&self.expr.id);
350-
for applicable_traits in opt_applicable_traits.iter() {
351-
let applicable_traits = applicable_traits.borrow();
352-
for trait_did in applicable_traits.get().iter() {
353-
ty::populate_implementations_for_trait_if_necessary(
354-
self.tcx(),
355-
*trait_did);
356-
357-
// Look for explicit implementations.
358-
let trait_impls = self.tcx().trait_impls.borrow();
359-
let opt_impl_infos = trait_impls.get().find(trait_did);
360-
for impl_infos in opt_impl_infos.iter() {
361-
let impl_infos = impl_infos.borrow();
362-
for impl_info in impl_infos.get().iter() {
363-
let mut extension_candidates =
364-
self.extension_candidates.borrow_mut();
365-
self.push_candidates_from_impl(
366-
extension_candidates.get(), *impl_info);
367-
368-
}
369-
}
398+
let opt_applicable_traits = self.fcx.ccx.trait_map.find(&self.expr.id);
399+
for applicable_traits in opt_applicable_traits.move_iter() {
400+
for trait_did in applicable_traits.iter() {
401+
self.push_extension_candidate(*trait_did);
370402
}
371403
}
372404
}
@@ -428,7 +460,7 @@ impl<'a> LookupContext<'a> {
428460
self.construct_transformed_self_ty_for_object(
429461
did, &rcvr_substs, &m);
430462

431-
Candidate {
463+
Some(Candidate {
432464
rcvr_match_condition: RcvrMatchesIfObject(did),
433465
rcvr_substs: new_trait_ref.substs.clone(),
434466
method_ty: @m,
@@ -438,49 +470,61 @@ impl<'a> LookupContext<'a> {
438470
method_num: method_num,
439471
real_index: vtable_index
440472
})
441-
}
473+
})
442474
});
443475
}
444476

445477
fn push_inherent_candidates_from_param(&self,
446478
rcvr_ty: ty::t,
479+
restrict_to: Option<DefId>,
447480
param_ty: param_ty) {
448481
debug!("push_inherent_candidates_from_param(param_ty={:?})",
449482
param_ty);
450483
self.push_inherent_candidates_from_bounds(
451484
rcvr_ty,
452485
self.fcx.inh.param_env.type_param_bounds[param_ty.idx].trait_bounds,
486+
restrict_to,
453487
param_numbered(param_ty.idx));
454488
}
455489

456490

457491
fn push_inherent_candidates_from_self(&self,
458-
rcvr_ty: ty::t) {
492+
rcvr_ty: ty::t,
493+
restrict_to: Option<DefId>) {
459494
debug!("push_inherent_candidates_from_self()");
460495
self.push_inherent_candidates_from_bounds(
461496
rcvr_ty,
462497
[self.fcx.inh.param_env.self_param_bound.unwrap()],
498+
restrict_to,
463499
param_self)
464500
}
465501

466502
fn push_inherent_candidates_from_bounds(&self,
467503
self_ty: ty::t,
468504
bounds: &[@TraitRef],
505+
restrict_to: Option<DefId>,
469506
param: param_index) {
470507
self.push_inherent_candidates_from_bounds_inner(bounds,
471508
|trait_ref, m, method_num, bound_num| {
472-
Candidate {
473-
rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
474-
rcvr_substs: trait_ref.substs.clone(),
475-
method_ty: m,
476-
origin: method_param(
477-
method_param {
509+
match restrict_to {
510+
Some(trait_did) => {
511+
if trait_did != trait_ref.def_id {
512+
return None;
513+
}
514+
}
515+
_ => {}
516+
}
517+
Some(Candidate {
518+
rcvr_match_condition: RcvrMatchesIfSubtype(self_ty),
519+
rcvr_substs: trait_ref.substs.clone(),
520+
method_ty: m,
521+
origin: method_param(method_param {
478522
trait_id: trait_ref.def_id,
479523
method_num: method_num,
480524
param_num: param,
481525
bound_num: bound_num,
482526
})
483-
}
527+
})
484528
})
485529
}
486530

@@ -492,7 +536,7 @@ impl<'a> LookupContext<'a> {
492536
m: @ty::Method,
493537
method_num: uint,
494538
bound_num: uint|
495-
-> Candidate) {
539+
-> Option<Candidate>) {
496540
let tcx = self.tcx();
497541
let mut next_bound_idx = 0; // count only trait bounds
498542

@@ -508,17 +552,17 @@ impl<'a> LookupContext<'a> {
508552
Some(pos) => {
509553
let method = trait_methods[pos];
510554

511-
let cand = mk_cand(bound_trait_ref, method,
512-
pos, this_bound_idx);
513-
514-
debug!("pushing inherent candidate for param: {:?}", cand);
515-
let mut inherent_candidates = self.inherent_candidates
516-
.borrow_mut();
517-
inherent_candidates.get().push(cand);
555+
match mk_cand(bound_trait_ref, method, pos, this_bound_idx) {
556+
Some(cand) => {
557+
debug!("pushing inherent candidate for param: {:?}", cand);
558+
self.inherent_candidates.borrow_mut().get().push(cand);
559+
}
560+
None => {}
561+
}
518562
}
519563
None => {
520564
debug!("trait doesn't contain method: {:?}",
521-
bound_trait_ref.def_id);
565+
bound_trait_ref.def_id);
522566
// check next trait or bound
523567
}
524568
}

0 commit comments

Comments
 (0)