forked from rust-lang/rust
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Handle supertrait calls in default methods
Add a new method_super origin for supertrait methods. Also make coherence create a table that maps pairs of trait IDs and self types to impl IDs, so that it's possible to check a supertrait method knowing only its index in its trait's methods (without knowing all supertraits for a given trait). As per rust-lang#3979
- Loading branch information
1 parent
e5bf6d1
commit d78265a
Showing
15 changed files
with
358 additions
and
77 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -93,7 +93,7 @@ use middle::typeck::check; | |
use middle::typeck::coherence::get_base_type_def_id; | ||
use middle::typeck::infer; | ||
use middle::typeck::{method_map_entry, method_origin, method_param}; | ||
use middle::typeck::{method_self, method_static, method_trait}; | ||
use middle::typeck::{method_self, method_static, method_trait, method_super}; | ||
use util::common::indenter; | ||
use util::ppaux::expr_repr; | ||
|
||
|
@@ -529,30 +529,66 @@ impl LookupContext { | |
did: def_id, | ||
substs: &ty::substs) { | ||
let tcx = self.tcx(); | ||
let methods = ty::trait_methods(tcx, did); // XXX: Inherited methods. | ||
let index; | ||
// First, try self methods | ||
let mut method = None; | ||
let methods = ty::trait_methods(tcx, did); | ||
let mut index = None; | ||
let mut trait_did = None; | ||
This comment has been minimized.
Sorry, something went wrong.
nikomatsakis
|
||
match vec::position(*methods, |m| m.ident == self.m_name) { | ||
Some(i) => index = i, | ||
None => return | ||
Some(i) => { | ||
index = Some(i); | ||
trait_did = Some(did); | ||
method = Some((methods[i].self_ty, methods[i].tps.len())); | ||
} | ||
None => () | ||
} | ||
let method = &methods[index]; | ||
|
||
let rcvr_substs = { self_ty: Some(self_ty), ../*bad*/copy *substs }; | ||
let (rcvr_ty, rcvr_substs) = | ||
self.create_rcvr_ty_and_substs_for_method( | ||
method.self_ty, | ||
self_ty, | ||
move rcvr_substs, | ||
TransformTypeNormally); | ||
// No method found yet? Check each supertrait | ||
if method.is_none() { | ||
for ty::trait_supertraits(tcx, did).each() |trait_ref| { | ||
This comment has been minimized.
Sorry, something went wrong.
nikomatsakis
|
||
let supertrait_methods = | ||
ty::trait_methods(tcx, trait_ref.def_id); | ||
match vec::position(*supertrait_methods, | ||
|m| m.ident == self.m_name) { | ||
Some(i) => { | ||
index = Some(i); | ||
trait_did = Some(trait_ref.def_id); | ||
method = Some((supertrait_methods[i].self_ty, | ||
supertrait_methods[i].tps.len())); | ||
break; | ||
} | ||
None => () | ||
} | ||
} | ||
} | ||
match (method, index, trait_did) { | ||
(Some((method_self_ty, method_num_tps)), | ||
Some(index), Some(trait_did)) => { | ||
|
||
self.inherent_candidates.push(Candidate { | ||
rcvr_ty: rcvr_ty, | ||
rcvr_substs: move rcvr_substs, | ||
explicit_self: method.self_ty, | ||
num_method_tps: method.tps.len(), | ||
self_mode: get_mode_from_self_type(method.self_ty), | ||
origin: method_self(did, index) | ||
}); | ||
// We've found a method -- return it | ||
let rcvr_substs = { self_ty: Some(self_ty), ..copy *substs }; | ||
This comment has been minimized.
Sorry, something went wrong.
nikomatsakis
|
||
let (rcvr_ty, rcvr_substs) = | ||
self.create_rcvr_ty_and_substs_for_method( | ||
method_self_ty, | ||
self_ty, | ||
move rcvr_substs, | ||
TransformTypeNormally); | ||
let origin = if trait_did == did { | ||
method_self(trait_did, index) | ||
} | ||
else { | ||
method_super(trait_did, index) | ||
}; | ||
self.inherent_candidates.push(Candidate { | ||
rcvr_ty: rcvr_ty, | ||
rcvr_substs: move rcvr_substs, | ||
explicit_self: method_self_ty, | ||
num_method_tps: method_num_tps, | ||
self_mode: get_mode_from_self_type(method_self_ty), | ||
origin: origin | ||
}); | ||
} | ||
_ => return | ||
} | ||
} | ||
|
||
fn push_inherent_impl_candidates_for_type(did: def_id) { | ||
|
@@ -1034,7 +1070,8 @@ impl LookupContext { | |
* vtable and hence cannot be monomorphized. */ | ||
|
||
match candidate.origin { | ||
method_static(*) | method_param(*) | method_self(*) => { | ||
method_static(*) | method_param(*) | | ||
method_self(*) | method_super(*) => { | ||
return; // not a call to a trait instance | ||
} | ||
method_trait(*) => {} | ||
|
@@ -1058,7 +1095,8 @@ impl LookupContext { | |
// No code can call the finalize method explicitly. | ||
let bad; | ||
match candidate.origin { | ||
method_static(method_id) | method_self(method_id, _) => { | ||
method_static(method_id) | method_self(method_id, _) | ||
| method_super(method_id, _) => { | ||
bad = self.tcx().destructors.contains_key(method_id); | ||
} | ||
method_param(method_param { trait_id: trait_id, _ }) | | ||
|
@@ -1088,7 +1126,8 @@ impl LookupContext { | |
method_param(ref mp) => { | ||
type_of_trait_method(self.tcx(), mp.trait_id, mp.method_num) | ||
} | ||
method_trait(did, idx, _) | method_self(did, idx) => { | ||
method_trait(did, idx, _) | method_self(did, idx) | | ||
method_super(did, idx) => { | ||
type_of_trait_method(self.tcx(), did, idx) | ||
} | ||
}; | ||
|
@@ -1109,7 +1148,8 @@ impl LookupContext { | |
method_param(ref mp) => { | ||
self.report_param_candidate(idx, (*mp).trait_id) | ||
} | ||
method_trait(trait_did, _, _) | method_self(trait_did, _) => { | ||
method_trait(trait_did, _, _) | method_self(trait_did, _) | ||
| method_super(trait_did, _) => { | ||
self.report_param_candidate(idx, trait_did) | ||
} | ||
} | ||
|
Oops, something went wrong.
Nit: I find this style of densely packing in comments and code really hard to read. This is a personal thing so do as you feel, but I would prefer this code to be formatted as so: