Navigation Menu

Skip to content

Commit

Permalink
Add check to ensure trait bounds are only placed o
Browse files Browse the repository at this point in the history
Add check to ensure trait bounds are only placed on
ty_param
  • Loading branch information
jroesch committed Jan 6, 2015
1 parent 340ac04 commit b683e87
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 26 deletions.
39 changes: 36 additions & 3 deletions src/librustc_typeck/check/wf.rs
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
});
}
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
29 changes: 23 additions & 6 deletions src/test/compile-fail/where-clauses-not-parameter.rs
Expand Up @@ -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
}

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

// This should be rejected as well.
fn test2() -> bool where Option<int> : Eq {}

trait U {}
#[derive(PartialEq)]
//~^ ERROR cannot bound type `int`, where clause bounds
enum Foo<T> where int : Eq { MkFoo }

// impl U for A {}
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;
}

fn equal<T>(_: &T, _: &T) -> bool where A : U {
true
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`
}
17 changes: 0 additions & 17 deletions src/test/run-pass/where-clauses-not-parameter.rs

This file was deleted.

0 comments on commit b683e87

Please sign in to comment.