properly handle feature gated lints

- lint: add `feature_gate` field, allow specifying it in `declare_lint!`

- generalize the lint feature gate check

- librustdoc: generalize whitelisting of feature-gated lints
This commit is contained in:
Joey Hain 2020-06-03 19:16:29 -07:00
parent 56daaf669e
commit e7e6bc1126
4 changed files with 29 additions and 21 deletions

View File

@ -214,9 +214,9 @@ impl<'s> LintLevelsBuilder<'s> {
match store.check_lint_name(&name.as_str(), tool_name) {
CheckLintNameResult::Ok(ids) => {
let src = LintSource::Node(name, li.span(), reason);
for id in ids {
self.check_gated_lint(*id, attr.span);
specs.insert(*id, (level, src));
for &id in ids {
self.check_gated_lint(id, attr.span);
specs.insert(id, (level, src));
}
}
@ -386,17 +386,18 @@ impl<'s> LintLevelsBuilder<'s> {
BuilderPush { prev, changed: prev != self.cur }
}
fn check_gated_lint(&self, id: LintId, span: Span) {
if id == LintId::of(builtin::UNSAFE_OP_IN_UNSAFE_FN)
&& !self.sess.features_untracked().unsafe_block_in_unsafe_fn
{
feature_err(
&self.sess.parse_sess,
sym::unsafe_block_in_unsafe_fn,
span,
"the `unsafe_op_in_unsafe_fn` lint is unstable",
)
.emit();
/// Checks if the lint is gated on a feature that is not enabled.
fn check_gated_lint(&self, lint_id: LintId, span: Span) {
if let Some(feature) = lint_id.lint.feature_gate {
if !self.sess.features_untracked().enabled(feature) {
feature_err(
&self.sess.parse_sess,
feature,
span,
&format!("the `{}` lint is unstable", lint_id.lint.name_lower()),
)
.emit();
}
}
}

View File

@ -85,6 +85,9 @@ pub struct Lint {
pub future_incompatible: Option<FutureIncompatibleInfo>,
pub is_plugin: bool,
/// `Some` if this lint is feature gated, otherwise `None`.
pub feature_gate: Option<Symbol>,
}
/// Extra information for a future incompatibility lint.
@ -107,6 +110,7 @@ impl Lint {
is_plugin: false,
report_in_external_macro: false,
future_incompatible: None,
feature_gate: None,
}
}
@ -276,7 +280,9 @@ macro_rules! declare_lint {
);
);
($vis: vis $NAME: ident, $Level: ident, $desc: expr,
$(@future_incompatible = $fi:expr;)? $($v:ident),*) => (
$(@future_incompatible = $fi:expr;)?
$(@feature_gate = $gate:expr;)?
$($v:ident),*) => (
$vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
name: stringify!($NAME),
default_level: $crate::lint::$Level,
@ -285,6 +291,7 @@ macro_rules! declare_lint {
is_plugin: false,
$($v: true,)*
$(future_incompatible: Some($fi),)*
$(feature_gate: Some($gate),)*
..$crate::lint::Lint::default_fields_for_macro()
};
);
@ -328,6 +335,7 @@ macro_rules! declare_tool_lint {
report_in_external_macro: $external,
future_incompatible: None,
is_plugin: true,
feature_gate: None,
};
);
}

View File

@ -7,6 +7,7 @@
use crate::lint::FutureIncompatibleInfo;
use crate::{declare_lint, declare_lint_pass};
use rustc_span::edition::Edition;
use rustc_span::symbol::sym;
declare_lint! {
pub ILL_FORMED_ATTRIBUTE_INPUT,
@ -530,6 +531,7 @@ declare_lint! {
pub UNSAFE_OP_IN_UNSAFE_FN,
Allow,
"unsafe operations in unsafe functions without an explicit unsafe block are deprecated",
@feature_gate = sym::unsafe_block_in_unsafe_fn;
}
declare_lint_pass! {

View File

@ -225,11 +225,6 @@ where
{
let warnings_lint_name = lint::builtin::WARNINGS.name;
// Whitelist feature-gated lints to avoid feature errors when trying to
// allow all lints.
// FIXME(#72694): handle feature-gated lints properly.
let unsafe_op_in_unsafe_fn_name = rustc_lint::builtin::UNSAFE_OP_IN_UNSAFE_FN.name;
whitelisted_lints.push(warnings_lint_name.to_owned());
whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
@ -241,7 +236,9 @@ where
let lint_opts = lints()
.filter_map(|lint| {
if lint.name == warnings_lint_name || lint.name == unsafe_op_in_unsafe_fn_name {
// Whitelist feature-gated lints to avoid feature errors when trying to
// allow all lints.
if lint.name == warnings_lint_name || lint.feature_gate.is_some() {
None
} else {
filter_call(lint)