1 pub use self::Level::*;
2 use crate::node_id::NodeId;
3 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
4 use rustc_span::edition::Edition;
5 use rustc_span::{sym, MultiSpan, Symbol};
7 /// Setting for how to handle a lint.
8 #[derive(Clone, Copy, PartialEq, PartialOrd, Eq, Ord, Debug, Hash)]
16 rustc_data_structures::impl_stable_hash_via_hash!(Level);
19 /// Converts a level to a lower-case string.
20 pub fn as_str(self) -> &'static str {
22 Level::Allow => "allow",
23 Level::Warn => "warn",
24 Level::Deny => "deny",
25 Level::Forbid => "forbid",
29 /// Converts a lower-case string to a level.
30 pub fn from_str(x: &str) -> Option<Level> {
32 "allow" => Some(Level::Allow),
33 "warn" => Some(Level::Warn),
34 "deny" => Some(Level::Deny),
35 "forbid" => Some(Level::Forbid),
40 /// Converts a symbol to a level.
41 pub fn from_symbol(x: Symbol) -> Option<Level> {
43 sym::allow => Some(Level::Allow),
44 sym::warn => Some(Level::Warn),
45 sym::deny => Some(Level::Deny),
46 sym::forbid => Some(Level::Forbid),
52 /// Specification of a single lint.
53 #[derive(Copy, Clone, Debug)]
55 /// A string identifier for the lint.
57 /// This identifies the lint in attributes and in command-line arguments.
58 /// In those contexts it is always lowercase, but this field is compared
59 /// in a way which is case-insensitive for ASCII characters. This allows
60 /// `declare_lint!()` invocations to follow the convention of upper-case
61 /// statics without repeating the name.
63 /// The name is written with underscores, e.g., "unused_imports".
64 /// On the command line, underscores become dashes.
65 pub name: &'static str,
67 /// Default level for the lint.
68 pub default_level: Level,
70 /// Description of the lint or the issue it detects.
72 /// e.g., "imports that are never used"
73 pub desc: &'static str,
75 /// Starting at the given edition, default to the given lint level. If this is `None`, then use
77 pub edition_lint_opts: Option<(Edition, Level)>,
79 /// `true` if this lint is reported even inside expansions of external macros.
80 pub report_in_external_macro: bool,
82 pub future_incompatible: Option<FutureIncompatibleInfo>,
87 /// Extra information for a future incompatibility lint.
88 #[derive(Copy, Clone, Debug)]
89 pub struct FutureIncompatibleInfo {
90 /// e.g., a URL for an issue/PR/RFC or error code
91 pub reference: &'static str,
92 /// If this is an edition fixing lint, the edition in which
93 /// this lint becomes obsolete
94 pub edition: Option<Edition>,
98 pub const fn default_fields_for_macro() -> Self {
101 default_level: Level::Forbid,
103 edition_lint_opts: None,
105 report_in_external_macro: false,
106 future_incompatible: None,
110 /// Gets the lint's name, with ASCII letters converted to lowercase.
111 pub fn name_lower(&self) -> String {
112 self.name.to_ascii_lowercase()
115 pub fn default_level(&self, edition: Edition) -> Level {
116 self.edition_lint_opts
117 .filter(|(e, _)| *e <= edition)
119 .unwrap_or(self.default_level)
123 /// Identifies a lint known to the compiler.
124 #[derive(Clone, Copy, Debug)]
126 // Identity is based on pointer equality of this field.
127 pub lint: &'static Lint,
130 impl PartialEq for LintId {
131 fn eq(&self, other: &LintId) -> bool {
132 std::ptr::eq(self.lint, other.lint)
136 impl Eq for LintId {}
138 impl std::hash::Hash for LintId {
139 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
140 let ptr = self.lint as *const Lint;
146 /// Gets the `LintId` for a `Lint`.
147 pub fn of(lint: &'static Lint) -> LintId {
151 pub fn lint_name_raw(&self) -> &'static str {
155 /// Gets the name of the lint.
156 pub fn to_string(&self) -> String {
157 self.lint.name_lower()
161 impl<HCX> HashStable<HCX> for LintId {
163 fn hash_stable(&self, hcx: &mut HCX, hasher: &mut StableHasher) {
164 self.lint_name_raw().hash_stable(hcx, hasher);
168 impl<HCX> ToStableHashKey<HCX> for LintId {
169 type KeyType = &'static str;
172 fn to_stable_hash_key(&self, _: &HCX) -> &'static str {
177 /// Stores buffered lint info which can later be passed to `librustc`.
178 pub struct BufferedEarlyLint {
179 /// The span of code that we are linting on.
182 /// The lint message.
185 /// The `NodeId` of the AST node that generated the lint.
188 /// A lint Id that can be passed to `rustc::lint::Lint::from_parser_lint_id`.
189 pub lint_id: &'static Lint,
192 /// Declares a static item of type `&'static Lint`.
194 macro_rules! declare_lint {
195 ($vis: vis $NAME: ident, $Level: ident, $desc: expr) => (
196 $crate::declare_lint!(
197 $vis $NAME, $Level, $desc,
200 ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
201 $(@future_incompatible = $fi:expr;)? $($v:ident),*) => (
202 $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
203 name: stringify!($NAME),
204 default_level: $crate::lint::$Level,
206 edition_lint_opts: None,
209 $(future_incompatible: Some($fi),)*
210 ..$crate::lint::Lint::default_fields_for_macro()
213 ($vis: vis $NAME: ident, $Level: ident, $desc: expr,
214 $lint_edition: expr => $edition_level: ident
216 $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
217 name: stringify!($NAME),
218 default_level: $crate::lint::$Level,
220 edition_lint_opts: Some(($lint_edition, $crate::lint::Level::$edition_level)),
221 report_in_external_macro: false,
228 macro_rules! declare_tool_lint {
230 $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
232 $crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
235 $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
236 report_in_external_macro: $rep:expr
238 $crate::declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
241 $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
245 $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
246 name: &concat!(stringify!($tool), "::", stringify!($NAME)),
247 default_level: $crate::lint::$Level,
249 edition_lint_opts: None,
250 report_in_external_macro: $external,
251 future_incompatible: None,