Skip to content

Commit

Permalink
In typeck, don't assume traits with default methods are in the same c…
Browse files Browse the repository at this point in the history
…rate

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
  • Loading branch information
catamorphism committed Sep 7, 2012
1 parent cd3cc6d commit c6b5154
Show file tree
Hide file tree
Showing 3 changed files with 38 additions and 23 deletions.
19 changes: 19 additions & 0 deletions src/rustc/middle/ty.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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.
Expand Down
35 changes: 12 additions & 23 deletions src/rustc/middle/typeck/collect.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 7 additions & 0 deletions src/test/compile-fail/issue-3344.rs
Original file line number Diff line number Diff line change
@@ -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() {}

0 comments on commit c6b5154

Please sign in to comment.