In typeck, don't assume traits with default methods are in the same crate

But note that default methods still don't work cross-crate (see #2794) --
this just makes it so that when a method is missing in a cross-crate impl,
the right error message gets printed.

Closes #3344
This commit is contained in:
Tim Chevalier 2012-09-06 17:44:42 -07:00
parent cd3cc6d17b
commit c6b51547c1
3 changed files with 38 additions and 23 deletions

View File

@ -190,6 +190,7 @@ export serialize_region_variance, deserialize_region_variance;
export opt_region_variance;
export serialize_opt_region_variance, deserialize_opt_region_variance;
export determine_inherited_purity;
export provided_trait_methods;
// Data types
@ -3069,6 +3070,24 @@ fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
cx.trait_method_cache.insert(ast_util::local_def(id), ms);
}
fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@ast::method] {
if is_local(id) {
match cx.items.find(id.node) {
Some(ast_map::node_item(@{node: item_trait(_, _, ms),_}, _)) =>
match ast_util::split_trait_methods(ms) {
(_, p) => p
},
_ => cx.sess.bug(#fmt("provided_trait_methods: %? is not a trait",
id))
}
}
else {
// FIXME #2794: default methods for traits don't work cross-crate
~[]
}
}
fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
match cx.trait_method_cache.find(id) {
// Local traits are supposed to have been added explicitly.

View File

@ -343,33 +343,22 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
// implementation in the trait itself. If not, raise a
// "missing method" error.
match tcx.items.get(did.node) {
ast_map::node_item(
@{node: ast::item_trait(_, _, trait_methods), _}, _) => {
let (_, provided_methods) =
split_trait_methods(trait_methods);
match vec::find(provided_methods, |provided_method|
provided_method.ident == trait_m.ident) {
Some(_) => {
// If there's a provided method with the name we
// want, then we're fine; nothing else to do.
}
None => {
tcx.sess.span_err(
a_trait_ty.path.span,
fmt!("missing method `%s`",
tcx.sess.str_of(trait_m.ident)));
}
}
let provided_methods = ty::provided_trait_methods(tcx, did);
match vec::find(provided_methods, |provided_method|
provided_method.ident == trait_m.ident) {
Some(_) => {
// If there's a provided method with the name we
// want, then we're fine; nothing else to do.
}
_ => {
tcx.sess.bug(~"check_methods_against_trait(): trait_ref \
didn't refer to a trait");
None => {
tcx.sess.span_err(
a_trait_ty.path.span,
fmt!("missing method `%s`",
tcx.sess.str_of(trait_m.ident)));
}
}
}
} // alt
} // match
} // |trait_m|
} // fn

View File

@ -0,0 +1,7 @@
enum thing = uint;
impl thing : cmp::Ord { //~ ERROR missing method `gt`
pure fn lt(&&other: thing) -> bool { *self < *other }
pure fn le(&&other: thing) -> bool { *self < *other }
pure fn ge(&&other: thing) -> bool { *self < *other }
}
fn main() {}