Change method lookup infrastructure to use the trait methods. Instead

of tracking individual candidates per impl, we just track one
candidate for the extension trait itself, and let the trait resolution
handle walking the individual impls and so forth. Also change the
interface to report back a richer notion of error.
This commit is contained in:
Niko Matsakis 2014-10-17 09:07:45 -04:00
parent 1562d8cbd8
commit dad2db7c83
4 changed files with 641 additions and 662 deletions

View File

@ -120,6 +120,13 @@ impl ImplOrTraitItem {
TypeTraitItem(ref associated_type) => associated_type.container,
}
}
pub fn as_opt_method(&self) -> Option<Rc<Method>> {
match *self {
MethodTraitItem(ref m) => Some((*m).clone()),
TypeTraitItem(_) => None
}
}
}
#[deriving(Clone)]
@ -1240,6 +1247,10 @@ impl Generics {
}
impl TraitRef {
pub fn new(def_id: ast::DefId, substs: Substs) -> TraitRef {
TraitRef { def_id: def_id, substs: substs }
}
pub fn self_ty(&self) -> ty::t {
self.substs.self_ty().unwrap()
}

File diff suppressed because it is too large Load Diff

View File

@ -77,6 +77,7 @@ type parameter).
*/
use driver::session::Session;
use middle::const_eval;
use middle::def;
use middle::lang_items::IteratorItem;
@ -2924,46 +2925,24 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
fcx.expr_ty(&*rcvr));
let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
let fn_ty = match method::lookup(fcx, expr, &*rcvr,
let fn_ty = match method::lookup(fcx,
expr,
&*rcvr,
method_name.node.name,
expr_t, tps.as_slice(),
expr_t,
tps.as_slice(),
DontDerefArgs,
CheckTraitsAndInherentMethods,
AutoderefReceiver, IgnoreStaticMethods) {
Some(method) => {
AutoderefReceiver) {
Ok(method) => {
let method_ty = method.ty;
let method_call = MethodCall::expr(expr.id);
fcx.inh.method_map.borrow_mut().insert(method_call, method);
method_ty
}
None => {
debug!("(checking method call) failing expr is {}", expr.id);
fcx.type_error_message(method_name.span,
|actual| {
format!("type `{}` does not implement any \
method in scope named `{}`",
actual,
token::get_ident(method_name.node))
},
expr_t,
None);
// Add error type for the result
Err(error) => {
method::report_error(fcx, method_name.span, expr_t, method_name.node.name, error);
fcx.write_error(expr.id);
// Check for potential static matches (missing self parameters)
method::lookup(fcx,
expr,
&*rcvr,
method_name.node.name,
expr_t,
tps.as_slice(),
DontDerefArgs,
CheckTraitsAndInherentMethods,
DontAutoderefReceiver,
ReportStaticMethods);
ty::mk_err()
}
};
@ -3466,9 +3445,8 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
tps.as_slice(),
DontDerefArgs,
CheckTraitsAndInherentMethods,
AutoderefReceiver,
IgnoreStaticMethods) {
Some(_) => {
AutoderefReceiver) {
Ok(_) => {
fcx.type_error_message(
field.span,
|actual| {
@ -3481,7 +3459,7 @@ fn check_expr_with_unifier(fcx: &FnCtxt,
"maybe a missing `()` to call it? If not, try an anonymous function.");
}
None => {
Err(_) => {
fcx.type_error_message(
expr.span,
|actual| {

View File

@ -536,6 +536,14 @@ impl<'ast> Map<'ast> {
.unwrap_or_else(|| fail!("AstMap.span: could not find span for id {}", id))
}
pub fn def_id_span(&self, def_id: DefId, fallback: Span) -> Span {
if def_id.krate == LOCAL_CRATE {
self.span(def_id.node)
} else {
fallback
}
}
pub fn node_to_string(&self, id: NodeId) -> String {
node_id_to_string(self, id)
}