Skip to content

Commit 0b3cf16

Browse files
committed
---
yaml --- r: 28366 b: refs/heads/try c: ac1f84c h: refs/heads/master v: v3
1 parent 73f85d7 commit 0b3cf16

File tree

8 files changed

+116
-10
lines changed

8 files changed

+116
-10
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
refs/heads/master: cd6f24f9d14ac90d167386a56e7a6ac1f0318195
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: cd6f24f9d14ac90d167386a56e7a6ac1f0318195
5-
refs/heads/try: c6b51547c14780a0473a5bcae90c8d4b0530b7c8
5+
refs/heads/try: ac1f84c153a171e641233e5d2d11404a0b520986
66
refs/tags/release-0.1: 1f5c5126e96c79d22cb7862f75304136e204f105
77
refs/heads/ndm: f3868061cd7988080c30d6d5bf352a5a5fe2460b
88
refs/heads/try2: d0c6ce338884ee21843f4b40bf6bf18d222ce5df

branches/try/src/rustc/middle/typeck/collect.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ use astconv::{ast_conv, ty_of_fn_decl, ty_of_arg, ast_ty_to_ty};
2424
use ast_util::trait_method_to_ty_method;
2525
use rscope::*;
2626
use ty::{FnTyBase, FnMeta, FnSig};
27+
use util::common::pluralize;
28+
use util::ppaux::bound_to_str;
2729

2830
fn collect_item_types(ccx: @crate_ctxt, crate: @ast::crate) {
2931

@@ -263,9 +265,13 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
263265
self type", tcx.sess.str_of(impl_m.ident)));
264266
}
265267

266-
if impl_m.tps != trait_m.tps {
267-
tcx.sess.span_err(sp, ~"method `" + tcx.sess.str_of(trait_m.ident) +
268-
~"` has an incompatible set of type parameters");
268+
if impl_m.tps.len() != trait_m.tps.len() {
269+
tcx.sess.span_err(sp, #fmt("method `%s` \
270+
has %u type %s, but its trait declaration has %u type %s",
271+
tcx.sess.str_of(trait_m.ident), impl_m.tps.len(),
272+
pluralize(impl_m.tps.len(), ~"parameter"),
273+
trait_m.tps.len(),
274+
pluralize(trait_m.tps.len(), ~"parameter")));
269275
return;
270276
}
271277

@@ -278,6 +284,28 @@ fn compare_impl_method(tcx: ty::ctxt, sp: span,
278284
return;
279285
}
280286

287+
for trait_m.tps.eachi() |i, trait_param_bounds| {
288+
// For each of the corresponding impl ty param's bounds...
289+
let impl_param_bounds = impl_m.tps[i];
290+
// Make sure the bounds lists have the same length
291+
// Would be nice to use the ty param names in the error message,
292+
// but we don't have easy access to them here
293+
if impl_param_bounds.len() != trait_param_bounds.len() {
294+
tcx.sess.span_err(sp, #fmt("in method `%s`, \
295+
type parameter %u has %u %s, but the same type \
296+
parameter in its trait declaration has %u %s",
297+
tcx.sess.str_of(trait_m.ident),
298+
i, impl_param_bounds.len(),
299+
pluralize(impl_param_bounds.len(), ~"bound"),
300+
trait_param_bounds.len(),
301+
pluralize(trait_param_bounds.len(), ~"bound")));
302+
return;
303+
}
304+
// tjc: I'm mildly worried that there's something I'm
305+
// not checking that require_same_types doesn't catch,
306+
// but I can't figure out what.
307+
}
308+
281309
// Perform substitutions so that the trait/impl methods are expressed
282310
// in terms of the same set of type/region parameters:
283311
// - replace trait type parameters with those from `trait_substs`

branches/try/src/rustc/util/common.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ fn is_main_name(path: syntax::ast_map::path) -> bool {
9494
)
9595
}
9696

97+
fn pluralize(n: uint, s: ~str) -> ~str {
98+
if n == 1 { s }
99+
else { str::concat([s, ~"s"]) }
100+
}
101+
97102
//
98103
// Local Variables:
99104
// mode: rust

branches/try/src/rustc/util/ppaux.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
use std::map::hashmap;
22
use middle::ty;
33
use middle::ty::{arg, canon_mode};
4+
use middle::ty::{bound_copy, bound_const, bound_owned, bound_send,
5+
bound_trait};
46
use middle::ty::{bound_region, br_anon, br_named, br_self, br_cap_avoid};
57
use middle::ty::{ck_block, ck_box, ck_uniq, ctxt, field, method};
6-
use middle::ty::{mt, t};
8+
use middle::ty::{mt, t, param_bound};
79
use middle::ty::{re_bound, re_free, re_scope, re_var, re_static, region};
810
use middle::ty::{ty_bool, ty_bot, ty_box, ty_class, ty_enum};
911
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 {
233235
rs
234236
}
235237

238+
fn bound_to_str(cx: ctxt, b: param_bound) -> ~str {
239+
match b {
240+
bound_copy => ~"copy",
241+
bound_owned => ~"owned",
242+
bound_send => ~"send",
243+
bound_const => ~"const",
244+
bound_trait(t) => ty_to_str(cx, t)
245+
}
246+
}
247+
236248
fn ty_to_str(cx: ctxt, typ: t) -> ~str {
237249
fn fn_input_to_str(cx: ctxt, input: {mode: ast::mode, ty: t}) ->
238250
~str {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
// Tests that impl methods are matched to traits exactly:
2+
// we might be tempted to think matching is contravariant, but if
3+
// we let an impl method can have more permissive bounds than the trait
4+
// method it's implementing, the return type might be less specific than
5+
// needed. Just punt and make it invariant.
6+
import iter;
7+
import iter::BaseIter;
8+
9+
trait A {
10+
fn b<C:copy const, D>(x: C) -> C;
11+
}
12+
13+
struct E {
14+
f: int;
15+
}
16+
17+
impl E: A {
18+
fn b<F:copy, G>(_x: F) -> F { fail } //~ ERROR in method `b`, type parameter 0 has 1 bound, but
19+
}
20+
21+
fn main() {}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// Tests that an impl method's bounds aren't *more* restrictive
2+
// than the trait method it's implementing
3+
import iter;
4+
import iter::BaseIter;
5+
6+
trait A {
7+
fn b<C:copy, D>(x: C) -> C;
8+
}
9+
10+
struct E {
11+
f: int;
12+
}
13+
14+
impl E: A {
15+
fn b<F:copy const, G>(_x: F) -> F { fail } //~ ERROR in method `b`, type parameter 0 has 2 bounds, but
16+
}
17+
18+
fn main() {}
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
// Tests that ty params get matched correctly when comparing
2+
// an impl against a trait
3+
import iter;
4+
import iter::BaseIter;
5+
6+
trait A {
7+
fn b<C:copy, D>(x: C) -> C;
8+
}
9+
10+
struct E {
11+
f: int;
12+
}
13+
14+
impl E: A {
15+
// n.b. The error message is awful -- see #3404
16+
fn b<F:copy, G>(_x: G) -> G { fail } //~ ERROR method `b` has an incompatible type
17+
}
18+
19+
fn main() {}

branches/try/src/test/run-pass/issue-2611.rs

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
1-
// xfail-test
2-
use iter::base_iter;
1+
use iter::BaseIter;
32

4-
impl Q<A> for base_iter<A> {
5-
fn flat_map_to_vec<B:copy, IB:base_iter<B>>(op: fn(B) -> IB) -> ~[B] {
6-
iter::flat_map_to_vec(self, op)
3+
trait FlatMapToVec<A> {
4+
fn flat_map_to_vec<B:copy, IB:BaseIter<B>>(op: fn(A) -> IB) -> ~[B];
5+
}
6+
7+
impl<A:copy> BaseIter<A>: FlatMapToVec<A> {
8+
fn flat_map_to_vec<B:copy, IB:BaseIter<B>>(op: fn(A) -> IB) -> ~[B] {
9+
iter::flat_map_to_vec(self, op)
710
}
811
}
912

0 commit comments

Comments
 (0)