Skip to content

Commit 120a520

Browse files
committed
Reject all uses of non-typaram bounds
1 parent 9e4e524 commit 120a520

File tree

2 files changed

+57
-19
lines changed

2 files changed

+57
-19
lines changed

Diff for: src/librustc_typeck/check/wf.rs

+47-11
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
7777
enum_variants(fcx, enum_def)
7878
});
7979
}
80+
ast::ItemTrait(..) => {
81+
let trait_def =
82+
ty::lookup_trait_def(ccx.tcx, local_def(item.id));
83+
reject_non_type_param_bounds(
84+
ccx.tcx,
85+
item.span,
86+
&trait_def.generics);
87+
}
8088
_ => {}
8189
}
8290
}
@@ -237,21 +245,32 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
237245
fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
238246
span: Span,
239247
generics: &ty::Generics<'tcx>) {
248+
240249
for predicate in generics.predicates.iter() {
241250
match predicate {
242251
&ty::Predicate::Trait(ty::Binder(ref tr)) => {
243-
let self_ty = tr.self_ty();
244-
if !self_ty.walk().any(|t| is_ty_param(t)) {
245-
tcx.sess.span_err(
246-
span,
247-
format!("cannot bound type `{}`, where clause \
248-
bounds may only be attached to types involving \
249-
type parameters",
250-
self_ty.repr(tcx)).as_slice())
251-
}
252+
let found_param = tr.input_types().iter()
253+
.flat_map(|ty| ty.walk())
254+
.any(is_ty_param);
255+
if !found_param { report_bound_error(tcx, span, tr.self_ty() )}
256+
}
257+
&ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(ty, _))) => {
258+
let found_param = ty.walk().any(|t| is_ty_param(t));
259+
if !found_param { report_bound_error(tcx, span, ty) }
252260
}
253261
_ => {}
254-
}
262+
};
263+
}
264+
265+
fn report_bound_error<'t>(tcx: &ty::ctxt<'t>,
266+
span: Span,
267+
bounded_ty: ty::Ty<'t>) {
268+
tcx.sess.span_err(
269+
span,
270+
format!("cannot bound type `{}`, where clause \
271+
bounds may only be attached to types involving \
272+
type parameters",
273+
bounded_ty.repr(tcx)).as_slice())
255274
}
256275

257276
fn is_ty_param(ty: ty::Ty) -> bool {
@@ -267,6 +286,24 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
267286
self.check_item_well_formed(i);
268287
visit::walk_item(self, i);
269288
}
289+
290+
fn visit_trait_item(&mut self, t: &'v ast::TraitItem) {
291+
match t {
292+
&ast::TraitItem::ProvidedMethod(_) |
293+
&ast::TraitItem::TypeTraitItem(_) => {},
294+
&ast::TraitItem::RequiredMethod(ref method) => {
295+
match ty::impl_or_trait_item(self.ccx.tcx, local_def(method.id)) {
296+
ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
297+
reject_non_type_param_bounds(
298+
self.ccx.tcx,
299+
method.span,
300+
&ty_method.generics)
301+
}
302+
_ => {}
303+
}
304+
}
305+
}
306+
}
270307
}
271308

272309
pub struct BoundsChecker<'cx,'tcx:'cx> {
@@ -455,7 +492,6 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
455492
let arg_tys =
456493
ty::assert_no_late_bound_regions(
457494
fcx.tcx(), &ty::ty_fn_args(ctor_ty));
458-
459495
AdtVariant {
460496
fields: args.iter().enumerate().map(|(index, arg)| {
461497
let arg_ty = arg_tys[index];

Diff for: src/test/compile-fail/where-clauses-not-parameter.rs

+10-8
Original file line numberDiff line numberDiff line change
@@ -8,32 +8,34 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11-
fn equal<T>(_: &T, _: &T) -> bool where int : Eq {
11+
fn equal<T>(_: &T, _: &T) -> bool where isize : Eq {
1212
true //~^ ERROR cannot bound type `isize`, where clause bounds may only be attached
1313
}
1414

1515
// This should be fine involves a type parameter.
1616
fn test<T: Eq>() -> bool where Option<T> : Eq {}
1717

1818
// This should be rejected as well.
19-
fn test2() -> bool where Option<int> : Eq {}
20-
//~^ ERROR cannot bound type `core::option::Option<isize>`, where clause bounds
19+
fn test2() -> bool where Option<isize> : Eq {}
20+
//~^ ERROR cannot bound type `core::option::Option<isize>`, where clause bounds may
2121

2222
#[derive(PartialEq)]
2323
//~^ ERROR cannot bound type `isize`, where clause bounds
24-
enum Foo<T> where int : Eq { MkFoo }
24+
enum Foo<T> where isize : Eq { MkFoo }
2525
//~^ ERROR cannot bound type `isize`, where clause bounds
2626

2727
fn test3<T: Eq>() -> bool where Option<Foo<T>> : Eq {}
2828

29-
fn test4() -> bool where Option<Foo<int>> : Eq {}
29+
fn test4() -> bool where Option<Foo<isize>> : Eq {}
3030
//~^ ERROR cannot bound type `core::option::Option<Foo<isize>>`, where clause bounds
3131

32-
trait Baz<T> where int : Eq {
33-
fn baz() where String : Eq;
32+
trait Baz<T> where isize : Eq {
33+
//~^ ERROR cannot bound type `isize`, where clause bounds may only
34+
fn baz() where String : Eq; //~ ERROR cannot bound type `collections::string::String`
35+
//~^ ERROR cannot bound type `isize`, where clause
3436
}
3537

36-
impl Baz<int> for int where int : Eq {
38+
impl Baz<int> for int where isize : Eq {
3739
//~^ ERROR cannot bound type `isize`, where clause bounds
3840
fn baz() where String : Eq {}
3941
}

0 commit comments

Comments
 (0)