about summary refs log tree commit diff
path: root/src/rustc
diff options
context:
space:
mode:
Diffstat (limited to 'src/rustc')
-rw-r--r--src/rustc/middle/typeck/collect.rs34
-rw-r--r--src/rustc/util/common.rs5
-rw-r--r--src/rustc/util/ppaux.rs14
3 files changed, 49 insertions, 4 deletions
diff --git a/src/rustc/middle/typeck/collect.rs b/src/rustc/middle/typeck/collect.rs
index 43d6cf14d93..3206d1709c5 100644
--- a/src/rustc/middle/typeck/collect.rs
+++ b/src/rustc/middle/typeck/collect.rs
@@ -24,6 +24,8 @@ use astconv::{ast_conv, ty_of_fn_decl, ty_of_arg, ast_ty_to_ty};
 use ast_util::trait_method_to_ty_method;
 use rscope::*;
 use ty::{FnTyBase, FnMeta, FnSig};
+use util::common::pluralize;
+use util::ppaux::bound_to_str;
 
 fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
 
@@ -263,9 +265,13 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
                           self type", tcx.sess.str_of(impl_m.ident)));
     }
 
-    if impl_m.tps != trait_m.tps {
-        tcx.sess.span_err(sp, ~"method `" + tcx.sess.str_of(trait_m.ident) +
-                          ~"` has an incompatible set of type parameters");
+    if impl_m.tps.len() != trait_m.tps.len() {
+        tcx.sess.span_err(sp, #fmt("method `%s` \
+           has %u type %s, but its trait declaration has %u type %s",
+           tcx.sess.str_of(trait_m.ident), impl_m.tps.len(),
+           pluralize(impl_m.tps.len(), ~"parameter"),
+           trait_m.tps.len(),
+           pluralize(trait_m.tps.len(), ~"parameter")));
         return;
     }
 
@@ -278,6 +284,28 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
         return;
     }
 
+    for trait_m.tps.eachi() |i, trait_param_bounds| {
+        // For each of the corresponding impl ty param's bounds...
+        let impl_param_bounds = impl_m.tps[i];
+        // Make sure the bounds lists have the same length
+        // Would be nice to use the ty param names in the error message,
+        // but we don't have easy access to them here
+        if impl_param_bounds.len() != trait_param_bounds.len() {
+           tcx.sess.span_err(sp, #fmt("in method `%s`, \
+             type parameter %u has %u %s, but the same type \
+             parameter in its trait declaration has %u %s",
+             tcx.sess.str_of(trait_m.ident),
+             i, impl_param_bounds.len(),
+             pluralize(impl_param_bounds.len(), ~"bound"),
+             trait_param_bounds.len(),
+             pluralize(trait_param_bounds.len(), ~"bound")));
+           return;
+        }
+        // tjc: I'm mildly worried that there's something I'm
+        // not checking that require_same_types doesn't catch,
+        // but I can't figure out what.
+    }
+
     // Perform substitutions so that the trait/impl methods are expressed
     // in terms of the same set of type/region parameters:
     // - replace trait type parameters with those from `trait_substs`
diff --git a/src/rustc/util/common.rs b/src/rustc/util/common.rs
index ee941c0ed01..901d5d504eb 100644
--- a/src/rustc/util/common.rs
+++ b/src/rustc/util/common.rs
@@ -94,6 +94,11 @@ fn is_main_name(path: syntax::ast_map::path) -> bool {
     )
 }
 
+fn pluralize(n: uint, s: ~str) -> ~str {
+    if n == 1 { s }
+    else { str::concat([s, ~"s"]) }
+}
+
 //
 // Local Variables:
 // mode: rust
diff --git a/src/rustc/util/ppaux.rs b/src/rustc/util/ppaux.rs
index f78495ef198..3a27a521985 100644
--- a/src/rustc/util/ppaux.rs
+++ b/src/rustc/util/ppaux.rs
@@ -1,9 +1,11 @@
 use std::map::hashmap;
 use middle::ty;
 use middle::ty::{arg, canon_mode};
+use middle::ty::{bound_copy, bound_const, bound_owned, bound_send,
+        bound_trait};
 use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
 use middle::ty::{ck_block, ck_box, ck_uniq, ctxt, field, method};
-use middle::ty::{mt, t};
+use middle::ty::{mt, t, param_bound};
 use middle::ty::{re_bound, re_free, re_scope, re_var, re_static, region};
 use middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_enum};
 use middle::ty::{ty_estr, ty_evec, ty_float, ty_fn, ty_trait, ty_int};
@@ -233,6 +235,16 @@ fn tys_to_str(cx: ctxt, ts: ~[t]) -> ~str {
     rs
 }
 
+fn bound_to_str(cx: ctxt, b: param_bound) -> ~str {
+    match b {
+      bound_copy     => ~"copy",
+      bound_owned    => ~"owned",
+      bound_send     => ~"send",
+      bound_const    => ~"const",
+      bound_trait(t) => ty_to_str(cx, t)
+    }
+}
+
 fn ty_to_str(cx: ctxt, typ: t) -> ~str {
     fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) ->
        ~str {