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:
parent
cd3cc6d17b
commit
c6b51547c1
@ -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.
|
||||
|
@ -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
|
||||
|
||||
|
7
src/test/compile-fail/issue-3344.rs
Normal file
7
src/test/compile-fail/issue-3344.rs
Normal 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() {}
|
Loading…
Reference in New Issue
Block a user