diff options
Diffstat (limited to 'src/rustc')
| -rw-r--r-- | src/rustc/middle/typeck/collect.rs | 34 | ||||
| -rw-r--r-- | src/rustc/util/common.rs | 5 | ||||
| -rw-r--r-- | src/rustc/util/ppaux.rs | 14 |
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 { |
