1
Fork 0

Honor lint level attributes in more places.

This extends the LintLevelBuilder to handle lint level attributes on
struct expression fields and pattern fields.

This also updates the early lints to honor lint levels on generic
parameters.
This commit is contained in:
Eric Huss 2022-05-05 13:44:12 -07:00
parent b651c1cebe
commit 6c7cb2bb77
6 changed files with 1312 additions and 6 deletions

View file

@ -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) { fn visit_generic_param(&mut self, param: &'a ast::GenericParam) {
run_early_pass!(self, check_generic_param, param); self.with_lint_attrs(param.id, &param.attrs, |cx| {
self.check_id(param.id); run_early_pass!(cx, check_generic_param, param);
ast_visit::walk_generic_param(self, param); ast_visit::walk_generic_param(cx, param);
});
} }
fn visit_generics(&mut self, g: &'a ast::Generics) { fn visit_generics(&mut self, g: &'a ast::Generics) {

View file

@ -761,9 +761,26 @@ impl<'tcx> intravisit::Visitor<'tcx> for LintLevelMapBuilder<'tcx> {
} }
fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) { fn visit_expr(&mut self, e: &'tcx hir::Expr<'tcx>) {
match e.kind {
hir::ExprKind::Struct(qpath, fields, base_expr) => {
self.with_lint_attrs(e.hir_id, |builder| { 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); intravisit::walk_expr(builder, e);
}) }),
}
} }
fn visit_field_def(&mut self, s: &'tcx hir::FieldDef<'tcx>) { 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); 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) { pub fn provide(providers: &mut Providers) {

View file

@ -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<foo>() {} // 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() {}

View file

@ -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

View file

@ -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>) {} // dyn_drop
fn verify_no_warnings() {
discriminant::<i32>(&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<dyn Drop>) {} // 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<dyn Drop>) {} //~ ERROR types that do not implement `Drop`
#[deny(enum_intrinsics_non_enums)]
fn assoc_fn() { discriminant::<i32>(&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::<i32>(&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::<i32>(&123); //~ ERROR the return value of
}
}
match f {
#[deny(enum_intrinsics_non_enums)]
Match{f1} => {
discriminant::<i32>(&123); //~ ERROR the return value of
}
}
// Statement Block
{
#![deny(enum_intrinsics_non_enums)]
discriminant::<i32>(&123); //~ ERROR the return value of
}
let block_tail = {
#[deny(enum_intrinsics_non_enums)]
discriminant::<i32>(&123); //~ ERROR the return value of
};
// Before expression as a statement.
#[deny(enum_intrinsics_non_enums)]
discriminant::<i32>(&123); //~ ERROR the return value of
[#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)]; //~ ERROR the return value of
(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123),); //~ ERROR the return value of
fn call(p: Discriminant<i32>) {}
call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&123)); //~ ERROR the return value of
struct TupleStruct(Discriminant<i32>);
TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&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() {}

View file

@ -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<dyn Drop>) {}
| ^^^^
|
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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&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::<i32>(&123)];
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:179:13
|
LL | [#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&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::<i32>(&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::<i32>(&123),);
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:180:13
|
LL | (#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&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::<i32>(&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::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:182:17
|
LL | call(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&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::<i32>(&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::<i32>(&123));
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: the lint level is defined here
--> $DIR/lint-attr-everywhere-late.rs:184:24
|
LL | TupleStruct(#[deny(enum_intrinsics_non_enums)] discriminant::<i32>(&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::<i32>(&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