Skip to content

Commit add20bb

Browse files
committed
Move error to typeck::check
1 parent e183277 commit add20bb

File tree

5 files changed

+50
-80
lines changed

5 files changed

+50
-80
lines changed

src/librustc/lint/builtin.rs

-63
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,6 @@
2626
//! a `pub fn new()`.
2727
use self::MethodContext::*;
2828

29-
30-
use fmt_macros::{Parser, Piece, Position};
31-
3229
use metadata::csearch;
3330
use middle::def::*;
3431
use middle::subst::Substs;
@@ -1924,63 +1921,3 @@ impl LintPass for UnstableFeatures {
19241921
}
19251922
}
19261923
}
1927-
1928-
/// Checks usage of `#[on_unimplemented]`
1929-
#[derive(Copy)]
1930-
pub struct BadOnUnimplemented;
1931-
1932-
declare_lint!(BAD_ON_UNIMPLEMENTED, Deny,
1933-
"Checks usage of `#[on_unimplemented]`");
1934-
1935-
impl LintPass for BadOnUnimplemented {
1936-
fn get_lints(&self) -> LintArray {
1937-
lint_array!(BAD_ON_UNIMPLEMENTED)
1938-
}
1939-
fn check_item(&mut self, ctx: &Context, item: &ast::Item) {
1940-
match item.node {
1941-
ast::ItemTrait(_, ref generics, _, _) => {
1942-
if let Some(ref attr) = item.attrs.iter().find(|&: a| {
1943-
a.check_name("on_unimplemented")
1944-
}) {
1945-
if let Some(ref istring) = attr.value_str() {
1946-
let mut parser = Parser::new(istring.get());
1947-
let types = generics.ty_params.as_slice();
1948-
for token in parser {
1949-
match token {
1950-
Piece::String(_) => (), // Normal string, no need to check it
1951-
Piece::NextArgument(a) => match a.position {
1952-
// `{Self}` is allowed
1953-
Position::ArgumentNamed(s) if s == "Self" => (),
1954-
// So is `{A}` if A is a type parameter
1955-
Position::ArgumentNamed(s) => match types.iter().find(|t| {
1956-
t.ident.as_str() == s
1957-
}) {
1958-
Some(_) => (),
1959-
None => {
1960-
ctx.span_lint(BAD_ON_UNIMPLEMENTED, attr.span,
1961-
format!("there is no type parameter \
1962-
{} on trait {}",
1963-
s, item.ident.as_str())
1964-
.as_slice());
1965-
}
1966-
},
1967-
// `{:1}` and `{}` are not to be used
1968-
Position::ArgumentIs(_) | Position::ArgumentNext => {
1969-
ctx.span_lint(BAD_ON_UNIMPLEMENTED, attr.span,
1970-
"only named substitution \
1971-
parameters are allowed");
1972-
}
1973-
}
1974-
}
1975-
}
1976-
} else {
1977-
ctx.span_lint(BAD_ON_UNIMPLEMENTED, attr.span,
1978-
"this attribute must have a value, \
1979-
eg `#[on_unimplemented = \"foo\"]`")
1980-
}
1981-
}
1982-
},
1983-
_ => () // Not a trait def, move along
1984-
}
1985-
}
1986-
}

src/librustc/lint/context.rs

-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ impl LintStore {
211211
UnusedAllocation,
212212
MissingCopyImplementations,
213213
UnstableFeatures,
214-
BadOnUnimplemented,
215214
);
216215

217216
add_builtin_with_new!(sess,

src/librustc_typeck/check/mod.rs

+49-1
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ use self::TupleArgumentsFlag::*;
8383

8484
use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv};
8585
use check::_match::pat_ctxt;
86+
use fmt_macros::{Parser, Piece, Position};
8687
use middle::{const_eval, def};
8788
use middle::infer;
8889
use middle::lang_items::IteratorItem;
@@ -113,6 +114,7 @@ use std::mem::replace;
113114
use std::rc::Rc;
114115
use std::iter::repeat;
115116
use syntax::{self, abi, attr};
117+
use syntax::attr::AttrMetaMethods;
116118
use syntax::ast::{self, ProvidedMethod, RequiredMethod, TypeTraitItem, DefId};
117119
use syntax::ast_util::{self, local_def, PostExpansionMethod};
118120
use syntax::codemap::{self, Span};
@@ -726,7 +728,8 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
726728
}
727729

728730
}
729-
ast::ItemTrait(_, _, _, ref trait_methods) => {
731+
ast::ItemTrait(_, ref generics, _, ref trait_methods) => {
732+
check_trait_on_unimplemented(ccx, generics, it);
730733
let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
731734
for trait_method in trait_methods.iter() {
732735
match *trait_method {
@@ -776,6 +779,51 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
776779
}
777780
}
778781

782+
fn check_trait_on_unimplemented<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
783+
generics: &ast::Generics,
784+
item: &ast::Item) {
785+
if let Some(ref attr) = item.attrs.iter().find(|&: a| {
786+
a.check_name("on_unimplemented")
787+
}) {
788+
if let Some(ref istring) = attr.value_str() {
789+
let mut parser = Parser::new(istring.get());
790+
let types = generics.ty_params.as_slice();
791+
for token in parser {
792+
match token {
793+
Piece::String(_) => (), // Normal string, no need to check it
794+
Piece::NextArgument(a) => match a.position {
795+
// `{Self}` is allowed
796+
Position::ArgumentNamed(s) if s == "Self" => (),
797+
// So is `{A}` if A is a type parameter
798+
Position::ArgumentNamed(s) => match types.iter().find(|t| {
799+
t.ident.as_str() == s
800+
}) {
801+
Some(_) => (),
802+
None => {
803+
ccx.tcx.sess.span_err(attr.span,
804+
format!("there is no type parameter \
805+
{} on trait {}",
806+
s, item.ident.as_str())
807+
.as_slice());
808+
}
809+
},
810+
// `{:1}` and `{}` are not to be used
811+
Position::ArgumentIs(_) | Position::ArgumentNext => {
812+
ccx.tcx.sess.span_err(attr.span,
813+
"only named substitution \
814+
parameters are allowed");
815+
}
816+
}
817+
}
818+
}
819+
} else {
820+
ccx.tcx.sess.span_err(attr.span,
821+
"this attribute must have a value, \
822+
eg `#[on_unimplemented = \"foo\"]`")
823+
}
824+
}
825+
}
826+
779827
/// Type checks a method body.
780828
///
781829
/// # Parameters

src/librustc_typeck/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,7 @@ This API is completely unstable and subject to change.
8484
#[macro_use] extern crate syntax;
8585

8686
extern crate arena;
87+
extern crate fmt_macros;
8788
extern crate rustc;
8889

8990
pub use rustc::lint;

src/test/compile-fail/on-unimplemented.rs

-15
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,11 @@ fn collect<A, I: Iterator<Item=A>, B: MyFromIterator<A>>(it: I) -> B {
2626
MyFromIterator::my_from_iter(it)
2727
}
2828

29-
#[on_unimplemented] //~ ERROR the #[on_unimplemented] attribute on trait definition for BadAnnotation1 must have a value, eg `#[on_unimplemented = "foo"]`
30-
trait BadAnnotation1 {}
31-
32-
#[on_unimplemented = "Unimplemented trait error on `{Self}` with params `<{A},{B},{C}>`"]
33-
//~^ ERROR the #[on_unimplemented] attribute on trait definition for BadAnnotation2<A, B> refers to non-existent type parameter C
34-
trait BadAnnotation2<A,B> {}
35-
36-
fn trigger1<T: BadAnnotation1>(t: T) {}
37-
fn trigger2<A, B, T: BadAnnotation2<A,B>>(t: T) {}
38-
3929
pub fn main() {
4030
let x = vec!(1u8, 2, 3, 4);
4131
let y: Option<Vec<u8>> = collect(x.iter()); // this should give approximately the same error for x.iter().collect()
4232
//~^ ERROR
4333
//~^^ NOTE a collection of type `core::option::Option<collections::vec::Vec<u8>>` cannot be built from an iterator over elements of type `&u8`
4434
let x: String = foobar(); //~ ERROR
4535
//~^ NOTE test error `collections::string::String` with `u8` `_` `u32`
46-
47-
// The following two have errors in their annotations, so the regular error should be thrown
48-
trigger1(1u8); //~ ERROR the trait `BadAnnotation1` is not implemented for the type `u8`
49-
trigger2::<u8, u8, u8>(1u8); //~ ERROR the trait `BadAnnotation2<u8, u8>` is not implemented
50-
5136
}

0 commit comments

Comments
 (0)