Add check to ensure trait bounds are only placed o
Add check to ensure trait bounds are only placed on ty_param
This commit is contained in:
parent
340ac040f7
commit
b683e879e4
@ -86,13 +86,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
{
|
||||
let ccx = self.ccx;
|
||||
let item_def_id = local_def(item.id);
|
||||
let polytype = ty::lookup_item_type(ccx.tcx, item_def_id);
|
||||
let type_scheme = ty::lookup_item_type(ccx.tcx, item_def_id);
|
||||
reject_non_type_param_bounds(ccx.tcx, item.span, &type_scheme.generics);
|
||||
let param_env =
|
||||
ty::construct_parameter_environment(ccx.tcx,
|
||||
&polytype.generics,
|
||||
&type_scheme.generics,
|
||||
item.id);
|
||||
let inh = Inherited::new(ccx.tcx, param_env);
|
||||
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(polytype.ty), item.id);
|
||||
let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id);
|
||||
f(self, &fcx);
|
||||
vtable::select_all_fcx_obligations_or_error(&fcx);
|
||||
regionck::regionck_item(&fcx, item);
|
||||
@ -143,10 +144,12 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
item.span,
|
||||
region::CodeExtent::from_node_id(item.id),
|
||||
Some(&mut this.cache));
|
||||
|
||||
let type_scheme = ty::lookup_item_type(fcx.tcx(), local_def(item.id));
|
||||
let item_ty = fcx.instantiate_type_scheme(item.span,
|
||||
&fcx.inh.param_env.free_substs,
|
||||
&type_scheme.ty);
|
||||
|
||||
bounds_checker.check_traits_in_ty(item_ty);
|
||||
});
|
||||
}
|
||||
@ -178,6 +181,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
None => { return; }
|
||||
Some(t) => { t }
|
||||
};
|
||||
|
||||
let trait_ref = fcx.instantiate_type_scheme(item.span,
|
||||
&fcx.inh.param_env.free_substs,
|
||||
&trait_ref);
|
||||
@ -229,6 +233,35 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
// Reject any predicates that do not involve a type parameter.
|
||||
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())
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_ty_param(ty: ty::Ty) -> bool {
|
||||
match &ty.sty {
|
||||
&ty::sty::ty_param(_) => true,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
|
||||
fn visit_item(&mut self, i: &ast::Item) {
|
||||
self.check_item_well_formed(i);
|
||||
|
@ -8,17 +8,34 @@
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
struct A;
|
||||
fn equal<T>(_: &T, _: &T) -> bool where int : Eq {
|
||||
true //~^ ERROR cannot bound type `int`, where clause bounds may only be attached
|
||||
}
|
||||
|
||||
trait U {}
|
||||
// This should be fine involves a type parameter.
|
||||
fn test<T: Eq>() -> bool where Option<T> : Eq {}
|
||||
|
||||
// impl U for A {}
|
||||
// This should be rejected as well.
|
||||
fn test2() -> bool where Option<int> : Eq {}
|
||||
|
||||
fn equal<T>(_: &T, _: &T) -> bool where A : U {
|
||||
true
|
||||
#[derive(PartialEq)]
|
||||
//~^ ERROR cannot bound type `int`, where clause bounds
|
||||
enum Foo<T> where int : Eq { MkFoo }
|
||||
|
||||
fn test3<T: Eq>() -> bool where Option<Foo<T>> : Eq {}
|
||||
|
||||
fn test4() -> bool where Option<Foo<int>> : Eq {}
|
||||
//~^ ERROR cannot bound type `core::option::Option<Foo<int>>`, where clause bounds
|
||||
|
||||
trait Baz<T> where int : Eq {
|
||||
fn baz() where String : Eq;
|
||||
}
|
||||
|
||||
impl Baz<int> for int where int : Eq {
|
||||
//~^ ERROR cannot bound type `int`, where clause bounds
|
||||
fn baz() where String : Eq {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
equal(&0i, &0i);
|
||||
//~^ ERROR the trait `U` is not implemented for the type `A`
|
||||
}
|
||||
|
@ -1,17 +0,0 @@
|
||||
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
|
||||
// file at the top-level directory of this distribution and at
|
||||
// http://rust-lang.org/COPYRIGHT.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||
// option. This file may not be copied, modified, or distributed
|
||||
// except according to those terms.
|
||||
|
||||
fn equal<T>(_: &T, _: &T) -> bool where int : Eq {
|
||||
true
|
||||
}
|
||||
|
||||
fn main() {
|
||||
equal(&0i, &0i);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user