]>
git.proxmox.com Git - rustc.git/blob - src/librustc/lint/mod.rs
1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! Lints, aka compiler warnings.
13 //! A 'lint' check is a kind of miscellaneous constraint that a user _might_
14 //! want to enforce, but might reasonably want to permit as well, on a
15 //! module-by-module basis. They contrast with static constraints enforced by
16 //! other phases of the compiler, which are generally required to hold in order
17 //! to compile the program at all.
19 //! Most lints can be written as `LintPass` instances. These run just before
20 //! translation to LLVM bytecode. The `LintPass`es built into rustc are defined
21 //! within `builtin.rs`, which has further comments on how to add such a lint.
22 //! rustc can also load user-defined lint plugins via the plugin mechanism.
24 //! Some of rustc's lints are defined elsewhere in the compiler and work by
25 //! calling `add_lint()` on the overall `Session` object. This works when
26 //! it happens before the main lint pass, which emits the lints stored by
27 //! `add_lint()`. To emit lints after the main lint pass (from trans, for
28 //! example) requires more effort. See `emit_lint` and `GatherNodeLevels`
31 pub use self::Level
::*;
32 pub use self::LintSource
::*;
35 use std
::ascii
::AsciiExt
;
36 use syntax
::codemap
::Span
;
37 use hir
::intravisit
::FnKind
;
38 use syntax
::visit
as ast_visit
;
42 pub use lint
::context
::{LateContext
, EarlyContext
, LintContext
, LintStore
,
43 raw_emit_lint
, check_crate
, check_ast_crate
, gather_attrs
,
44 raw_struct_lint
, GatherNodeLevels
, FutureIncompatibleInfo
};
46 /// Specification of a single lint.
47 #[derive(Copy, Clone, Debug)]
49 /// A string identifier for the lint.
51 /// This identifies the lint in attributes and in command-line arguments.
52 /// In those contexts it is always lowercase, but this field is compared
53 /// in a way which is case-insensitive for ASCII characters. This allows
54 /// `declare_lint!()` invocations to follow the convention of upper-case
55 /// statics without repeating the name.
57 /// The name is written with underscores, e.g. "unused_imports".
58 /// On the command line, underscores become dashes.
59 pub name
: &'
static str,
61 /// Default level for the lint.
62 pub default_level
: Level
,
64 /// Description of the lint or the issue it detects.
66 /// e.g. "imports that are never used"
67 pub desc
: &'
static str,
71 /// Get the lint's name, with ASCII letters converted to lowercase.
72 pub fn name_lower(&self) -> String
{
73 self.name
.to_ascii_lowercase()
77 /// Build a `Lint` initializer.
79 macro_rules
! lint_initializer
{
80 ($name
:ident
, $level
:ident
, $desc
:expr
) => (
82 name
: stringify
!($name
),
83 default_level
: ::rustc
::lint
::$level
,
89 /// Declare a static item of type `&'static Lint`.
91 macro_rules
! declare_lint
{
92 (pub $name
:ident
, $level
:ident
, $desc
:expr
) => (
93 pub static $name
: &'
static ::rustc
::lint
::Lint
94 = &lint_initializer
!($name
, $level
, $desc
);
96 ($name
:ident
, $level
:ident
, $desc
:expr
) => (
97 static $name
: &'
static ::rustc
::lint
::Lint
98 = &lint_initializer
!($name
, $level
, $desc
);
102 /// Declare a static `LintArray` and return it as an expression.
104 macro_rules
! lint_array
{ ($
( $lint
:expr
),*) => (
106 static ARRAY
: LintArray
= &[ $
( &$lint
),* ];
111 pub type LintArray
= &'
static [&'
static &'
static Lint
];
114 /// Get descriptions of the lints this `LintPass` object can emit.
116 /// NB: there is no enforcement that the object only emits lints it registered.
117 /// And some `rustc` internal `LintPass`es register lints to be emitted by other
118 /// parts of the compiler. If you want enforced access restrictions for your
119 /// `Lint`, make it a private `static` item in its own module.
120 fn get_lints(&self) -> LintArray
;
124 /// Trait for types providing lint checks.
126 /// Each `check` method checks a single syntax node, and should not
127 /// invoke methods recursively (unlike `Visitor`). By default they
130 // FIXME: eliminate the duplication with `Visitor`. But this also
131 // contains a few lint-specific methods with no equivalent in `Visitor`.
132 pub trait LateLintPass
: LintPass
{
133 fn check_name(&mut self, _
: &LateContext
, _
: Span
, _
: ast
::Name
) { }
134 fn check_crate(&mut self, _
: &LateContext
, _
: &hir
::Crate
) { }
135 fn check_crate_post(&mut self, _
: &LateContext
, _
: &hir
::Crate
) { }
136 fn check_mod(&mut self, _
: &LateContext
, _
: &hir
::Mod
, _
: Span
, _
: ast
::NodeId
) { }
137 fn check_mod_post(&mut self, _
: &LateContext
, _
: &hir
::Mod
, _
: Span
, _
: ast
::NodeId
) { }
138 fn check_foreign_item(&mut self, _
: &LateContext
, _
: &hir
::ForeignItem
) { }
139 fn check_foreign_item_post(&mut self, _
: &LateContext
, _
: &hir
::ForeignItem
) { }
140 fn check_item(&mut self, _
: &LateContext
, _
: &hir
::Item
) { }
141 fn check_item_post(&mut self, _
: &LateContext
, _
: &hir
::Item
) { }
142 fn check_local(&mut self, _
: &LateContext
, _
: &hir
::Local
) { }
143 fn check_block(&mut self, _
: &LateContext
, _
: &hir
::Block
) { }
144 fn check_block_post(&mut self, _
: &LateContext
, _
: &hir
::Block
) { }
145 fn check_stmt(&mut self, _
: &LateContext
, _
: &hir
::Stmt
) { }
146 fn check_arm(&mut self, _
: &LateContext
, _
: &hir
::Arm
) { }
147 fn check_pat(&mut self, _
: &LateContext
, _
: &hir
::Pat
) { }
148 fn check_decl(&mut self, _
: &LateContext
, _
: &hir
::Decl
) { }
149 fn check_expr(&mut self, _
: &LateContext
, _
: &hir
::Expr
) { }
150 fn check_expr_post(&mut self, _
: &LateContext
, _
: &hir
::Expr
) { }
151 fn check_ty(&mut self, _
: &LateContext
, _
: &hir
::Ty
) { }
152 fn check_generics(&mut self, _
: &LateContext
, _
: &hir
::Generics
) { }
153 fn check_fn(&mut self, _
: &LateContext
,
154 _
: FnKind
, _
: &hir
::FnDecl
, _
: &hir
::Block
, _
: Span
, _
: ast
::NodeId
) { }
155 fn check_fn_post(&mut self, _
: &LateContext
,
156 _
: FnKind
, _
: &hir
::FnDecl
, _
: &hir
::Block
, _
: Span
, _
: ast
::NodeId
) { }
157 fn check_trait_item(&mut self, _
: &LateContext
, _
: &hir
::TraitItem
) { }
158 fn check_trait_item_post(&mut self, _
: &LateContext
, _
: &hir
::TraitItem
) { }
159 fn check_impl_item(&mut self, _
: &LateContext
, _
: &hir
::ImplItem
) { }
160 fn check_impl_item_post(&mut self, _
: &LateContext
, _
: &hir
::ImplItem
) { }
161 fn check_struct_def(&mut self, _
: &LateContext
,
162 _
: &hir
::VariantData
, _
: ast
::Name
, _
: &hir
::Generics
, _
: ast
::NodeId
) { }
163 fn check_struct_def_post(&mut self, _
: &LateContext
,
164 _
: &hir
::VariantData
, _
: ast
::Name
, _
: &hir
::Generics
, _
: ast
::NodeId
) { }
165 fn check_struct_field(&mut self, _
: &LateContext
, _
: &hir
::StructField
) { }
166 fn check_variant(&mut self, _
: &LateContext
, _
: &hir
::Variant
, _
: &hir
::Generics
) { }
167 fn check_variant_post(&mut self, _
: &LateContext
, _
: &hir
::Variant
, _
: &hir
::Generics
) { }
168 fn check_lifetime(&mut self, _
: &LateContext
, _
: &hir
::Lifetime
) { }
169 fn check_lifetime_def(&mut self, _
: &LateContext
, _
: &hir
::LifetimeDef
) { }
170 fn check_explicit_self(&mut self, _
: &LateContext
, _
: &hir
::ExplicitSelf
) { }
171 fn check_path(&mut self, _
: &LateContext
, _
: &hir
::Path
, _
: ast
::NodeId
) { }
172 fn check_path_list_item(&mut self, _
: &LateContext
, _
: &hir
::PathListItem
) { }
173 fn check_attribute(&mut self, _
: &LateContext
, _
: &ast
::Attribute
) { }
175 /// Called when entering a syntax node that can have lint attributes such
176 /// as `#[allow(...)]`. Called with *all* the attributes of that node.
177 fn enter_lint_attrs(&mut self, _
: &LateContext
, _
: &[ast
::Attribute
]) { }
179 /// Counterpart to `enter_lint_attrs`.
180 fn exit_lint_attrs(&mut self, _
: &LateContext
, _
: &[ast
::Attribute
]) { }
183 pub trait EarlyLintPass
: LintPass
{
184 fn check_ident(&mut self, _
: &EarlyContext
, _
: Span
, _
: ast
::Ident
) { }
185 fn check_crate(&mut self, _
: &EarlyContext
, _
: &ast
::Crate
) { }
186 fn check_crate_post(&mut self, _
: &EarlyContext
, _
: &ast
::Crate
) { }
187 fn check_mod(&mut self, _
: &EarlyContext
, _
: &ast
::Mod
, _
: Span
, _
: ast
::NodeId
) { }
188 fn check_mod_post(&mut self, _
: &EarlyContext
, _
: &ast
::Mod
, _
: Span
, _
: ast
::NodeId
) { }
189 fn check_foreign_item(&mut self, _
: &EarlyContext
, _
: &ast
::ForeignItem
) { }
190 fn check_foreign_item_post(&mut self, _
: &EarlyContext
, _
: &ast
::ForeignItem
) { }
191 fn check_item(&mut self, _
: &EarlyContext
, _
: &ast
::Item
) { }
192 fn check_item_post(&mut self, _
: &EarlyContext
, _
: &ast
::Item
) { }
193 fn check_local(&mut self, _
: &EarlyContext
, _
: &ast
::Local
) { }
194 fn check_block(&mut self, _
: &EarlyContext
, _
: &ast
::Block
) { }
195 fn check_block_post(&mut self, _
: &EarlyContext
, _
: &ast
::Block
) { }
196 fn check_stmt(&mut self, _
: &EarlyContext
, _
: &ast
::Stmt
) { }
197 fn check_arm(&mut self, _
: &EarlyContext
, _
: &ast
::Arm
) { }
198 fn check_pat(&mut self, _
: &EarlyContext
, _
: &ast
::Pat
) { }
199 fn check_decl(&mut self, _
: &EarlyContext
, _
: &ast
::Decl
) { }
200 fn check_expr(&mut self, _
: &EarlyContext
, _
: &ast
::Expr
) { }
201 fn check_expr_post(&mut self, _
: &EarlyContext
, _
: &ast
::Expr
) { }
202 fn check_ty(&mut self, _
: &EarlyContext
, _
: &ast
::Ty
) { }
203 fn check_generics(&mut self, _
: &EarlyContext
, _
: &ast
::Generics
) { }
204 fn check_fn(&mut self, _
: &EarlyContext
,
205 _
: ast_visit
::FnKind
, _
: &ast
::FnDecl
, _
: &ast
::Block
, _
: Span
, _
: ast
::NodeId
) { }
206 fn check_fn_post(&mut self, _
: &EarlyContext
,
207 _
: ast_visit
::FnKind
, _
: &ast
::FnDecl
, _
: &ast
::Block
, _
: Span
, _
: ast
::NodeId
) { }
208 fn check_trait_item(&mut self, _
: &EarlyContext
, _
: &ast
::TraitItem
) { }
209 fn check_trait_item_post(&mut self, _
: &EarlyContext
, _
: &ast
::TraitItem
) { }
210 fn check_impl_item(&mut self, _
: &EarlyContext
, _
: &ast
::ImplItem
) { }
211 fn check_impl_item_post(&mut self, _
: &EarlyContext
, _
: &ast
::ImplItem
) { }
212 fn check_struct_def(&mut self, _
: &EarlyContext
,
213 _
: &ast
::VariantData
, _
: ast
::Ident
, _
: &ast
::Generics
, _
: ast
::NodeId
) { }
214 fn check_struct_def_post(&mut self, _
: &EarlyContext
,
215 _
: &ast
::VariantData
, _
: ast
::Ident
, _
: &ast
::Generics
, _
: ast
::NodeId
) { }
216 fn check_struct_field(&mut self, _
: &EarlyContext
, _
: &ast
::StructField
) { }
217 fn check_variant(&mut self, _
: &EarlyContext
, _
: &ast
::Variant
, _
: &ast
::Generics
) { }
218 fn check_variant_post(&mut self, _
: &EarlyContext
, _
: &ast
::Variant
, _
: &ast
::Generics
) { }
219 fn check_lifetime(&mut self, _
: &EarlyContext
, _
: &ast
::Lifetime
) { }
220 fn check_lifetime_def(&mut self, _
: &EarlyContext
, _
: &ast
::LifetimeDef
) { }
221 fn check_explicit_self(&mut self, _
: &EarlyContext
, _
: &ast
::ExplicitSelf
) { }
222 fn check_path(&mut self, _
: &EarlyContext
, _
: &ast
::Path
, _
: ast
::NodeId
) { }
223 fn check_path_list_item(&mut self, _
: &EarlyContext
, _
: &ast
::PathListItem
) { }
224 fn check_attribute(&mut self, _
: &EarlyContext
, _
: &ast
::Attribute
) { }
226 /// Called when entering a syntax node that can have lint attributes such
227 /// as `#[allow(...)]`. Called with *all* the attributes of that node.
228 fn enter_lint_attrs(&mut self, _
: &EarlyContext
, _
: &[ast
::Attribute
]) { }
230 /// Counterpart to `enter_lint_attrs`.
231 fn exit_lint_attrs(&mut self, _
: &EarlyContext
, _
: &[ast
::Attribute
]) { }
234 /// A lint pass boxed up as a trait object.
235 pub type EarlyLintPassObject
= Box
<EarlyLintPass
+ '
static>;
236 pub type LateLintPassObject
= Box
<LateLintPass
+ '
static>;
238 /// Identifies a lint known to the compiler.
239 #[derive(Clone, Copy, Debug)]
241 // Identity is based on pointer equality of this field.
245 impl PartialEq
for LintId
{
246 fn eq(&self, other
: &LintId
) -> bool
{
247 (self.lint
as *const Lint
) == (other
.lint
as *const Lint
)
251 impl Eq
for LintId { }
253 impl hash
::Hash
for LintId
{
254 fn hash
<H
: hash
::Hasher
>(&self, state
: &mut H
) {
255 let ptr
= self.lint
as *const Lint
;
261 /// Get the `LintId` for a `Lint`.
262 pub fn of(lint
: &'
static Lint
) -> LintId
{
268 /// Get the name of the lint.
269 pub fn as_str(&self) -> String
{
270 self.lint
.name_lower()
274 /// Setting for how to handle a lint.
275 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug)]
277 Allow
, Warn
, Deny
, Forbid
281 /// Convert a level to a lower-case string.
282 pub fn as_str(self) -> &'
static str {
291 /// Convert a lower-case string to a level.
292 pub fn from_str(x
: &str) -> Option
<Level
> {
294 "allow" => Some(Allow
),
295 "warn" => Some(Warn
),
296 "deny" => Some(Deny
),
297 "forbid" => Some(Forbid
),
303 /// How a lint level was set.
304 #[derive(Clone, Copy, PartialEq, Eq)]
305 pub enum LintSource
{
306 /// Lint is at the default level as declared
307 /// in rustc or a plugin.
310 /// Lint level was set by an attribute.
313 /// Lint level was set by a command-line flag.
317 pub type LevelSource
= (Level
, LintSource
);