diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs index cbf1a6775550..d94c5d034a65 100644 --- a/compiler/rustc_lint/src/early.rs +++ b/compiler/rustc_lint/src/early.rs @@ -219,9 +219,10 @@ impl<'a, T: EarlyLintPass> ast_visit::Visitor<'a> for EarlyContextAndPass<'a, T> } fn visit_generic_param(&mut self, param: &'a ast::GenericParam) { - run_early_pass!(self, check_generic_param, param); - self.check_id(param.id); - ast_visit::walk_generic_param(self, param); + self.with_lint_attrs(param.id, ¶m.attrs, |cx| { + run_early_pass!(cx, check_generic_param, param); + ast_visit::walk_generic_param(cx, param); + }); } fn visit_generics(&mut self, g: &'a ast::Generics) { diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 7ab9302d835a..bae366479923 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -761,9 +761,26 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { } fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { - self.with_lint_attrs(e.hir_id, |builder| { - intravisit::walk_expr(builder, e); - }) + match e.kind { + hir::ExprKind::Struct(qpath, fields, base_expr) => { + self.with_lint_attrs(e.hir_id, |builder| { + builder.visit_qpath(qpath, e.hir_id, e.span); + for field in fields { + builder.with_lint_attrs(field.hir_id, |field_builder| { + field_builder.visit_id(field.hir_id); + field_builder.visit_ident(field.ident); + field_builder.visit_expr(field.expr); + }); + } + if let Some(base_expr) = base_expr { + builder.visit_expr(base_expr); + } + }); + } + _ => self.with_lint_attrs(e.hir_id, |builder| { + intravisit::walk_expr(builder, e); + }), + } } fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { @@ -801,6 +818,28 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> { intravisit::walk_impl_item(builder, impl_item); }); } + + fn visit_pat(&mut self, p: &'tcx hir::Pat<'tcx>) { + match &p.kind { + hir::PatKind::Struct(qpath, fields, _) => { + self.visit_qpath(&qpath, p.hir_id, p.span); + for field in *fields { + self.with_lint_attrs(field.hir_id, |builder| { + builder.visit_id(field.hir_id); + builder.visit_ident(field.ident); + builder.visit_pat(field.pat); + }) + } + } + _ => intravisit::walk_pat(self, p), + } + } + + fn visit_generic_param(&mut self, p: &'tcx hir::GenericParam<'tcx>) { + self.with_lint_attrs(p.hir_id, |builder| { + intravisit::walk_generic_param(builder, p); + }); + } } pub fn provide(providers: &mut Providers) { diff --git a/src/test/ui/lint/lint-attr-everywhere-early.rs b/src/test/ui/lint/lint-attr-everywhere-early.rs new file mode 100644 index 000000000000..9ac0e45c6da0 --- /dev/null +++ b/src/test/ui/lint/lint-attr-everywhere-early.rs @@ -0,0 +1,169 @@ +// Tests that lint levels can be set for early lints. +#![allow(non_camel_case_types, unsafe_code, while_true, unused_parens)] + +// The following is a check of the lints used here to verify they do not warn +// when allowed. +fn verify_no_warnings() { + type non_camel_type = i32; // non_camel_case_types + struct NON_CAMEL_IS_ALLOWED; // non_camel_case_types + unsafe {} // unsafe_code + enum Enum { + VARIANT_CAMEL // non_camel_case_types + } + fn generics() {} // non_camel_case_types + while true {} // while_true + type T = (i32); // unused_parens +} + + +// ################## Types + +#[deny(non_camel_case_types)] +type type_outer = i32; //~ ERROR type `type_outer` should have an upper camel case name + +type BareFnPtr = fn(#[deny(unused_parens)](i32)); //~ ERROR unnecessary parentheses around type +// There aren't any early lints that currently apply to the variadic spot. +// type BareFnPtrVariadic = extern "C" fn(i32, #[deny()]...); + +// ################## Items +#[deny(non_camel_case_types)] +struct ITEM_OUTER; //~ ERROR type `ITEM_OUTER` should have an upper camel case name + +mod module_inner { + #![deny(unsafe_code)] + fn f() { + unsafe {} //~ ERROR usage of an `unsafe` block + } +} + +struct Associated; +impl Associated { + #![deny(unsafe_code)] + + fn inherent_denied_from_inner() { unsafe {} } //~ usage of an `unsafe` block + + #[deny(while_true)] + fn inherent_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const INHERENT_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with +} + +trait trait_inner { //~ ERROR trait `trait_inner` should have an upper camel case name + #![deny(non_camel_case_types)] +} + +trait AssociatedTrait { + #![deny(unsafe_code)] + + fn denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block + + #[deny(while_true)] + fn assoc_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const ASSOC_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with + + #[deny(non_camel_case_types)] + type assoc_type; //~ ERROR associated type `assoc_type` should have an upper camel case name +} + +impl AssociatedTrait for Associated { + #![deny(unsafe_code)] + + fn denied_from_inner() { unsafe {} } //~ ERROR usage of an `unsafe` block + + #[deny(while_true)] + fn assoc_fn() { while true {} } //~ ERROR denote infinite loops with + + #[deny(while_true)] + const ASSOC_CONST: i32 = {while true {} 1}; //~ ERROR denote infinite loops with + + #[deny(unused_parens)] + type assoc_type = (i32); //~ ERROR unnecessary parentheses around type +} + +struct StructFields { + #[deny(unused_parens)]f1: (i32), //~ ERROR unnecessary parentheses around type +} +struct StructTuple(#[deny(unused_parens)](i32)); //~ ERROR unnecessary parentheses around type + +enum Enum { + #[deny(non_camel_case_types)] + VARIANT_CAMEL, //~ ERROR variant `VARIANT_CAMEL` should have an upper camel case name +} + +extern "C" { + #![deny(unused_parens)] + + fn foreign_denied_from_inner(x: (i32)); //~ ERROR unnecessary parentheses around type +} + +extern "C" { + #[deny(unused_parens)] + fn foreign_denied_from_outer(x: (i32)); //~ ERROR unnecessary parentheses around type +} + +fn function(#[deny(unused_parens)] param: (i32)) {} //~ ERROR unnecessary parentheses around type + +fn generics<#[deny(non_camel_case_types)]foo>() {} //~ ERROR type parameter `foo` should have an upper camel case name + + +// ################## Statements +fn statements() { + #[deny(unused_parens)] + let x = (1); //~ ERROR unnecessary parentheses around assigned value +} + + +// ################## Expressions +fn expressions() { + let closure = |#[deny(unused_parens)] param: (i32)| {}; //~ ERROR unnecessary parentheses around type + + struct Match{f1: i32} + // Strangely unused_parens doesn't fire with {f1: (123)} + let f = Match{#[deny(unused_parens)]f1: {(123)}}; //~ ERROR unnecessary parentheses around block return value + + match f { + #![deny(unsafe_code)] + + #[deny(while_true)] + Match{f1} => { + unsafe {} //~ ERROR usage of an `unsafe` block + while true {} //~ ERROR denote infinite loops with + } + } + + // Statement Block + { + #![deny(unsafe_code)] + unsafe {} //~ ERROR usage of an `unsafe` block + } + let block_tail = { + #[deny(unsafe_code)] + unsafe {} //~ ERROR usage of an `unsafe` block + }; + + // Before expression as a statement. + #[deny(unsafe_code)] + unsafe {}; //~ ERROR usage of an `unsafe` block + + [#[deny(unsafe_code)] unsafe {123}]; //~ ERROR usage of an `unsafe` block + (#[deny(unsafe_code)] unsafe {123},); //~ ERROR usage of an `unsafe` block + fn call(p: i32) {} + call(#[deny(unsafe_code)] unsafe {123}); //~ ERROR usage of an `unsafe` block + struct TupleStruct(i32); + TupleStruct(#[deny(unsafe_code)] unsafe {123}); //~ ERROR usage of an `unsafe` block +} + + +// ################## Patterns +fn patterns() { + // There aren't any early lints that I can find that apply to pattern fields. + // + // struct PatField{f1: i32, f2: i32}; + // let f = PatField{f1: 1, f2: 2}; + // let PatField{#[deny()]f1, #[deny()]..} = f; +} + +fn main() {} diff --git a/src/test/ui/lint/lint-attr-everywhere-early.stderr b/src/test/ui/lint/lint-attr-everywhere-early.stderr new file mode 100644 index 000000000000..f65d811105fa --- /dev/null +++ b/src/test/ui/lint/lint-attr-everywhere-early.stderr @@ -0,0 +1,472 @@ +error: type `type_outer` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:22:6 + | +LL | type type_outer = i32; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `TypeOuter` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:21:8 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:24:43 + | +LL | type BareFnPtr = fn(#[deny(unused_parens)](i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:24:28 + | +LL | type BareFnPtr = fn(#[deny(unused_parens)](i32)); + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - type BareFnPtr = fn(#[deny(unused_parens)](i32)); +LL + type BareFnPtr = fn(#[deny(unused_parens)]i32); + | + +error: type `ITEM_OUTER` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:30:8 + | +LL | struct ITEM_OUTER; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `ItemOuter` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:29:8 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:35:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:33:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:43:39 + | +LL | fn inherent_denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:41:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:46:24 + | +LL | fn inherent_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:45:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:49:34 + | +LL | const INHERENT_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:48:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: trait `trait_inner` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:52:7 + | +LL | trait trait_inner { + | ^^^^^^^^^^^ help: convert the identifier to upper camel case: `TraitInner` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:53:13 + | +LL | #![deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:59:30 + | +LL | fn denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:57:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:62:21 + | +LL | fn assoc_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:61:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:65:31 + | +LL | const ASSOC_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:64:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: associated type `assoc_type` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:68:10 + | +LL | type assoc_type; + | ^^^^^^^^^^ help: convert the identifier to upper camel case: `AssocType` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:67:12 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:74:30 + | +LL | fn denied_from_inner() { unsafe {} } + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:72:13 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:77:21 + | +LL | fn assoc_fn() { while true {} } + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:76:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:80:31 + | +LL | const ASSOC_CONST: i32 = {while true {} 1}; + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:79:12 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:83:23 + | +LL | type assoc_type = (i32); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:82:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - type assoc_type = (i32); +LL + type assoc_type = i32; + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:87:31 + | +LL | #[deny(unused_parens)]f1: (i32), + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:87:12 + | +LL | #[deny(unused_parens)]f1: (i32), + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - #[deny(unused_parens)]f1: (i32), +LL + #[deny(unused_parens)]f1: i32, + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:89:42 + | +LL | struct StructTuple(#[deny(unused_parens)](i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:89:27 + | +LL | struct StructTuple(#[deny(unused_parens)](i32)); + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - struct StructTuple(#[deny(unused_parens)](i32)); +LL + struct StructTuple(#[deny(unused_parens)]i32); + | + +error: variant `VARIANT_CAMEL` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:93:5 + | +LL | VARIANT_CAMEL, + | ^^^^^^^^^^^^^ help: convert the identifier to upper camel case: `VariantCamel` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:92:12 + | +LL | #[deny(non_camel_case_types)] + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:99:37 + | +LL | fn foreign_denied_from_inner(x: (i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:97:13 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn foreign_denied_from_inner(x: (i32)); +LL + fn foreign_denied_from_inner(x: i32); + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:104:37 + | +LL | fn foreign_denied_from_outer(x: (i32)); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:103:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn foreign_denied_from_outer(x: (i32)); +LL + fn foreign_denied_from_outer(x: i32); + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:107:43 + | +LL | fn function(#[deny(unused_parens)] param: (i32)) {} + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:107:20 + | +LL | fn function(#[deny(unused_parens)] param: (i32)) {} + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - fn function(#[deny(unused_parens)] param: (i32)) {} +LL + fn function(#[deny(unused_parens)] param: i32) {} + | + +error: type parameter `foo` should have an upper camel case name + --> $DIR/lint-attr-everywhere-early.rs:109:42 + | +LL | fn generics<#[deny(non_camel_case_types)]foo>() {} + | ^^^ help: convert the identifier to upper camel case (notice the capitalization): `Foo` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:109:20 + | +LL | fn generics<#[deny(non_camel_case_types)]foo>() {} + | ^^^^^^^^^^^^^^^^^^^^ + +error: unnecessary parentheses around assigned value + --> $DIR/lint-attr-everywhere-early.rs:115:13 + | +LL | let x = (1); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:114:12 + | +LL | #[deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let x = (1); +LL + let x = 1; + | + +error: unnecessary parentheses around type + --> $DIR/lint-attr-everywhere-early.rs:121:50 + | +LL | let closure = |#[deny(unused_parens)] param: (i32)| {}; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:121:27 + | +LL | let closure = |#[deny(unused_parens)] param: (i32)| {}; + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let closure = |#[deny(unused_parens)] param: (i32)| {}; +LL + let closure = |#[deny(unused_parens)] param: i32| {}; + | + +error: unnecessary parentheses around block return value + --> $DIR/lint-attr-everywhere-early.rs:125:46 + | +LL | let f = Match{#[deny(unused_parens)]f1: {(123)}}; + | ^ ^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:125:26 + | +LL | let f = Match{#[deny(unused_parens)]f1: {(123)}}; + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - let f = Match{#[deny(unused_parens)]f1: {(123)}}; +LL + let f = Match{#[deny(unused_parens)]f1: {123}}; + | + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:132:13 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:128:17 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: denote infinite loops with `loop { ... }` + --> $DIR/lint-attr-everywhere-early.rs:133:13 + | +LL | while true {} + | ^^^^^^^^^^ help: use `loop` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:130:16 + | +LL | #[deny(while_true)] + | ^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:140:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:139:17 + | +LL | #![deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:144:9 + | +LL | unsafe {} + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:143:16 + | +LL | #[deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:149:5 + | +LL | unsafe {}; + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:148:12 + | +LL | #[deny(unsafe_code)] + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:151:27 + | +LL | [#[deny(unsafe_code)] unsafe {123}]; + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:151:13 + | +LL | [#[deny(unsafe_code)] unsafe {123}]; + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:152:27 + | +LL | (#[deny(unsafe_code)] unsafe {123},); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:152:13 + | +LL | (#[deny(unsafe_code)] unsafe {123},); + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:154:31 + | +LL | call(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:154:17 + | +LL | call(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^ + +error: usage of an `unsafe` block + --> $DIR/lint-attr-everywhere-early.rs:156:38 + | +LL | TupleStruct(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-early.rs:156:24 + | +LL | TupleStruct(#[deny(unsafe_code)] unsafe {123}); + | ^^^^^^^^^^^ + +error: aborting due to 35 previous errors + diff --git a/src/test/ui/lint/lint-attr-everywhere-late.rs b/src/test/ui/lint/lint-attr-everywhere-late.rs new file mode 100644 index 000000000000..1055157d6020 --- /dev/null +++ b/src/test/ui/lint/lint-attr-everywhere-late.rs @@ -0,0 +1,197 @@ +// Tests that lint levels can be set for late lints. +#![allow( + non_snake_case, + overflowing_literals, + missing_docs, + dyn_drop, + enum_intrinsics_non_enums, + clashing_extern_declarations +)] + +extern crate core; +use core::mem::{Discriminant, discriminant}; + +// The following is a check of the lints used here to verify they do not warn +// when allowed. +pub fn missing_docs_allowed() {} // missing_docs +fn dyn_drop_allowed(_x: Box) {} // dyn_drop +fn verify_no_warnings() { + discriminant::(&123); // enum_intrinsics_non_enums + let x: u8 = 1000; // overflowing_literals + let NON_SNAKE_CASE = 1; // non_snake_case +} +mod clashing_extern_allowed { + extern "C" { + fn extern_allowed(); + } +} +extern "C" { + fn extern_allowed(_: i32); // clashing_extern_declarations +} + +// ################## Types + +#[deny(missing_docs)] +pub type MissingDocType = i32; //~ ERROR missing documentation for a type alias + +// There aren't any late lints that I can find that can be easily used with types. +// type BareFnPtr = fn(#[deny()]i32); +// type BareFnPtrVariadic = extern "C" fn(i32, #[deny()]...); + +// ################## Items +#[deny(missing_docs)] +pub struct ItemOuter; //~ ERROR missing documentation for a struct + +pub mod module_inner { //~ ERROR missing documentation for a module + #![deny(missing_docs)] + pub fn missing_inner() {} //~ ERROR missing documentation for a function +} + +pub struct Associated; +impl Associated { + #![deny(missing_docs)] + + pub fn inherent_denied_from_inner() {} //~ ERROR missing documentation for an associated function +} + +impl Associated { + #[deny(missing_docs)] + pub fn inherent_fn() {} //~ ERROR missing documentation for an associated function + + #[deny(missing_docs)] + pub const INHERENT_CONST: i32 = 1; //~ ERROR missing documentation for an associated constant +} + +pub trait TraitInner { //~ ERROR missing documentation for a trait + #![deny(missing_docs)] +} + +pub trait AssociatedTraitInner { //~ ERROR missing documentation for a trait + #![deny(missing_docs)] + + fn denied_from_inner() {} //~ ERROR missing documentation for an associated function +} + +pub trait AssociatedTrait { + fn denied_from_inner(_x: Box) {} // Used below + + #[deny(missing_docs)] + fn assoc_fn() {} //~ ERROR missing documentation for an associated function + + #[deny(missing_docs)] + const ASSOC_CONST: u8 = 1; //~ ERROR missing documentation for an associated constant + + #[deny(missing_docs)] + type AssocType; //~ ERROR missing documentation for an associated type +} + +struct Foo; + +impl AssociatedTrait for Associated { + #![deny(dyn_drop)] + + fn denied_from_inner(_x: Box) {} //~ ERROR types that do not implement `Drop` + + #[deny(enum_intrinsics_non_enums)] + fn assoc_fn() { discriminant::(&123); } //~ ERROR the return value of + + #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; //~ ERROR literal out of range + type AssocType = i32; +} + + +// There aren't any late lints that can apply to a field that I can find. +// non_snake_case doesn't work on fields +// struct StructFields { +// #[deny()]f1: i32, +// } +// struct StructTuple(#[deny()]i32); + +pub enum Enum { + #[deny(missing_docs)] + Variant1, //~ ERROR missing documentation for a variant +} + +mod clashing_extern { + extern "C" { + fn clashing1(); + fn clashing2(); + } +} +extern "C" { + #![deny(clashing_extern_declarations)] + fn clashing1(_: i32); //~ ERROR `clashing1` redeclared with a different signature +} + +extern "C" { + #[deny(clashing_extern_declarations)] + fn clashing2(_: i32); //~ ERROR `clashing2` redeclared with a different signature +} + +fn function(#[deny(non_snake_case)] PARAM: i32) {} //~ ERROR variable `PARAM` should have a snake case name +// There aren't any late lints that can apply to generics that I can find. +// fn generics<#[deny()]T>() {} + + +// ################## Statements +fn statements() { + #[deny(enum_intrinsics_non_enums)] + let _ = discriminant::(&123); //~ ERROR the return value of +} + + +// ################## Expressions +fn expressions() { + let closure = |#[deny(non_snake_case)] PARAM: i32| {}; //~ ERROR variable `PARAM` should have a snake case name + + struct Match{f1: i32} + // I can't find any late lints for patterns. + // let f = Match{#[deny()]f1: 123}; + + let f = Match{f1: 123}; + match f { + #![deny(enum_intrinsics_non_enums)] + Match{f1} => { + discriminant::(&123); //~ ERROR the return value of + } + } + match f { + #[deny(enum_intrinsics_non_enums)] + Match{f1} => { + discriminant::(&123); //~ ERROR the return value of + } + } + + // Statement Block + { + #![deny(enum_intrinsics_non_enums)] + discriminant::(&123); //~ ERROR the return value of + } + let block_tail = { + #[deny(enum_intrinsics_non_enums)] + discriminant::(&123); //~ ERROR the return value of + }; + + // Before expression as a statement. + #[deny(enum_intrinsics_non_enums)] + discriminant::(&123); //~ ERROR the return value of + + [#[deny(enum_intrinsics_non_enums)] discriminant::(&123)]; //~ ERROR the return value of + (#[deny(enum_intrinsics_non_enums)] discriminant::(&123),); //~ ERROR the return value of + fn call(p: Discriminant) {} + call(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); //~ ERROR the return value of + struct TupleStruct(Discriminant); + TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); //~ ERROR the return value of +} + + +// ################## Patterns +fn patterns() { + // There aren't any late lints that I can find that apply to pattern fields. + // + // struct PatField{f1: i32, f2: i32}; + // let f = PatField{f1: 1, f2: 2}; + // let PatField{#[deny()]f1, #[deny()]..} = f; +} + +fn main() {} diff --git a/src/test/ui/lint/lint-attr-everywhere-late.stderr b/src/test/ui/lint/lint-attr-everywhere-late.stderr new file mode 100644 index 000000000000..d302798d6500 --- /dev/null +++ b/src/test/ui/lint/lint-attr-everywhere-late.stderr @@ -0,0 +1,428 @@ +error: missing documentation for a type alias + --> $DIR/lint-attr-everywhere-late.rs:35:1 + | +LL | pub type MissingDocType = i32; + | ^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:34:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a struct + --> $DIR/lint-attr-everywhere-late.rs:43:1 + | +LL | pub struct ItemOuter; + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:42:8 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a module + --> $DIR/lint-attr-everywhere-late.rs:45:1 + | +LL | pub mod module_inner { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:46:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a function + --> $DIR/lint-attr-everywhere-late.rs:47:5 + | +LL | pub fn missing_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:54:5 + | +LL | pub fn inherent_denied_from_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:52:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:59:5 + | +LL | pub fn inherent_fn() {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:58:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated constant + --> $DIR/lint-attr-everywhere-late.rs:62:5 + | +LL | pub const INHERENT_CONST: i32 = 1; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:61:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a trait + --> $DIR/lint-attr-everywhere-late.rs:65:1 + | +LL | pub trait TraitInner { + | ^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:66:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for a trait + --> $DIR/lint-attr-everywhere-late.rs:69:1 + | +LL | pub trait AssociatedTraitInner { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:70:13 + | +LL | #![deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:72:5 + | +LL | fn denied_from_inner() {} + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: missing documentation for an associated function + --> $DIR/lint-attr-everywhere-late.rs:79:5 + | +LL | fn assoc_fn() {} + | ^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:78:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated constant + --> $DIR/lint-attr-everywhere-late.rs:82:5 + | +LL | const ASSOC_CONST: u8 = 1; + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:81:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: missing documentation for an associated type + --> $DIR/lint-attr-everywhere-late.rs:85:5 + | +LL | type AssocType; + | ^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:84:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: types that do not implement `Drop` can still have drop glue, consider instead using `std::mem::needs_drop` to detect whether a type is trivially dropped + --> $DIR/lint-attr-everywhere-late.rs:93:38 + | +LL | fn denied_from_inner(_x: Box) {} + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:91:13 + | +LL | #![deny(dyn_drop)] + | ^^^^^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:96:21 + | +LL | fn assoc_fn() { discriminant::(&123); } + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:95:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:96:41 + | +LL | fn assoc_fn() { discriminant::(&123); } + | ^^^^ + +error: missing documentation for a variant + --> $DIR/lint-attr-everywhere-late.rs:112:5 + | +LL | Variant1, + | ^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:111:12 + | +LL | #[deny(missing_docs)] + | ^^^^^^^^^^^^ + +error: `clashing1` redeclared with a different signature + --> $DIR/lint-attr-everywhere-late.rs:123:5 + | +LL | fn clashing1(); + | --------------- `clashing1` previously declared here +... +LL | fn clashing1(_: i32); + | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:122:13 + | +LL | #![deny(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `unsafe extern "C" fn()` + found `unsafe extern "C" fn(i32)` + +error: `clashing2` redeclared with a different signature + --> $DIR/lint-attr-everywhere-late.rs:128:5 + | +LL | fn clashing2(); + | --------------- `clashing2` previously declared here +... +LL | fn clashing2(_: i32); + | ^^^^^^^^^^^^^^^^^^^^^ this signature doesn't match the previous declaration + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:127:12 + | +LL | #[deny(clashing_extern_declarations)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: expected `unsafe extern "C" fn()` + found `unsafe extern "C" fn(i32)` + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:139:13 + | +LL | let _ = discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:138:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:139:33 + | +LL | let _ = discriminant::(&123); + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:155:13 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:153:17 + | +LL | #![deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:155:33 + | +LL | discriminant::(&123); + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:161:13 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:159:16 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:161:33 + | +LL | discriminant::(&123); + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:168:9 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:167:17 + | +LL | #![deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:168:29 + | +LL | discriminant::(&123); + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:172:9 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:171:16 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:172:29 + | +LL | discriminant::(&123); + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:177:5 + | +LL | discriminant::(&123); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:176:12 + | +LL | #[deny(enum_intrinsics_non_enums)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:177:25 + | +LL | discriminant::(&123); + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:179:41 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::(&123)]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:179:13 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::(&123)]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:179:61 + | +LL | [#[deny(enum_intrinsics_non_enums)] discriminant::(&123)]; + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:180:41 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::(&123),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:180:13 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::(&123),); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:180:61 + | +LL | (#[deny(enum_intrinsics_non_enums)] discriminant::(&123),); + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:182:45 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:182:17 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:182:65 + | +LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^ + +error: the return value of `mem::discriminant` is unspecified when called with a non-enum type + --> $DIR/lint-attr-everywhere-late.rs:184:52 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:184:24 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ +note: the argument to `discriminant` should be a reference to an enum, but it was passed a reference to a `i32`, which is not an enum. + --> $DIR/lint-attr-everywhere-late.rs:184:72 + | +LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::(&123)); + | ^^^^ + +error: literal out of range for `u8` + --> $DIR/lint-attr-everywhere-late.rs:98:59 + | +LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; + | ^^^^ + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:98:12 + | +LL | #[deny(overflowing_literals)] const ASSOC_CONST: u8 = 1000; + | ^^^^^^^^^^^^^^^^^^^^ + = note: the literal `1000` does not fit into the type `u8` whose range is `0..=255` + +error: variable `PARAM` should have a snake case name + --> $DIR/lint-attr-everywhere-late.rs:131:37 + | +LL | fn function(#[deny(non_snake_case)] PARAM: i32) {} + | ^^^^^ help: convert the identifier to snake case: `param` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:131:20 + | +LL | fn function(#[deny(non_snake_case)] PARAM: i32) {} + | ^^^^^^^^^^^^^^ + +error: variable `PARAM` should have a snake case name + --> $DIR/lint-attr-everywhere-late.rs:145:44 + | +LL | let closure = |#[deny(non_snake_case)] PARAM: i32| {}; + | ^^^^^ help: convert the identifier to snake case: `param` + | +note: the lint level is defined here + --> $DIR/lint-attr-everywhere-late.rs:145:27 + | +LL | let closure = |#[deny(non_snake_case)] PARAM: i32| {}; + | ^^^^^^^^^^^^^^ + +error: aborting due to 31 previous errors +