about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorManish Goregaokar <manishsmail@gmail.com>2015-01-11 18:17:46 +0530
committerManish Goregaokar <manishsmail@gmail.com>2015-01-11 18:17:51 +0530
commitadd20bbb6dae07fddc80bc46f53296fbf5679f27 (patch)
tree9e3d1ac2355dd06d3fd0ca47929b3c19bec1adff /src
parente1832779483df51b59367250850213d8e7fe159a (diff)
downloadrust-add20bbb6dae07fddc80bc46f53296fbf5679f27.tar.gz
rust-add20bbb6dae07fddc80bc46f53296fbf5679f27.zip
Move error to typeck::check
Diffstat (limited to 'src')
-rw-r--r--src/librustc/lint/builtin.rs63
-rw-r--r--src/librustc/lint/context.rs1
-rw-r--r--src/librustc_typeck/check/mod.rs50
-rw-r--r--src/librustc_typeck/lib.rs1
-rw-r--r--src/test/compile-fail/on-unimplemented.rs15
5 files changed, 50 insertions, 80 deletions
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 29d37af30fc..300b9aaf100 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -26,9 +26,6 @@
 //! a `pub fn new()`.
 use self::MethodContext::*;
 
-
-use fmt_macros::{Parser, Piece, Position};
-
 use metadata::csearch;
 use middle::def::*;
 use middle::subst::Substs;
@@ -1924,63 +1921,3 @@ impl LintPass for UnstableFeatures {
         }
     }
 }
-
-/// Checks usage of `#[on_unimplemented]`
-#[derive(Copy)]
-pub struct BadOnUnimplemented;
-
-declare_lint!(BAD_ON_UNIMPLEMENTED, Deny,
-              "Checks usage of `#[on_unimplemented]`");
-
-impl LintPass for BadOnUnimplemented {
-    fn get_lints(&self) -> LintArray {
-        lint_array!(BAD_ON_UNIMPLEMENTED)
-    }
-    fn check_item(&mut self, ctx: &Context, item: &ast::Item) {
-        match item.node {
-            ast::ItemTrait(_, ref generics, _, _) => {
-                if let Some(ref attr) = item.attrs.iter().find(|&: a| {
-                    a.check_name("on_unimplemented")
-                }) {
-                    if let Some(ref istring) = attr.value_str() {
-                        let mut parser = Parser::new(istring.get());
-                        let types = generics.ty_params.as_slice();
-                        for token in parser {
-                            match token {
-                                Piece::String(_) => (), // Normal string, no need to check it
-                                Piece::NextArgument(a) => match a.position {
-                                    // `{Self}` is allowed
-                                    Position::ArgumentNamed(s) if s == "Self" => (),
-                                    // So is `{A}` if A is a type parameter
-                                    Position::ArgumentNamed(s) => match types.iter().find(|t| {
-                                        t.ident.as_str() == s
-                                    }) {
-                                        Some(_) => (),
-                                        None => {
-                                            ctx.span_lint(BAD_ON_UNIMPLEMENTED, attr.span,
-                                                         format!("there is no type parameter \
-                                                                    {} on trait {}",
-                                                                    s, item.ident.as_str())
-                                                           .as_slice());
-                                        }
-                                    },
-                                    // `{:1}` and `{}` are not to be used
-                                    Position::ArgumentIs(_) | Position::ArgumentNext => {
-                                        ctx.span_lint(BAD_ON_UNIMPLEMENTED, attr.span,
-                                                     "only named substitution \
-                                                     parameters are allowed");
-                                    }
-                                }
-                            }
-                        }
-                    } else {
-                        ctx.span_lint(BAD_ON_UNIMPLEMENTED, attr.span,
-                                     "this attribute must have a value, \
-                                      eg `#[on_unimplemented = \"foo\"]`")
-                    }
-                }
-            },
-            _ => () // Not a trait def, move along
-        }
-    }
-}
\ No newline at end of file
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index b50c505a3ac..95e1e8d44bf 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -211,7 +211,6 @@ impl LintStore {
                      UnusedAllocation,
                      MissingCopyImplementations,
                      UnstableFeatures,
-                     BadOnUnimplemented,
         );
 
         add_builtin_with_new!(sess,
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 1d184131ded..de6c884d6d7 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -83,6 +83,7 @@ use self::TupleArgumentsFlag::*;
 
 use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
 use check::_match::pat_ctxt;
+use fmt_macros::{Parser, Piece, Position};
 use middle::{const_eval, def};
 use middle::infer;
 use middle::lang_items::IteratorItem;
@@ -113,6 +114,7 @@ use std::mem::replace;
 use std::rc::Rc;
 use std::iter::repeat;
 use syntax::{self, abi, attr};
+use syntax::attr::AttrMetaMethods;
 use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
 use syntax::ast_util::{self, local_def, PostExpansionMethod};
 use syntax::codemap::{self, Span};
@@ -726,7 +728,8 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
         }
 
       }
-      ast::ItemTrait(_, _, _, ref trait_methods) => {
+      ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
+        check_trait_on_unimplemented(ccx, generics, it);
         let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
         for trait_method in trait_methods.iter() {
             match *trait_method {
@@ -776,6 +779,51 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
     }
 }
 
+fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                               generics: &ast::Generics,
+                               item: &ast::Item) {
+    if let Some(ref attr) = item.attrs.iter().find(|&: a| {
+        a.check_name("on_unimplemented")
+    }) {
+        if let Some(ref istring) = attr.value_str() {
+            let mut parser = Parser::new(istring.get());
+            let types = generics.ty_params.as_slice();
+            for token in parser {
+                match token {
+                    Piece::String(_) => (), // Normal string, no need to check it
+                    Piece::NextArgument(a) => match a.position {
+                        // `{Self}` is allowed
+                        Position::ArgumentNamed(s) if s == "Self" => (),
+                        // So is `{A}` if A is a type parameter
+                        Position::ArgumentNamed(s) => match types.iter().find(|t| {
+                            t.ident.as_str() == s
+                        }) {
+                            Some(_) => (),
+                            None => {
+                                ccx.tcx.sess.span_err(attr.span,
+                                                 format!("there is no type parameter \
+                                                          {} on trait {}",
+                                                           s, item.ident.as_str())
+                                            .as_slice());
+                            }
+                        },
+                        // `{:1}` and `{}` are not to be used
+                        Position::ArgumentIs(_) | Position::ArgumentNext => {
+                            ccx.tcx.sess.span_err(attr.span,
+                                                  "only named substitution \
+                                                   parameters are allowed");
+                        }
+                    }
+                }
+            }
+        } else {
+            ccx.tcx.sess.span_err(attr.span,
+                                  "this attribute must have a value, \
+                                   eg `#[on_unimplemented = \"foo\"]`")
+        }
+    }
+}
+
 /// Type checks a method body.
 ///
 /// # Parameters
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index f15d53290e7..68b152dee23 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -84,6 +84,7 @@ This API is completely unstable and subject to change.
 #[macro_use] extern crate syntax;
 
 extern crate arena;
+extern crate fmt_macros;
 extern crate rustc;
 
 pub use rustc::lint;
diff --git a/src/test/compile-fail/on-unimplemented.rs b/src/test/compile-fail/on-unimplemented.rs
index 3f899288f50..20b4448ea77 100644
--- a/src/test/compile-fail/on-unimplemented.rs
+++ b/src/test/compile-fail/on-unimplemented.rs
@@ -26,16 +26,6 @@ fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
     MyFromIterator::my_from_iter(it)
 }
 
-#[on_unimplemented] //~ ERROR the #[on_unimplemented] attribute on trait definition for BadAnnotation1 must have a value, eg `#[on_unimplemented = "foo"]`
-trait BadAnnotation1 {}
-
-#[on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
-//~^ ERROR the #[on_unimplemented] attribute on trait definition for BadAnnotation2<A, B> refers to non-existent type parameter C
-trait BadAnnotation2<A,B> {}
-
-fn trigger1<T: BadAnnotation1>(t: T)  {}
-fn trigger2<A, B, T: BadAnnotation2<A,B>>(t: T) {}
-
 pub fn main() {
     let x = vec!(1u8, 2, 3, 4);
     let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
@@ -43,9 +33,4 @@ pub fn main() {
     //~^^ NOTE a collection of type `core::option::Option<collections::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
     let x: String = foobar(); //~ ERROR
     //~^ NOTE test error `collections::string::String` with `u8` `_` `u32`
-
-    // The following two have errors in their annotations, so the regular error should be thrown
-    trigger1(1u8); //~ ERROR the trait `BadAnnotation1` is not implemented for the type `u8`
-    trigger2::<u8, u8, u8>(1u8); //~ ERROR the trait `BadAnnotation2<u8, u8>` is not implemented
-
 }