about summary refs log tree commit diff
diff options
context:
space:
mode:
authorJared Roesch <roeschinc@gmail.com>2015-01-07 01:04:08 -0800
committerJared Roesch <roeschinc@gmail.com>2015-01-07 11:27:36 -0800
commit120a52034d27a3ac08ed01a637569db9bc47108d (patch)
treecaea493f416c5e9122092d2818fdb0ed2a2f04cc
parent9e4e524e0eb17c8f463e731f23b544003e8709c6 (diff)
downloadrust-120a52034d27a3ac08ed01a637569db9bc47108d.tar.gz
rust-120a52034d27a3ac08ed01a637569db9bc47108d.zip
Reject all uses of non-typaram bounds
-rw-r--r--src/librustc_typeck/check/wf.rs58
-rw-r--r--src/test/compile-fail/where-clauses-not-parameter.rs18
2 files changed, 57 insertions, 19 deletions
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index 84823b0fd57..90487afb177 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -77,6 +77,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                     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 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 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 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         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];
diff --git a/src/test/compile-fail/where-clauses-not-parameter.rs b/src/test/compile-fail/where-clauses-not-parameter.rs
index 148473f8987..d8af859c081 100644
--- a/src/test/compile-fail/where-clauses-not-parameter.rs
+++ b/src/test/compile-fail/where-clauses-not-parameter.rs
@@ -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 {}
 }