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:
commit
3800f6417b
@ -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];
|
||||
|
@ -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 {}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user