From c6b51547c14780a0473a5bcae90c8d4b0530b7c8 Mon Sep 17 00:00:00 2001 From: Tim Chevalier Date: Thu, 6 Sep 2012 17:44:42 -0700 Subject: [PATCH] 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 --- src/rustc/middle/ty.rs | 19 ++++++++++++++++ src/rustc/middle/typeck/collect.rs | 35 ++++++++++------------------- src/test/compile-fail/issue-3344.rs | 7 ++++++ 3 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 src/test/compile-fail/issue-3344.rs diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index f95997c93e95b..dd48c2183a7d7 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -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. diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs index 3b25e41d313ce..43d6cf14d9380 100644 --- a/src/rustc/middle/typeck/collect.rs +++ b/src/rustc/middle/typeck/collect.rs @@ -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 diff --git a/src/test/compile-fail/issue-3344.rs b/src/test/compile-fail/issue-3344.rs new file mode 100644 index 0000000000000..a9fa659398639 --- /dev/null +++ b/src/test/compile-fail/issue-3344.rs @@ -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() {}