//! a `pub fn new()`.
use self::MethodContext::*;
+
+use fmt_macros::{Parser, Piece, Position};
+
use metadata::csearch;
use middle::def::*;
use middle::subst::Substs;
}
}
}
+
+/// 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
--- /dev/null
+// 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.
+// ignore-tidy-linelength
+
+#[allow(unused)]
+
+#[on_unimplemented = "test error `{Self}` with `{Bar}` `{Baz}` `{Quux}`"]
+trait Foo<Bar, Baz, Quux>{}
+
+#[on_unimplemented="a collection of type `{Self}` cannot be built from an iterator over elements of type `{A}`"]
+trait MyFromIterator<A> {
+ /// Build a container with elements from an external iterator.
+ fn my_from_iter<T: Iterator<Item=A>>(iterator: T) -> Self;
+}
+
+#[on_unimplemented] //~ ERROR this attribute must have a value
+trait BadAnnotation1 {}
+
+#[on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
+//~^ ERROR there is no type parameter C on trait BadAnnotation2
+trait BadAnnotation2<A,B> {}
+
+
+pub fn main() {
+}