rollup merge of #20688: jroesch/reject-non-param-bounds-followup

This is a follow up to my recent PR. r? @nikomatsakis
This commit is contained in:
Alex Crichton 2015-01-07 17:17:25 -08:00
commit 3800f6417b
2 changed files with 57 additions and 19 deletions

View File

@ -77,6 +77,14 @@ fn check_item_well_formed(&mut self, item: &ast::Item) {
enum_variants(fcx, enum_def)
});
}
ast::ItemTrait(..) => {
let trait_def =
ty::lookup_trait_def(ccx.tcx, local_def(item.id));
reject_non_type_param_bounds(
ccx.tcx,
item.span,
&trait_def.generics);
}
_ => {}
}
}
@ -237,21 +245,32 @@ fn check_impl(&mut self,
fn reject_non_type_param_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
span: Span,
generics: &ty::Generics<'tcx>) {
for predicate in generics.predicates.iter() {
match predicate {
&ty::Predicate::Trait(ty::Binder(ref tr)) => {
let self_ty = tr.self_ty();
if !self_ty.walk().any(|t| is_ty_param(t)) {
tcx.sess.span_err(
span,
format!("cannot bound type `{}`, where clause \
bounds may only be attached to types involving \
type parameters",
self_ty.repr(tcx)).as_slice())
}
let found_param = tr.input_types().iter()
.flat_map(|ty| ty.walk())
.any(is_ty_param);
if !found_param { report_bound_error(tcx, span, tr.self_ty() )}
}
&ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(ty, _))) => {
let found_param = ty.walk().any(|t| is_ty_param(t));
if !found_param { report_bound_error(tcx, span, ty) }
}
_ => {}
}
};
}
fn report_bound_error<'t>(tcx: &ty::ctxt<'t>,
span: Span,
bounded_ty: ty::Ty<'t>) {
tcx.sess.span_err(
span,
format!("cannot bound type `{}`, where clause \
bounds may only be attached to types involving \
type parameters",
bounded_ty.repr(tcx)).as_slice())
}
fn is_ty_param(ty: ty::Ty) -> bool {
@ -267,6 +286,24 @@ fn visit_item(&mut self, i: &ast::Item) {
self.check_item_well_formed(i);
visit::walk_item(self, i);
}
fn visit_trait_item(&mut self, t: &'v ast::TraitItem) {
match t {
&ast::TraitItem::ProvidedMethod(_) |
&ast::TraitItem::TypeTraitItem(_) => {},
&ast::TraitItem::RequiredMethod(ref method) => {
match ty::impl_or_trait_item(self.ccx.tcx, local_def(method.id)) {
ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
reject_non_type_param_bounds(
self.ccx.tcx,
method.span,
&ty_method.generics)
}
_ => {}
}
}
}
}
}
pub struct BoundsChecker<'cx,'tcx:'cx> {
@ -455,7 +492,6 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
let arg_tys =
ty::assert_no_late_bound_regions(
fcx.tcx(), &ty::ty_fn_args(ctor_ty));
AdtVariant {
fields: args.iter().enumerate().map(|(index, arg)| {
let arg_ty = arg_tys[index];

View File

@ -8,7 +8,7 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.
fn equal<T>(_: &T, _: &T) -> bool where int : Eq {
fn equal<T>(_: &T, _: &T) -> bool where isize : Eq {
true //~^ ERROR cannot bound type `isize`, where clause bounds may only be attached
}
@ -16,24 +16,26 @@ fn equal<T>(_: &T, _: &T) -> bool where int : Eq {
fn test<T: Eq>() -> bool where Option<T> : Eq {}
// This should be rejected as well.
fn test2() -> bool where Option<int> : Eq {}
//~^ ERROR cannot bound type `core::option::Option<isize>`, where clause bounds
fn test2() -> bool where Option<isize> : Eq {}
//~^ ERROR cannot bound type `core::option::Option<isize>`, where clause bounds may
#[derive(PartialEq)]
//~^ ERROR cannot bound type `isize`, where clause bounds
enum Foo<T> where int : Eq { MkFoo }
enum Foo<T> where isize : Eq { MkFoo }
//~^ ERROR cannot bound type `isize`, where clause bounds
fn test3<T: Eq>() -> bool where Option<Foo<T>> : Eq {}
fn test4() -> bool where Option<Foo<int>> : Eq {}
fn test4() -> bool where Option<Foo<isize>> : Eq {}
//~^ ERROR cannot bound type `core::option::Option<Foo<isize>>`, where clause bounds
trait Baz<T> where int : Eq {
fn baz() where String : Eq;
trait Baz<T> where isize : Eq {
//~^ ERROR cannot bound type `isize`, where clause bounds may only
fn baz() where String : Eq; //~ ERROR cannot bound type `collections::string::String`
//~^ ERROR cannot bound type `isize`, where clause
}
impl Baz<int> for int where int : Eq {
impl Baz<int> for int where isize : Eq {
//~^ ERROR cannot bound type `isize`, where clause bounds
fn baz() where String : Eq {}
}