mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-10 23:06:23 +00:00
Add lint and test for malformed but unused #[on_unimplemented] attributes
This commit is contained in:
parent
4d17fbaf37
commit
dc0de42035
@ -26,6 +26,9 @@
|
||||
//! a `pub fn new()`.
|
||||
use self::MethodContext::*;
|
||||
|
||||
|
||||
use fmt_macros::{Parser, Piece, Position};
|
||||
|
||||
use metadata::csearch;
|
||||
use middle::def::*;
|
||||
use middle::subst::Substs;
|
||||
@ -1921,3 +1924,63 @@ 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
|
||||
}
|
||||
}
|
||||
}
|
@ -211,6 +211,7 @@ impl LintStore {
|
||||
UnusedAllocation,
|
||||
MissingCopyImplementations,
|
||||
UnstableFeatures,
|
||||
BadOnUnimplemented,
|
||||
);
|
||||
|
||||
add_builtin_with_new!(sess,
|
||||
|
32
src/test/compile-fail/on-unimplemented-bad-anno.rs
Normal file
32
src/test/compile-fail/on-unimplemented-bad-anno.rs
Normal file
@ -0,0 +1,32 @@
|
||||
// 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() {
|
||||
}
|
Loading…
Reference in New Issue
Block a user