Skip to content

Commit c6b5154

Browse files
committed
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
1 parent cd3cc6d commit c6b5154

File tree

3 files changed

+38
-23
lines changed

3 files changed

+38
-23
lines changed

src/rustc/middle/ty.rs

+19
Original file line numberDiff line numberDiff line change
@@ -190,6 +190,7 @@ export serialize_region_variance, deserialize_region_variance;
190190
export opt_region_variance;
191191
export serialize_opt_region_variance, deserialize_opt_region_variance;
192192
export determine_inherited_purity;
193+
export provided_trait_methods;
193194

194195
// Data types
195196

@@ -3069,6 +3070,24 @@ fn store_trait_methods(cx: ctxt, id: ast::node_id, ms: @~[method]) {
30693070
cx.trait_method_cache.insert(ast_util::local_def(id), ms);
30703071
}
30713072

3073+
fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@ast::method] {
3074+
if is_local(id) {
3075+
match cx.items.find(id.node) {
3076+
Some(ast_map::node_item(@{node: item_trait(_, _, ms),_}, _)) =>
3077+
match ast_util::split_trait_methods(ms) {
3078+
(_, p) => p
3079+
},
3080+
_ => cx.sess.bug(#fmt("provided_trait_methods: %? is not a trait",
3081+
id))
3082+
}
3083+
}
3084+
else {
3085+
// FIXME #2794: default methods for traits don't work cross-crate
3086+
~[]
3087+
}
3088+
}
3089+
3090+
30723091
fn trait_methods(cx: ctxt, id: ast::def_id) -> @~[method] {
30733092
match cx.trait_method_cache.find(id) {
30743093
// Local traits are supposed to have been added explicitly.

src/rustc/middle/typeck/collect.rs

+12-23
Original file line numberDiff line numberDiff line change
@@ -343,33 +343,22 @@ fn check_methods_against_trait(ccx: @crate_ctxt,
343343
// implementation in the trait itself. If not, raise a
344344
// "missing method" error.
345345

346-
match tcx.items.get(did.node) {
347-
ast_map::node_item(
348-
@{node: ast::item_trait(_, _, trait_methods), _}, _) => {
349-
let (_, provided_methods) =
350-
split_trait_methods(trait_methods);
351-
352-
match vec::find(provided_methods, |provided_method|
353-
provided_method.ident == trait_m.ident) {
354-
Some(_) => {
355-
// If there's a provided method with the name we
356-
// want, then we're fine; nothing else to do.
357-
}
358-
None => {
359-
tcx.sess.span_err(
360-
a_trait_ty.path.span,
361-
fmt!("missing method `%s`",
362-
tcx.sess.str_of(trait_m.ident)));
363-
}
364-
}
346+
let provided_methods = ty::provided_trait_methods(tcx, did);
347+
match vec::find(provided_methods, |provided_method|
348+
provided_method.ident == trait_m.ident) {
349+
Some(_) => {
350+
// If there's a provided method with the name we
351+
// want, then we're fine; nothing else to do.
365352
}
366-
_ => {
367-
tcx.sess.bug(~"check_methods_against_trait(): trait_ref \
368-
didn't refer to a trait");
353+
None => {
354+
tcx.sess.span_err(
355+
a_trait_ty.path.span,
356+
fmt!("missing method `%s`",
357+
tcx.sess.str_of(trait_m.ident)));
369358
}
370359
}
371360
}
372-
} // alt
361+
} // match
373362
} // |trait_m|
374363
} // fn
375364

src/test/compile-fail/issue-3344.rs

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

0 commit comments

Comments
 (0)