mirror of
https://github.com/rust-lang/rust.git
synced 2026-04-26 13:01:27 +03:00
Auto merge of #152369 - Bryntet:lint_attrs, r=JonathanBrouwer,jdonszelmann
Port lint attributes to attribute parser *[View all comments](https://triagebot.infra.rust-lang.org/gh-comments/rust-lang/rust/pull/152369)* Tracking issue: rust-lang/rust#131229 Ports `#[allow]`, `#[deny]`, `#[expect]`, `#[forbid]`, and `#[warn]` to being parsed attrs I tried my best to make this PR as small as possible, it was difficult. I hope it isn't too difficult to review r? @JonathanBrouwer r? @jdonszelmann
This commit is contained in:
@@ -4224,7 +4224,6 @@ dependencies = [
|
||||
name = "rustc_lint_defs"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"rustc_ast",
|
||||
"rustc_data_structures",
|
||||
"rustc_error_messages",
|
||||
"rustc_hir_id",
|
||||
|
||||
@@ -154,7 +154,7 @@ struct LoweringContext<'a, 'hir, R> {
|
||||
|
||||
impl<'a, 'hir, R: ResolverAstLoweringExt<'hir>> LoweringContext<'a, 'hir, R> {
|
||||
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut R) -> Self {
|
||||
let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect();
|
||||
let registered_tools = tcx.registered_tools(());
|
||||
Self {
|
||||
tcx,
|
||||
resolver,
|
||||
|
||||
@@ -295,10 +295,15 @@ fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
|
||||
let span = self.span?;
|
||||
|
||||
let Some(tools) = cx.tools else {
|
||||
unreachable!("tools required while parsing attributes");
|
||||
};
|
||||
|
||||
let tools = tools.iter().map(|tool| tool.name).collect::<Vec<_>>();
|
||||
// only if we found a naked attribute do we do the somewhat expensive check
|
||||
'outer: for other_attr in cx.all_attrs {
|
||||
for allowed_attr in ALLOW_LIST {
|
||||
if other_attr.segments().next().is_some_and(|i| cx.tools.contains(&i.name)) {
|
||||
if other_attr.segments().next().is_some_and(|i| tools.contains(&i.name)) {
|
||||
// effectively skips the error message being emitted below
|
||||
// if it's a tool attribute
|
||||
continue 'outer;
|
||||
|
||||
@@ -0,0 +1,371 @@
|
||||
use rustc_ast::LitKind;
|
||||
use rustc_hir::HashIgnoredAttrId;
|
||||
use rustc_hir::attrs::{LintAttribute, LintAttributeKind, LintInstance};
|
||||
use rustc_hir::lints::AttributeLintKind;
|
||||
use rustc_hir::target::GenericParamKind;
|
||||
use rustc_session::DynLintStore;
|
||||
use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES};
|
||||
use rustc_session::lint::{CheckLintNameResult, LintId};
|
||||
|
||||
use super::prelude::*;
|
||||
use crate::attributes::AcceptFn;
|
||||
use crate::session_diagnostics::UnknownToolInScopedLint;
|
||||
|
||||
pub(crate) trait Lint {
|
||||
const KIND: LintAttributeKind;
|
||||
const ATTR_SYMBOL: Symbol = Self::KIND.symbol();
|
||||
}
|
||||
|
||||
pub(crate) struct Allow;
|
||||
|
||||
impl Lint for Allow {
|
||||
const KIND: LintAttributeKind = LintAttributeKind::Allow;
|
||||
}
|
||||
pub(crate) struct Deny;
|
||||
|
||||
impl Lint for Deny {
|
||||
const KIND: LintAttributeKind = LintAttributeKind::Deny;
|
||||
}
|
||||
pub(crate) struct Expect;
|
||||
|
||||
impl Lint for Expect {
|
||||
const KIND: LintAttributeKind = LintAttributeKind::Expect;
|
||||
}
|
||||
pub(crate) struct Forbid;
|
||||
|
||||
impl Lint for Forbid {
|
||||
const KIND: LintAttributeKind = LintAttributeKind::Forbid;
|
||||
}
|
||||
pub(crate) struct Warn;
|
||||
|
||||
impl Lint for Warn {
|
||||
const KIND: LintAttributeKind = LintAttributeKind::Warn;
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct LintParser {
|
||||
lint_attrs: ThinVec<LintAttribute>,
|
||||
}
|
||||
|
||||
trait Mapping<S: Stage> {
|
||||
const MAPPING: (&'static [Symbol], AttributeTemplate, AcceptFn<LintParser, S>);
|
||||
}
|
||||
impl<S: Stage, T: Lint> Mapping<S> for T {
|
||||
const MAPPING: (&'static [Symbol], AttributeTemplate, AcceptFn<LintParser, S>) = (
|
||||
&[T::ATTR_SYMBOL],
|
||||
template!(
|
||||
List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#],
|
||||
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
|
||||
),
|
||||
|this, cx, args| {
|
||||
if let Some(lint_attr) = validate_lint_attr::<T, S>(cx, args) {
|
||||
this.lint_attrs.push(lint_attr);
|
||||
}
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<S> for LintParser {
|
||||
const ATTRIBUTES: AcceptMapping<Self, S> =
|
||||
&[Allow::MAPPING, Deny::MAPPING, Expect::MAPPING, Forbid::MAPPING, Warn::MAPPING];
|
||||
|
||||
const ALLOWED_TARGETS: AllowedTargets = {
|
||||
use super::prelude::{Allow, Warn};
|
||||
AllowedTargets::AllowList(&[
|
||||
Allow(Target::ExternCrate),
|
||||
Allow(Target::Use),
|
||||
Allow(Target::Static),
|
||||
Allow(Target::Const),
|
||||
Allow(Target::Fn),
|
||||
Allow(Target::Closure),
|
||||
Allow(Target::Mod),
|
||||
Allow(Target::ForeignMod),
|
||||
Allow(Target::GlobalAsm),
|
||||
Allow(Target::TyAlias),
|
||||
Allow(Target::Enum),
|
||||
Allow(Target::Variant),
|
||||
Allow(Target::Struct),
|
||||
Allow(Target::Field),
|
||||
Allow(Target::Union),
|
||||
Allow(Target::Trait),
|
||||
Allow(Target::TraitAlias),
|
||||
Allow(Target::Impl { of_trait: false }),
|
||||
Allow(Target::Impl { of_trait: true }),
|
||||
Allow(Target::Expression),
|
||||
Allow(Target::Statement),
|
||||
Allow(Target::Arm),
|
||||
Allow(Target::AssocConst),
|
||||
Allow(Target::Method(MethodKind::Inherent)),
|
||||
Allow(Target::Method(MethodKind::Trait { body: false })),
|
||||
Allow(Target::Method(MethodKind::Trait { body: true })),
|
||||
Allow(Target::Method(MethodKind::TraitImpl)),
|
||||
Allow(Target::AssocTy),
|
||||
Allow(Target::ForeignFn),
|
||||
Allow(Target::ForeignStatic),
|
||||
Allow(Target::ForeignTy),
|
||||
Allow(Target::MacroDef),
|
||||
Allow(Target::Param),
|
||||
Allow(Target::PatField),
|
||||
Allow(Target::ExprField),
|
||||
Allow(Target::Crate),
|
||||
Allow(Target::Delegation { mac: false }),
|
||||
Allow(Target::Delegation { mac: true }),
|
||||
Allow(Target::GenericParam { kind: GenericParamKind::Type, has_default: false }),
|
||||
Allow(Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: false }),
|
||||
Allow(Target::GenericParam { kind: GenericParamKind::Const, has_default: false }),
|
||||
Allow(Target::GenericParam { kind: GenericParamKind::Type, has_default: true }),
|
||||
Allow(Target::GenericParam { kind: GenericParamKind::Lifetime, has_default: true }),
|
||||
Allow(Target::GenericParam { kind: GenericParamKind::Const, has_default: true }),
|
||||
Warn(Target::MacroCall),
|
||||
])
|
||||
};
|
||||
|
||||
fn finalize(mut self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
if !self.lint_attrs.is_empty() {
|
||||
// Sort to ensure correct order operations later
|
||||
self.lint_attrs.sort_by(|a, b| a.attr_span.cmp(&b.attr_span));
|
||||
Some(AttributeKind::LintAttributes(self.lint_attrs))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
fn validate_lint_attr<T: Lint, S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
args: &ArgParser,
|
||||
) -> Option<LintAttribute> {
|
||||
let Some(lint_store) = cx.sess.lint_store.as_ref().map(|store| store.to_owned()) else {
|
||||
unreachable!("lint_store required while parsing attributes");
|
||||
};
|
||||
let lint_store = lint_store.as_ref();
|
||||
let Some(list) = args.list() else {
|
||||
let span = cx.inner_span;
|
||||
cx.adcx().expected_list(span, args);
|
||||
return None;
|
||||
};
|
||||
let mut list = list.mixed().peekable();
|
||||
|
||||
let mut skip_unused_check = false;
|
||||
let mut errored = false;
|
||||
let mut reason = None;
|
||||
let mut lint_instances = ThinVec::new();
|
||||
let mut lint_index = 0;
|
||||
let targeting_crate = matches!(cx.target, Target::Crate);
|
||||
while let Some(item) = list.next() {
|
||||
let Some(meta_item) = item.meta_item() else {
|
||||
cx.adcx().expected_identifier(item.span());
|
||||
errored = true;
|
||||
continue;
|
||||
};
|
||||
|
||||
match meta_item.args() {
|
||||
ArgParser::NameValue(nv_parser) if meta_item.path().word_is(sym::reason) => {
|
||||
//FIXME replace this with duplicate check?
|
||||
if list.peek().is_some() {
|
||||
cx.adcx().expected_nv_as_last_argument(meta_item.span(), sym::reason);
|
||||
errored = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
let val_lit = nv_parser.value_as_lit();
|
||||
let LitKind::Str(reason_sym, _) = val_lit.kind else {
|
||||
cx.adcx().expected_string_literal(nv_parser.value_span, Some(val_lit));
|
||||
errored = true;
|
||||
continue;
|
||||
};
|
||||
reason = Some(reason_sym);
|
||||
}
|
||||
ArgParser::NameValue(_) => {
|
||||
cx.adcx().expected_specific_argument(meta_item.span(), &[sym::reason]);
|
||||
errored = true;
|
||||
}
|
||||
ArgParser::List(list) => {
|
||||
cx.adcx().expected_no_args(list.span);
|
||||
errored = true;
|
||||
}
|
||||
ArgParser::NoArgs => {
|
||||
skip_unused_check = true;
|
||||
let mut segments = meta_item.path().segments();
|
||||
|
||||
let Some(tool_or_name) = segments.next() else {
|
||||
unreachable!("first segment should always exist");
|
||||
};
|
||||
|
||||
let rest = segments.collect::<Vec<_>>();
|
||||
let (tool_name, tool_span, name): (Option<Symbol>, Option<Span>, _) =
|
||||
if rest.is_empty() {
|
||||
let name = tool_or_name.name;
|
||||
(None, None, name.to_string())
|
||||
} else {
|
||||
let tool = tool_or_name;
|
||||
let name = rest
|
||||
.into_iter()
|
||||
.map(|ident| ident.to_string())
|
||||
.collect::<Vec<_>>()
|
||||
.join("::");
|
||||
(Some(tool.name), Some(tool.span), name)
|
||||
};
|
||||
|
||||
let meta_item_span = meta_item.span();
|
||||
let original_name = Symbol::intern(&name);
|
||||
let mut full_name = tool_name
|
||||
.map(|tool| Symbol::intern(&format!("{tool}::{}", original_name)))
|
||||
.unwrap_or(original_name);
|
||||
|
||||
if let Some(ids) = check_lint(
|
||||
cx,
|
||||
lint_store,
|
||||
original_name,
|
||||
&mut full_name,
|
||||
tool_name,
|
||||
tool_span,
|
||||
meta_item_span,
|
||||
) {
|
||||
if !targeting_crate && ids.iter().any(|lint_id| lint_id.lint.crate_level_only) {
|
||||
cx.emit_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
AttributeLintKind::IgnoredUnlessCrateSpecified {
|
||||
level: T::ATTR_SYMBOL,
|
||||
name: original_name,
|
||||
},
|
||||
meta_item_span,
|
||||
);
|
||||
}
|
||||
lint_instances.extend(ids.into_iter().map(|id| {
|
||||
LintInstance::new(full_name, id.to_string(), meta_item_span, lint_index)
|
||||
}));
|
||||
}
|
||||
lint_index += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
if !skip_unused_check && !errored && lint_instances.is_empty() {
|
||||
let span = cx.attr_span;
|
||||
cx.adcx().warn_empty_attribute(span);
|
||||
}
|
||||
|
||||
(!errored).then_some(LintAttribute {
|
||||
reason,
|
||||
lint_instances,
|
||||
attr_span: cx.attr_span,
|
||||
attr_style: cx.attr_style,
|
||||
attr_id: HashIgnoredAttrId { attr_id: cx.attr_id },
|
||||
kind: T::KIND,
|
||||
})
|
||||
}
|
||||
|
||||
fn check_lint<'a, S: Stage>(
|
||||
cx: &mut AcceptContext<'_, '_, S>,
|
||||
lint_store: &'a dyn DynLintStore,
|
||||
original_name: Symbol,
|
||||
full_name: &mut Symbol,
|
||||
tool_name: Option<Symbol>,
|
||||
tool_span: Option<Span>,
|
||||
span: Span,
|
||||
) -> Option<&'a [LintId]> {
|
||||
let Some(tools) = cx.tools else {
|
||||
unreachable!("tools required while parsing attributes");
|
||||
};
|
||||
if tools.is_empty() {
|
||||
unreachable!("tools should never be empty")
|
||||
}
|
||||
|
||||
match lint_store.check_lint_name(original_name.as_str(), tool_name, tools) {
|
||||
CheckLintNameResult::Ok(ids) => Some(ids),
|
||||
CheckLintNameResult::Tool(ids, new_lint_name) => {
|
||||
let _name = match new_lint_name {
|
||||
None => original_name,
|
||||
Some(new_lint_name) => {
|
||||
let new_lint_name = Symbol::intern(&new_lint_name);
|
||||
cx.emit_lint(
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
AttributeLintKind::DeprecatedLintName {
|
||||
name: *full_name,
|
||||
suggestion: span,
|
||||
replace: new_lint_name,
|
||||
},
|
||||
span,
|
||||
);
|
||||
new_lint_name
|
||||
}
|
||||
};
|
||||
Some(ids)
|
||||
}
|
||||
|
||||
CheckLintNameResult::MissingTool => {
|
||||
// If `MissingTool` is returned, then either the lint does not
|
||||
// exist in the tool or the code was not compiled with the tool and
|
||||
// therefore the lint was never added to the `LintStore`. To detect
|
||||
// this is the responsibility of the lint tool.
|
||||
None
|
||||
}
|
||||
|
||||
CheckLintNameResult::NoTool => {
|
||||
cx.emit_err(UnknownToolInScopedLint {
|
||||
span: tool_span,
|
||||
tool_name: tool_name.unwrap(),
|
||||
full_lint_name: *full_name,
|
||||
is_nightly_build: cx.sess.is_nightly_build(),
|
||||
});
|
||||
None
|
||||
}
|
||||
|
||||
CheckLintNameResult::Renamed(replace) => {
|
||||
cx.emit_lint(
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
AttributeLintKind::RenamedLint { name: *full_name, replace, suggestion: span },
|
||||
span,
|
||||
);
|
||||
|
||||
// Since it was renamed, and we have emitted the warning
|
||||
// we replace the "full_name", to ensure we don't get notes with:
|
||||
// `#[allow(NEW_NAME)]` implied by `#[allow(OLD_NAME)]`
|
||||
// Other lints still have access to the original name as the user wrote it,
|
||||
// through `original_name`
|
||||
*full_name = replace;
|
||||
|
||||
// If this lint was renamed, apply the new lint instead of ignoring the
|
||||
// attribute. Ignore any errors or warnings that happen because the new
|
||||
// name is inaccurate.
|
||||
// NOTE: `new_name` already includes the tool name, so we don't
|
||||
// have to add it again.
|
||||
match lint_store.check_lint_name(replace.as_str(), None, tools) {
|
||||
CheckLintNameResult::Ok(ids) => Some(ids),
|
||||
_ => panic!("renamed lint does not exist: {replace}"),
|
||||
}
|
||||
}
|
||||
|
||||
CheckLintNameResult::RenamedToolLint(new_name) => {
|
||||
cx.emit_lint(
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
AttributeLintKind::RenamedLint {
|
||||
name: *full_name,
|
||||
replace: new_name,
|
||||
suggestion: span,
|
||||
},
|
||||
span,
|
||||
);
|
||||
None
|
||||
}
|
||||
|
||||
CheckLintNameResult::Removed(reason) => {
|
||||
cx.emit_lint(
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
AttributeLintKind::RemovedLint { name: *full_name, reason },
|
||||
span,
|
||||
);
|
||||
None
|
||||
}
|
||||
|
||||
CheckLintNameResult::NoLint(suggestion) => {
|
||||
cx.emit_lint(
|
||||
UNKNOWN_LINTS,
|
||||
AttributeLintKind::UnknownLint { name: *full_name, suggestion, span },
|
||||
span,
|
||||
);
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -46,6 +46,7 @@
|
||||
pub(crate) mod inline;
|
||||
pub(crate) mod instruction_set;
|
||||
pub(crate) mod link_attrs;
|
||||
pub(crate) mod lint;
|
||||
pub(crate) mod lint_helpers;
|
||||
pub(crate) mod loop_match;
|
||||
pub(crate) mod macro_attrs;
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
use rustc_parse::parser::Recovery;
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::{Lint, LintId};
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
use rustc_span::{AttrId, ErrorGuaranteed, Span, Symbol};
|
||||
|
||||
use crate::AttributeParser;
|
||||
// Glob imports to avoid big, bitrotty import lists
|
||||
@@ -37,6 +37,7 @@
|
||||
use crate::attributes::inline::*;
|
||||
use crate::attributes::instruction_set::*;
|
||||
use crate::attributes::link_attrs::*;
|
||||
use crate::attributes::lint::*;
|
||||
use crate::attributes::lint_helpers::*;
|
||||
use crate::attributes::loop_match::*;
|
||||
use crate::attributes::macro_attrs::*;
|
||||
@@ -149,6 +150,7 @@ mod late {
|
||||
ConfusablesParser,
|
||||
ConstStabilityParser,
|
||||
DocParser,
|
||||
LintParser,
|
||||
MacroUseParser,
|
||||
NakedParser,
|
||||
OnConstParser,
|
||||
@@ -445,6 +447,8 @@ pub struct AcceptContext<'f, 'sess, S: Stage> {
|
||||
|
||||
/// The name of the attribute we're currently accepting.
|
||||
pub(crate) attr_path: AttrPath,
|
||||
|
||||
pub(crate) attr_id: AttrId,
|
||||
}
|
||||
|
||||
impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> {
|
||||
@@ -804,6 +808,17 @@ pub(crate) fn expected_specific_argument_strings(
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn expected_nv_as_last_argument(
|
||||
&mut self,
|
||||
span: Span,
|
||||
name_value_key: Symbol,
|
||||
) -> ErrorGuaranteed {
|
||||
self.emit_parse_error(
|
||||
span,
|
||||
AttributeParseErrorReason::ExpectedNameValueAsLastArgument { span, name_value_key },
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn warn_empty_attribute(&mut self, span: Span) {
|
||||
let attr_path = self.attr_path.clone().to_string();
|
||||
let valid_without_list = self.template.word;
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::token::DocFragmentKind;
|
||||
use rustc_ast::{AttrItemKind, AttrStyle, NodeId, Safety};
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_errors::DiagCtxtHandle;
|
||||
use rustc_feature::{AttributeTemplate, Features};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
@@ -10,7 +11,7 @@
|
||||
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::{BuiltinLintDiag, LintId};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
|
||||
|
||||
use crate::context::{AcceptContext, FinalizeContext, FinalizeFn, SharedContext, Stage};
|
||||
use crate::early_parsed::{EARLY_PARSED_ATTRIBUTES, EarlyParsedState};
|
||||
@@ -21,7 +22,7 @@
|
||||
/// Context created once, for example as part of the ast lowering
|
||||
/// context, through which all attributes can be lowered.
|
||||
pub struct AttributeParser<'sess, S: Stage = Late> {
|
||||
pub(crate) tools: Vec<Symbol>,
|
||||
pub(crate) tools: Option<&'sess FxIndexSet<Ident>>,
|
||||
pub(crate) features: Option<&'sess Features>,
|
||||
pub(crate) sess: &'sess Session,
|
||||
pub(crate) stage: S,
|
||||
@@ -47,6 +48,8 @@ impl<'sess> AttributeParser<'sess, Early> {
|
||||
/// No diagnostics will be emitted when parsing limited. Lints are not emitted at all, while
|
||||
/// errors will be emitted as a delayed bugs. in other words, we *expect* attributes parsed
|
||||
/// with `parse_limited` to be reparsed later during ast lowering where we *do* emit the errors
|
||||
///
|
||||
/// Due to this function not taking in RegisteredTools (`FxIndexSet<Ident>`), *do not* use this for parsing any lint attributes
|
||||
pub fn parse_limited(
|
||||
sess: &'sess Session,
|
||||
attrs: &[ast::Attribute],
|
||||
@@ -68,6 +71,8 @@ pub fn parse_limited(
|
||||
|
||||
/// This does the same as `parse_limited`, except it has a `should_emit` parameter which allows it to emit errors.
|
||||
/// Usually you want `parse_limited`, which emits no errors.
|
||||
///
|
||||
/// Due to this function not taking in RegisteredTools (`FxIndexSet<Ident>`), *do not* use this for parsing any lint attributes
|
||||
pub fn parse_limited_should_emit(
|
||||
sess: &'sess Session,
|
||||
attrs: &[ast::Attribute],
|
||||
@@ -86,6 +91,7 @@ pub fn parse_limited_should_emit(
|
||||
target_node_id,
|
||||
features,
|
||||
should_emit,
|
||||
None,
|
||||
);
|
||||
assert!(parsed.len() <= 1);
|
||||
parsed.pop()
|
||||
@@ -98,18 +104,18 @@ pub fn parse_limited_should_emit(
|
||||
/// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
|
||||
/// crash if you tried to do so through [`parse_limited_all`](Self::parse_limited_all).
|
||||
/// Therefore, if `parse_only` is None, then features *must* be provided.
|
||||
pub fn parse_limited_all(
|
||||
pub fn parse_limited_all<'a>(
|
||||
sess: &'sess Session,
|
||||
attrs: &[ast::Attribute],
|
||||
attrs: impl IntoIterator<Item = &'a ast::Attribute>,
|
||||
parse_only: Option<Symbol>,
|
||||
target: Target,
|
||||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
features: Option<&'sess Features>,
|
||||
emit_errors: ShouldEmit,
|
||||
tools: Option<&'sess FxIndexSet<Ident>>,
|
||||
) -> Vec<Attribute> {
|
||||
let mut p =
|
||||
Self { features, tools: Vec::new(), parse_only, sess, stage: Early { emit_errors } };
|
||||
let mut p = Self { features, tools, parse_only, sess, stage: Early { emit_errors } };
|
||||
p.parse_attribute_list(
|
||||
attrs,
|
||||
target_span,
|
||||
@@ -127,6 +133,32 @@ pub fn parse_limited_all(
|
||||
)
|
||||
}
|
||||
|
||||
/// This method provides the same functionality as [`parse_limited_all`](Self::parse_limited_all) except filtered,
|
||||
/// making sure that only allow-listed symbols are parsed
|
||||
pub fn parse_limited_all_filtered<'a>(
|
||||
sess: &'sess Session,
|
||||
attrs: impl IntoIterator<Item = &'a ast::Attribute>,
|
||||
filter: &[Symbol],
|
||||
target: Target,
|
||||
target_span: Span,
|
||||
target_node_id: NodeId,
|
||||
features: Option<&'sess Features>,
|
||||
emit_errors: ShouldEmit,
|
||||
tools: &'sess FxIndexSet<Ident>,
|
||||
) -> Vec<Attribute> {
|
||||
Self::parse_limited_all(
|
||||
sess,
|
||||
attrs.into_iter().filter(|attr| attr.has_any_name(filter)),
|
||||
None,
|
||||
target,
|
||||
target_span,
|
||||
target_node_id,
|
||||
features,
|
||||
emit_errors,
|
||||
Some(tools),
|
||||
)
|
||||
}
|
||||
|
||||
/// This method parses a single attribute, using `parse_fn`.
|
||||
/// This is useful if you already know what exact attribute this is, and want to parse it.
|
||||
pub fn parse_single<T>(
|
||||
@@ -193,13 +225,8 @@ pub fn parse_single_args<T, I>(
|
||||
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &I) -> T,
|
||||
template: &AttributeTemplate,
|
||||
) -> T {
|
||||
let mut parser = Self {
|
||||
features,
|
||||
tools: Vec::new(),
|
||||
parse_only: None,
|
||||
sess,
|
||||
stage: Early { emit_errors },
|
||||
};
|
||||
let mut parser =
|
||||
Self { features, tools: None, parse_only: None, sess, stage: Early { emit_errors } };
|
||||
let mut emit_lint = |lint_id: LintId, span: Span, kind: AttributeLintKind| {
|
||||
sess.psess.buffer_lint(
|
||||
lint_id.lint,
|
||||
@@ -211,6 +238,7 @@ pub fn parse_single_args<T, I>(
|
||||
if let Some(safety) = attr_safety {
|
||||
parser.check_attribute_safety(&attr_path, inner_span, safety, &mut emit_lint)
|
||||
}
|
||||
let attr_id = sess.psess.attr_id_generator.mk_attr_id();
|
||||
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
|
||||
shared: SharedContext {
|
||||
cx: &mut parser,
|
||||
@@ -224,6 +252,7 @@ pub fn parse_single_args<T, I>(
|
||||
parsed_description,
|
||||
template,
|
||||
attr_path,
|
||||
attr_id,
|
||||
};
|
||||
parse_fn(&mut cx, args)
|
||||
}
|
||||
@@ -233,10 +262,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
||||
pub fn new(
|
||||
sess: &'sess Session,
|
||||
features: &'sess Features,
|
||||
tools: Vec<Symbol>,
|
||||
tools: &'sess FxIndexSet<Ident>,
|
||||
stage: S,
|
||||
) -> Self {
|
||||
Self { features: Some(features), tools, parse_only: None, sess, stage }
|
||||
Self { features: Some(features), tools: Some(tools), parse_only: None, sess, stage }
|
||||
}
|
||||
|
||||
pub(crate) fn sess(&self) -> &'sess Session {
|
||||
@@ -259,9 +288,9 @@ pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
|
||||
///
|
||||
/// `target_span` is the span of the thing this list of attributes is applied to,
|
||||
/// and when `omit_doc` is set, doc attributes are filtered out.
|
||||
pub fn parse_attribute_list(
|
||||
pub fn parse_attribute_list<'a>(
|
||||
&mut self,
|
||||
attrs: &[ast::Attribute],
|
||||
attrs: impl IntoIterator<Item = &'a ast::Attribute>,
|
||||
target_span: Span,
|
||||
target: Target,
|
||||
omit_doc: OmitDoc,
|
||||
@@ -277,9 +306,9 @@ pub fn parse_attribute_list(
|
||||
let mut attr_paths: Vec<RefPathParser<'_>> = Vec::new();
|
||||
let mut early_parsed_state = EarlyParsedState::default();
|
||||
|
||||
let mut finalizers: Vec<&FinalizeFn<S>> = Vec::with_capacity(attrs.len());
|
||||
let mut finalizers: Vec<&FinalizeFn<S>> = Vec::new();
|
||||
|
||||
for attr in attrs {
|
||||
for attr in attrs.into_iter() {
|
||||
// If we're only looking for a single attribute, skip all the ones we don't care about.
|
||||
if let Some(expected) = self.parse_only {
|
||||
if !attr.has_name(expected) {
|
||||
@@ -389,6 +418,7 @@ pub fn parse_attribute_list(
|
||||
parsed_description: ParsedDescription::Attribute,
|
||||
template: &accept.template,
|
||||
attr_path: attr_path.clone(),
|
||||
attr_id: attr.id,
|
||||
};
|
||||
|
||||
(accept.accept_fn)(&mut cx, &args);
|
||||
@@ -415,11 +445,9 @@ pub fn parse_attribute_list(
|
||||
|
||||
let attr = Attribute::Unparsed(Box::new(attr));
|
||||
|
||||
if self.tools.contains(&parts[0])
|
||||
// FIXME: this can be removed once #152369 has been merged.
|
||||
// https://github.com/rust-lang/rust/pull/152369
|
||||
|| [sym::allow, sym::deny, sym::expect, sym::forbid, sym::warn]
|
||||
.contains(&parts[0])
|
||||
if self
|
||||
.tools
|
||||
.is_some_and(|tools| tools.iter().any(|tool| tool.name == parts[0]))
|
||||
{
|
||||
attributes.push(attr);
|
||||
} else {
|
||||
|
||||
@@ -575,6 +575,10 @@ pub(crate) enum AttributeParseErrorReason<'a> {
|
||||
list: bool,
|
||||
},
|
||||
ExpectedIdentifier,
|
||||
ExpectedNameValueAsLastArgument {
|
||||
span: Span,
|
||||
name_value_key: Symbol,
|
||||
},
|
||||
}
|
||||
|
||||
/// A description of a thing that can be parsed using an attribute parser.
|
||||
@@ -835,6 +839,12 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> {
|
||||
AttributeParseErrorReason::ExpectedIdentifier => {
|
||||
diag.span_label(self.span, "expected a valid identifier here");
|
||||
}
|
||||
AttributeParseErrorReason::ExpectedNameValueAsLastArgument { span, name_value_key } => {
|
||||
diag.span_label(
|
||||
*span,
|
||||
format!("expected {name_value_key} = \"...\" to be the last argument"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(link) = self.template.docs {
|
||||
@@ -1128,3 +1138,14 @@ pub(crate) struct UnstableAttrForAlreadyStableFeature {
|
||||
#[label("the stability attribute annotates this item")]
|
||||
pub item_span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("unknown tool name `{$tool_name}` found in scoped lint: `{$full_lint_name}`", code = E0710)]
|
||||
pub(crate) struct UnknownToolInScopedLint {
|
||||
#[primary_span]
|
||||
pub span: Option<Span>,
|
||||
pub tool_name: Symbol,
|
||||
pub full_lint_name: Symbol,
|
||||
#[help("add `#![register_tool({$tool_name})]` to the crate root")]
|
||||
pub is_nightly_build: bool,
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
#### Note: this error code is no longer emitted by the compiler
|
||||
An invalid lint attribute has been given.
|
||||
|
||||
Erroneous code example:
|
||||
|
||||
```compile_fail,E0452
|
||||
```compile_fail
|
||||
#![allow(foo = "")] // error: malformed lint attribute
|
||||
```
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
use rustc_ast::attr::MarkedAttrs;
|
||||
use rustc_ast::tokenstream::TokenStream;
|
||||
use rustc_ast::visit::{AssocCtxt, Visitor};
|
||||
use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind, Safety};
|
||||
use rustc_ast::{self as ast, AttrVec, HasAttrs, Item, NodeId, PatKind, Safety};
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
|
||||
use rustc_data_structures::sync;
|
||||
use rustc_errors::{BufferedEarlyLint, DiagCtxtHandle, ErrorGuaranteed, PResult};
|
||||
@@ -1188,7 +1188,6 @@ fn pre_expansion_lint(
|
||||
features: &Features,
|
||||
registered_tools: &RegisteredTools,
|
||||
node_id: NodeId,
|
||||
attrs: &[Attribute],
|
||||
items: &[Box<Item>],
|
||||
name: Symbol,
|
||||
);
|
||||
|
||||
@@ -1403,7 +1403,6 @@ fn wrap_flat_map_node_walk_flat_map(
|
||||
ecx.ecfg.features,
|
||||
ecx.resolver.registered_tools(),
|
||||
ecx.current_expansion.lint_node_id,
|
||||
&attrs,
|
||||
&items,
|
||||
ident.name,
|
||||
);
|
||||
@@ -2258,6 +2257,7 @@ fn check_attributes(&self, attrs: &[ast::Attribute], call: &ast::MacCall) {
|
||||
self.cx.current_expansion.lint_node_id,
|
||||
Some(self.cx.ecfg.features),
|
||||
ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed },
|
||||
Some(self.cx.resolver.registered_tools()),
|
||||
);
|
||||
|
||||
let current_span = if let Some(sp) = span { sp.to(attr.span) } else { attr.span };
|
||||
|
||||
@@ -15,14 +15,16 @@
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic, PrintAttribute};
|
||||
use rustc_span::def_id::DefId;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};
|
||||
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, sym};
|
||||
pub use rustc_target::spec::SanitizerSet;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::attrs::diagnostic::*;
|
||||
use crate::attrs::pretty_printing::PrintAttribute;
|
||||
use crate::limit::Limit;
|
||||
use crate::{DefaultBodyStability, PartialConstStability, RustcVersion, Stability};
|
||||
use crate::{
|
||||
DefaultBodyStability, HashIgnoredAttrId, PartialConstStability, RustcVersion, Stability,
|
||||
};
|
||||
|
||||
#[derive(Copy, Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
|
||||
pub enum EiiImplResolution {
|
||||
@@ -894,6 +896,143 @@ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute)]
|
||||
pub struct LintAttribute {
|
||||
/// See RFC #2383
|
||||
pub reason: Option<Symbol>,
|
||||
pub kind: LintAttributeKind,
|
||||
pub attr_style: AttrStyle,
|
||||
pub attr_span: Span,
|
||||
/// Needed by `LintExpectationId` to track fulfilled expectations
|
||||
pub attr_id: HashIgnoredAttrId,
|
||||
pub lint_instances: ThinVec<LintInstance>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Encodable, Decodable, HashStable_Generic)]
|
||||
pub struct LintInstance {
|
||||
/// The span of the `MetaItem` that produced this `LintInstance`
|
||||
span: Span,
|
||||
/// The fully resolved name of the lint
|
||||
/// for renamed lints, this gets updated to match the new name
|
||||
lint_name: Symbol,
|
||||
/// The raw identifier for resolving this lint
|
||||
/// if this is none, lint_name never diffed from the original
|
||||
/// name after parsing, original_name.unwrap_or(self.lint_name)
|
||||
original_name: Option<Symbol>,
|
||||
/// Index of this lint, used to keep track of lint groups
|
||||
lint_index: usize,
|
||||
kind: LintAttrTool,
|
||||
}
|
||||
|
||||
impl fmt::Display for LintInstance {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
self.full_lint().fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
impl LintInstance {
|
||||
pub fn new(
|
||||
original_name: Symbol,
|
||||
long_lint_name: String,
|
||||
span: Span,
|
||||
lint_index: usize,
|
||||
) -> Self {
|
||||
let original_name = (original_name.as_str() != long_lint_name).then_some(original_name);
|
||||
let mut tool_name = None;
|
||||
|
||||
let lint_name = match long_lint_name.split_once("::") {
|
||||
Some((new_tool_name, lint_name)) => {
|
||||
tool_name = Some(Symbol::intern(new_tool_name));
|
||||
Symbol::intern(lint_name)
|
||||
}
|
||||
None => Symbol::intern(&long_lint_name),
|
||||
};
|
||||
let kind = match tool_name {
|
||||
Some(tool_name) => {
|
||||
let full_lint = Symbol::intern(&format!("{tool_name}::{lint_name}",));
|
||||
LintAttrTool::Present { tool_name, full_lint }
|
||||
}
|
||||
None => LintAttrTool::NoTool,
|
||||
};
|
||||
|
||||
Self { original_name, span, lint_index, lint_name, kind }
|
||||
}
|
||||
|
||||
pub fn full_lint(&self) -> Symbol {
|
||||
match self.kind {
|
||||
LintAttrTool::Present { full_lint, .. } => full_lint,
|
||||
LintAttrTool::NoTool => self.lint_name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn span(&self) -> Span {
|
||||
self.span
|
||||
}
|
||||
|
||||
pub fn lint_index(&self) -> usize {
|
||||
self.lint_index
|
||||
}
|
||||
|
||||
pub fn lint_name(&self) -> Symbol {
|
||||
self.lint_name
|
||||
}
|
||||
|
||||
pub fn original_name_without_tool(&self) -> Symbol {
|
||||
let full_original_lint_name = self.original_lint_name();
|
||||
match self.kind {
|
||||
LintAttrTool::Present { tool_name, .. } => Symbol::intern(
|
||||
full_original_lint_name
|
||||
.as_str()
|
||||
.trim_start_matches(tool_name.as_str())
|
||||
.trim_start_matches("::"),
|
||||
),
|
||||
LintAttrTool::NoTool => full_original_lint_name,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tool_name(&self) -> Option<Symbol> {
|
||||
if let LintAttrTool::Present { tool_name, .. } = self.kind { Some(tool_name) } else { None }
|
||||
}
|
||||
|
||||
pub fn tool_is_named(&self, other: Symbol) -> bool {
|
||||
self.tool_name().is_some_and(|tool_name| tool_name == other)
|
||||
}
|
||||
|
||||
pub fn original_lint_name(&self) -> Symbol {
|
||||
match self.original_name {
|
||||
Some(name) => name,
|
||||
None => self.full_lint(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PrintAttribute, Encodable, Decodable, HashStable_Generic)]
|
||||
enum LintAttrTool {
|
||||
Present { tool_name: Symbol, full_lint: Symbol },
|
||||
NoTool,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, HashStable_Generic, Encodable, Decodable, PrintAttribute, PartialEq)]
|
||||
pub enum LintAttributeKind {
|
||||
Allow,
|
||||
Deny,
|
||||
Expect,
|
||||
Forbid,
|
||||
Warn,
|
||||
}
|
||||
|
||||
impl LintAttributeKind {
|
||||
pub const fn symbol(&self) -> Symbol {
|
||||
match self {
|
||||
Self::Allow => sym::allow,
|
||||
Self::Deny => sym::deny,
|
||||
Self::Expect => sym::expect,
|
||||
Self::Forbid => sym::forbid,
|
||||
Self::Warn => sym::warn,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents parsed *built-in* inert attributes.
|
||||
///
|
||||
/// ## Overview
|
||||
@@ -1097,6 +1236,9 @@ pub enum AttributeKind {
|
||||
/// Represents `#[linkage]`.
|
||||
Linkage(Linkage, Span),
|
||||
|
||||
/// Represents `#[allow]`, `#[expect]`, `#[warn]`, `#[deny]`, `#[forbid]`
|
||||
LintAttributes(ThinVec<LintAttribute>),
|
||||
|
||||
/// Represents `#[loop_match]`.
|
||||
LoopMatch(Span),
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ pub fn encode_cross_crate(&self) -> EncodeCrossCrate {
|
||||
LinkOrdinal { .. } => No,
|
||||
LinkSection { .. } => Yes, // Needed for rustdoc
|
||||
Linkage(..) => No,
|
||||
LintAttributes { .. } => No,
|
||||
LoopMatch(..) => No,
|
||||
MacroEscape(..) => No,
|
||||
MacroExport { .. } => Yes,
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
use rustc_target::spec::SanitizerSet;
|
||||
use thin_vec::ThinVec;
|
||||
|
||||
use crate::HashIgnoredAttrId;
|
||||
use crate::attrs::LintInstance;
|
||||
use crate::limit::Limit;
|
||||
|
||||
/// This trait is used to print attributes in `rustc_hir_pretty`.
|
||||
@@ -191,8 +193,8 @@ fn print_attribute(&self, p: &mut Printer) {
|
||||
}
|
||||
|
||||
print_tup!(A B C D E F G H);
|
||||
print_skip!(Span, (), ErrorGuaranteed, AttrId);
|
||||
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit);
|
||||
print_skip!(Span, (), ErrorGuaranteed, AttrId, HashIgnoredAttrId);
|
||||
print_disp!(u8, u16, u32, u128, usize, bool, NonZero<u32>, Limit, LintInstance);
|
||||
print_debug!(
|
||||
Symbol,
|
||||
Ident,
|
||||
|
||||
@@ -1304,6 +1304,19 @@ pub fn is_parsed_attr(&self) -> bool {
|
||||
Attribute::Unparsed(_) => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn has_span_without_desugaring_kind(&self) -> bool {
|
||||
let span = match self {
|
||||
Attribute::Unparsed(attr) => attr.span,
|
||||
Attribute::Parsed(AttributeKind::Deprecated { span, .. }) => *span,
|
||||
Attribute::Parsed(AttributeKind::LintAttributes(sub_attrs)) => {
|
||||
return sub_attrs.iter().any(|attr| attr.attr_span.desugaring_kind().is_none());
|
||||
}
|
||||
Attribute::Parsed(attr) => panic!("can't get span of parsed attr: {:?}", attr),
|
||||
};
|
||||
|
||||
span.desugaring_kind().is_none()
|
||||
}
|
||||
}
|
||||
|
||||
impl AttributeExt for Attribute {
|
||||
@@ -1378,6 +1391,7 @@ fn span(&self) -> Span {
|
||||
Attribute::Parsed(AttributeKind::DocComment { span, .. }) => *span,
|
||||
Attribute::Parsed(AttributeKind::Deprecated { span, .. }) => *span,
|
||||
Attribute::Parsed(AttributeKind::CfgTrace(cfgs)) => cfgs[0].1,
|
||||
Attribute::Parsed(AttributeKind::LintAttributes(sub_attrs)) => sub_attrs[0].attr_span,
|
||||
a => panic!("can't get the span of an arbitrary parsed attribute: {a:?}"),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,11 +16,10 @@
|
||||
Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, Subdiagnostic, listify, pluralize,
|
||||
struct_span_code_err,
|
||||
};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def::{CtorKind, DefKind, Res};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_hir::lang_items::LangItem;
|
||||
use rustc_hir::{ExprKind, HirId, QPath, find_attr, is_range_literal};
|
||||
use rustc_hir::{self as hir, Attribute, ExprKind, HirId, QPath, find_attr, is_range_literal};
|
||||
use rustc_hir_analysis::NoVariantNamed;
|
||||
use rustc_hir_analysis::errors::NoFieldOnType;
|
||||
use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _;
|
||||
@@ -56,26 +55,21 @@
|
||||
|
||||
impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
||||
pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
|
||||
// For the purpose of rendering suggestions, disregard attributes
|
||||
// that originate from desugaring of any kind. For example, `x?`
|
||||
// desugars to `#[allow(unreachable_code)] match ...`. Failing to
|
||||
// ignore the prefix attribute in the desugaring would cause this
|
||||
// suggestion:
|
||||
//
|
||||
// let y: u32 = x?.try_into().unwrap();
|
||||
// ++++++++++++++++++++
|
||||
//
|
||||
// to be rendered as:
|
||||
//
|
||||
// let y: u32 = (x?).try_into().unwrap();
|
||||
// + +++++++++++++++++++++
|
||||
let has_attr = |id: HirId| -> bool {
|
||||
for attr in self.tcx.hir_attrs(id) {
|
||||
// For the purpose of rendering suggestions, disregard attributes
|
||||
// that originate from desugaring of any kind. For example, `x?`
|
||||
// desugars to `#[allow(unreachable_code)] match ...`. Failing to
|
||||
// ignore the prefix attribute in the desugaring would cause this
|
||||
// suggestion:
|
||||
//
|
||||
// let y: u32 = x?.try_into().unwrap();
|
||||
// ++++++++++++++++++++
|
||||
//
|
||||
// to be rendered as:
|
||||
//
|
||||
// let y: u32 = (x?).try_into().unwrap();
|
||||
// + +++++++++++++++++++++
|
||||
if attr.span().desugaring_kind().is_none() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
self.tcx.hir_attrs(id).iter().any(Attribute::has_span_without_desugaring_kind)
|
||||
};
|
||||
|
||||
// Special case: range expressions are desugared to struct literals in HIR,
|
||||
|
||||
@@ -119,11 +119,10 @@ fn pre_expansion_lint(
|
||||
features: &Features,
|
||||
registered_tools: &RegisteredTools,
|
||||
node_id: ast::NodeId,
|
||||
attrs: &[ast::Attribute],
|
||||
items: &[Box<ast::Item>],
|
||||
name: Symbol,
|
||||
) {
|
||||
pre_expansion_lint(sess, features, self.0, registered_tools, (node_id, attrs, items), name);
|
||||
pre_expansion_lint(sess, features, self.0, registered_tools, (node_id, items), name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1901,9 +1901,10 @@ fn check_ident_token(
|
||||
return;
|
||||
}
|
||||
|
||||
cx.emit_span_lint(
|
||||
cx.sess().psess.buffer_lint(
|
||||
lint,
|
||||
ident.span,
|
||||
CRATE_NODE_ID,
|
||||
BuiltinKeywordIdents { kw: ident, next: edition, suggestion: ident.span, prefix },
|
||||
);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
|
||||
use rustc_middle::ty::print::{PrintError, PrintTraitRefExt as _, Printer, with_no_trimmed_paths};
|
||||
use rustc_middle::ty::{self, GenericArg, RegisteredTools, Ty, TyCtxt, TypingEnv, TypingMode};
|
||||
use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintExpectationId, LintId};
|
||||
use rustc_session::lint::{
|
||||
CheckLintNameResult, FutureIncompatibleInfo, Lint, LintExpectationId, LintId, TargetLint,
|
||||
};
|
||||
use rustc_session::{DynLintStore, Session};
|
||||
use rustc_span::edit_distance::find_best_match_for_names;
|
||||
use rustc_span::{Ident, Span, Symbol, sym};
|
||||
@@ -69,26 +71,19 @@ fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = rustc_session::LintGroup>
|
||||
rustc_session::LintGroup { name, lints, is_externally_loaded }
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
/// The target of the `by_name` map, which accounts for renaming/deprecation.
|
||||
#[derive(Debug)]
|
||||
enum TargetLint {
|
||||
/// A direct lint target
|
||||
Id(LintId),
|
||||
fn check_lint_name(
|
||||
&self,
|
||||
lint_name: &str,
|
||||
tool_name: Option<Symbol>,
|
||||
registered_tools: &RegisteredTools,
|
||||
) -> CheckLintNameResult<'_> {
|
||||
self.check_lint_name(lint_name, tool_name, registered_tools)
|
||||
}
|
||||
|
||||
/// Temporary renaming, used for easing migration pain; see #16545
|
||||
Renamed(String, LintId),
|
||||
|
||||
/// Lint with this name existed previously, but has been removed/deprecated.
|
||||
/// The string argument is the reason for removal.
|
||||
Removed(String),
|
||||
|
||||
/// A lint name that should give no warnings and have no effect.
|
||||
///
|
||||
/// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers
|
||||
/// them as tool lints.
|
||||
Ignored,
|
||||
fn find_lints(&self, lint_name: &str) -> Option<&[LintId]> {
|
||||
self.find_lints(lint_name)
|
||||
}
|
||||
}
|
||||
|
||||
struct LintAlias {
|
||||
@@ -103,29 +98,6 @@ struct LintGroup {
|
||||
depr: Option<LintAlias>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CheckLintNameResult<'a> {
|
||||
Ok(&'a [LintId]),
|
||||
/// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
|
||||
NoLint(Option<(Symbol, bool)>),
|
||||
/// The lint refers to a tool that has not been registered.
|
||||
NoTool,
|
||||
/// The lint has been renamed to a new name.
|
||||
Renamed(String),
|
||||
/// The lint has been removed due to the given reason.
|
||||
Removed(String),
|
||||
|
||||
/// The lint is from a tool. The `LintId` will be returned as if it were a
|
||||
/// rustc lint. The `Option<String>` indicates if the lint has been
|
||||
/// renamed.
|
||||
Tool(&'a [LintId], Option<String>),
|
||||
|
||||
/// The lint is from a tool. Either the lint does not exist in the tool or
|
||||
/// the code was not compiled with the tool and therefore the lint was
|
||||
/// never added to the `LintStore`.
|
||||
MissingTool,
|
||||
}
|
||||
|
||||
impl LintStore {
|
||||
pub fn new() -> LintStore {
|
||||
LintStore {
|
||||
@@ -304,6 +276,10 @@ pub fn register_removed(&mut self, name: &str, reason: &str) {
|
||||
self.by_name.insert(name.into(), Removed(reason.into()));
|
||||
}
|
||||
|
||||
pub fn get_lint_by_name(&self, lint_name: &str) -> Option<&TargetLint> {
|
||||
self.by_name.get(lint_name)
|
||||
}
|
||||
|
||||
pub fn find_lints(&self, lint_name: &str) -> Option<&[LintId]> {
|
||||
match self.by_name.get(lint_name) {
|
||||
Some(Id(lint_id)) => Some(slice::from_ref(lint_id)),
|
||||
@@ -393,7 +369,7 @@ pub fn check_lint_name(
|
||||
}
|
||||
}
|
||||
match self.by_name.get(&complete_name) {
|
||||
Some(Renamed(new_name, _)) => CheckLintNameResult::Renamed(new_name.to_string()),
|
||||
Some(Renamed(new_name, _)) => CheckLintNameResult::Renamed(Symbol::intern(new_name)),
|
||||
Some(Removed(reason)) => CheckLintNameResult::Removed(reason.to_string()),
|
||||
None => match self.lint_groups.get(&*complete_name) {
|
||||
// If neither the lint, nor the lint group exists check if there is a `clippy::`
|
||||
@@ -602,6 +578,8 @@ fn opt_span_lint<S: Into<MultiSpan>>(
|
||||
}
|
||||
}
|
||||
|
||||
/// Only appropriate for use inside of the compiler
|
||||
/// since the compiler doesn't track levels of tool lints
|
||||
fn get_lint_level(&self, lint: &'static Lint) -> LevelAndSource {
|
||||
self.tcx.lint_level_at_node(lint, self.last_node_with_lint_attrs)
|
||||
}
|
||||
@@ -842,12 +820,7 @@ pub fn get_associated_type(
|
||||
/// be used for pretty-printing HIR by rustc_hir_pretty.
|
||||
pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence {
|
||||
let has_attr = |id: hir::HirId| -> bool {
|
||||
for attr in self.tcx.hir_attrs(id) {
|
||||
if attr.span().desugaring_kind().is_none() {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
false
|
||||
self.tcx.hir_attrs(id).iter().any(hir::Attribute::has_span_without_desugaring_kind)
|
||||
};
|
||||
expr.precedence(&has_attr)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
use rustc_middle::ty::{RegisteredTools, TyCtxt};
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::LintPass;
|
||||
use rustc_span::{Ident, Span};
|
||||
use rustc_span::{DUMMY_SP, Ident, Span};
|
||||
use tracing::debug;
|
||||
|
||||
use crate::DecorateBuiltinLint;
|
||||
@@ -59,13 +59,17 @@ fn check_id(&mut self, id: ast::NodeId) {
|
||||
/// Merge the lints specified by any lint attributes into the
|
||||
/// current lint context, call the provided function, then reset the
|
||||
/// lints in effect to their previous state.
|
||||
fn with_lint_attrs<F>(&mut self, id: ast::NodeId, attrs: &'_ [ast::Attribute], f: F)
|
||||
where
|
||||
fn with_lint_attrs<F>(
|
||||
&mut self,
|
||||
id: ast::NodeId,
|
||||
attrs: &'_ [ast::Attribute],
|
||||
f: F,
|
||||
target_span: Span,
|
||||
) where
|
||||
F: FnOnce(&mut Self),
|
||||
{
|
||||
let is_crate_node = id == ast::CRATE_NODE_ID;
|
||||
debug!(?id);
|
||||
let push = self.context.builder.push(attrs, is_crate_node, None);
|
||||
let push = self.context.builder.push(attrs, id, target_span);
|
||||
|
||||
debug!("early context: enter_attrs({:?})", attrs);
|
||||
lint_callback!(self, check_attributes, attrs);
|
||||
@@ -84,24 +88,39 @@ fn visit_id(&mut self, id: rustc_ast::NodeId) {
|
||||
}
|
||||
|
||||
fn visit_param(&mut self, param: &'ast ast::Param) {
|
||||
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
|
||||
lint_callback!(cx, check_param, param);
|
||||
ast_visit::walk_param(cx, param);
|
||||
});
|
||||
self.with_lint_attrs(
|
||||
param.id,
|
||||
¶m.attrs,
|
||||
|cx| {
|
||||
lint_callback!(cx, check_param, param);
|
||||
ast_visit::walk_param(cx, param);
|
||||
},
|
||||
param.span,
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_item(&mut self, it: &'ast ast::Item) {
|
||||
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
||||
lint_callback!(cx, check_item, it);
|
||||
ast_visit::walk_item(cx, it);
|
||||
lint_callback!(cx, check_item_post, it);
|
||||
})
|
||||
self.with_lint_attrs(
|
||||
it.id,
|
||||
&it.attrs,
|
||||
|cx| {
|
||||
lint_callback!(cx, check_item, it);
|
||||
ast_visit::walk_item(cx, it);
|
||||
lint_callback!(cx, check_item_post, it);
|
||||
},
|
||||
it.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_foreign_item(&mut self, it: &'ast ast::ForeignItem) {
|
||||
self.with_lint_attrs(it.id, &it.attrs, |cx| {
|
||||
ast_visit::walk_item(cx, it);
|
||||
})
|
||||
self.with_lint_attrs(
|
||||
it.id,
|
||||
&it.attrs,
|
||||
|cx| {
|
||||
ast_visit::walk_item(cx, it);
|
||||
},
|
||||
it.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_pat(&mut self, p: &'ast ast::Pat) {
|
||||
@@ -111,23 +130,38 @@ fn visit_pat(&mut self, p: &'ast ast::Pat) {
|
||||
}
|
||||
|
||||
fn visit_pat_field(&mut self, field: &'ast ast::PatField) {
|
||||
self.with_lint_attrs(field.id, &field.attrs, |cx| {
|
||||
ast_visit::walk_pat_field(cx, field);
|
||||
});
|
||||
self.with_lint_attrs(
|
||||
field.id,
|
||||
&field.attrs,
|
||||
|cx| {
|
||||
ast_visit::walk_pat_field(cx, field);
|
||||
},
|
||||
field.span,
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_expr(&mut self, e: &'ast ast::Expr) {
|
||||
self.with_lint_attrs(e.id, &e.attrs, |cx| {
|
||||
lint_callback!(cx, check_expr, e);
|
||||
ast_visit::walk_expr(cx, e);
|
||||
lint_callback!(cx, check_expr_post, e);
|
||||
})
|
||||
self.with_lint_attrs(
|
||||
e.id,
|
||||
&e.attrs,
|
||||
|cx| {
|
||||
lint_callback!(cx, check_expr, e);
|
||||
ast_visit::walk_expr(cx, e);
|
||||
lint_callback!(cx, check_expr_post, e);
|
||||
},
|
||||
e.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_expr_field(&mut self, f: &'ast ast::ExprField) {
|
||||
self.with_lint_attrs(f.id, &f.attrs, |cx| {
|
||||
ast_visit::walk_expr_field(cx, f);
|
||||
})
|
||||
self.with_lint_attrs(
|
||||
f.id,
|
||||
&f.attrs,
|
||||
|cx| {
|
||||
ast_visit::walk_expr_field(cx, f);
|
||||
},
|
||||
f.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_stmt(&mut self, s: &'ast ast::Stmt) {
|
||||
@@ -139,10 +173,15 @@ fn visit_stmt(&mut self, s: &'ast ast::Stmt) {
|
||||
//
|
||||
// Note that statements get their attributes from
|
||||
// the AST struct that they wrap (e.g. an item)
|
||||
self.with_lint_attrs(s.id, s.attrs(), |cx| {
|
||||
lint_callback!(cx, check_stmt, s);
|
||||
ast_visit::walk_stmt(cx, s);
|
||||
});
|
||||
self.with_lint_attrs(
|
||||
s.id,
|
||||
s.attrs(),
|
||||
|cx| {
|
||||
lint_callback!(cx, check_stmt, s);
|
||||
ast_visit::walk_stmt(cx, s);
|
||||
},
|
||||
s.span,
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_fn(&mut self, fk: ast_visit::FnKind<'ast>, _: &AttrVec, span: Span, id: ast::NodeId) {
|
||||
@@ -151,16 +190,26 @@ fn visit_fn(&mut self, fk: ast_visit::FnKind<'ast>, _: &AttrVec, span: Span, id:
|
||||
}
|
||||
|
||||
fn visit_field_def(&mut self, s: &'ast ast::FieldDef) {
|
||||
self.with_lint_attrs(s.id, &s.attrs, |cx| {
|
||||
ast_visit::walk_field_def(cx, s);
|
||||
})
|
||||
self.with_lint_attrs(
|
||||
s.id,
|
||||
&s.attrs,
|
||||
|cx| {
|
||||
ast_visit::walk_field_def(cx, s);
|
||||
},
|
||||
s.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_variant(&mut self, v: &'ast ast::Variant) {
|
||||
self.with_lint_attrs(v.id, &v.attrs, |cx| {
|
||||
lint_callback!(cx, check_variant, v);
|
||||
ast_visit::walk_variant(cx, v);
|
||||
})
|
||||
self.with_lint_attrs(
|
||||
v.id,
|
||||
&v.attrs,
|
||||
|cx| {
|
||||
lint_callback!(cx, check_variant, v);
|
||||
ast_visit::walk_variant(cx, v);
|
||||
},
|
||||
v.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_ty(&mut self, t: &'ast ast::Ty) {
|
||||
@@ -173,10 +222,15 @@ fn visit_ident(&mut self, ident: &Ident) {
|
||||
}
|
||||
|
||||
fn visit_local(&mut self, l: &'ast ast::Local) {
|
||||
self.with_lint_attrs(l.id, &l.attrs, |cx| {
|
||||
lint_callback!(cx, check_local, l);
|
||||
ast_visit::walk_local(cx, l);
|
||||
})
|
||||
self.with_lint_attrs(
|
||||
l.id,
|
||||
&l.attrs,
|
||||
|cx| {
|
||||
lint_callback!(cx, check_local, l);
|
||||
ast_visit::walk_local(cx, l);
|
||||
},
|
||||
l.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_block(&mut self, b: &'ast ast::Block) {
|
||||
@@ -185,10 +239,15 @@ fn visit_block(&mut self, b: &'ast ast::Block) {
|
||||
}
|
||||
|
||||
fn visit_arm(&mut self, a: &'ast ast::Arm) {
|
||||
self.with_lint_attrs(a.id, &a.attrs, |cx| {
|
||||
lint_callback!(cx, check_arm, a);
|
||||
ast_visit::walk_arm(cx, a);
|
||||
})
|
||||
self.with_lint_attrs(
|
||||
a.id,
|
||||
&a.attrs,
|
||||
|cx| {
|
||||
lint_callback!(cx, check_arm, a);
|
||||
ast_visit::walk_arm(cx, a);
|
||||
},
|
||||
a.span,
|
||||
)
|
||||
}
|
||||
|
||||
fn visit_generic_arg(&mut self, arg: &'ast ast::GenericArg) {
|
||||
@@ -197,10 +256,15 @@ fn visit_generic_arg(&mut self, arg: &'ast ast::GenericArg) {
|
||||
}
|
||||
|
||||
fn visit_generic_param(&mut self, param: &'ast ast::GenericParam) {
|
||||
self.with_lint_attrs(param.id, ¶m.attrs, |cx| {
|
||||
lint_callback!(cx, check_generic_param, param);
|
||||
ast_visit::walk_generic_param(cx, param);
|
||||
});
|
||||
self.with_lint_attrs(
|
||||
param.id,
|
||||
¶m.attrs,
|
||||
|cx| {
|
||||
lint_callback!(cx, check_generic_param, param);
|
||||
ast_visit::walk_generic_param(cx, param);
|
||||
},
|
||||
param.span(),
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_generics(&mut self, g: &'ast ast::Generics) {
|
||||
@@ -220,25 +284,30 @@ fn visit_poly_trait_ref(&mut self, t: &'ast ast::PolyTraitRef) {
|
||||
}
|
||||
|
||||
fn visit_assoc_item(&mut self, item: &'ast ast::AssocItem, ctxt: ast_visit::AssocCtxt) {
|
||||
self.with_lint_attrs(item.id, &item.attrs, |cx| {
|
||||
match ctxt {
|
||||
ast_visit::AssocCtxt::Trait => {
|
||||
lint_callback!(cx, check_trait_item, item);
|
||||
self.with_lint_attrs(
|
||||
item.id,
|
||||
&item.attrs,
|
||||
|cx| {
|
||||
match ctxt {
|
||||
ast_visit::AssocCtxt::Trait => {
|
||||
lint_callback!(cx, check_trait_item, item);
|
||||
}
|
||||
ast_visit::AssocCtxt::Impl { .. } => {
|
||||
lint_callback!(cx, check_impl_item, item);
|
||||
}
|
||||
}
|
||||
ast_visit::AssocCtxt::Impl { .. } => {
|
||||
lint_callback!(cx, check_impl_item, item);
|
||||
ast_visit::walk_assoc_item(cx, item, ctxt);
|
||||
match ctxt {
|
||||
ast_visit::AssocCtxt::Trait => {
|
||||
lint_callback!(cx, check_trait_item_post, item);
|
||||
}
|
||||
ast_visit::AssocCtxt::Impl { .. } => {
|
||||
lint_callback!(cx, check_impl_item_post, item);
|
||||
}
|
||||
}
|
||||
}
|
||||
ast_visit::walk_assoc_item(cx, item, ctxt);
|
||||
match ctxt {
|
||||
ast_visit::AssocCtxt::Trait => {
|
||||
lint_callback!(cx, check_trait_item_post, item);
|
||||
}
|
||||
ast_visit::AssocCtxt::Impl { .. } => {
|
||||
lint_callback!(cx, check_impl_item_post, item);
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
item.span,
|
||||
);
|
||||
}
|
||||
|
||||
fn visit_attribute(&mut self, attr: &'ast ast::Attribute) {
|
||||
@@ -310,16 +379,15 @@ fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx,
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [ast::Attribute], &'a [Box<ast::Item>]) {
|
||||
impl<'a> EarlyCheckNode<'a> for (ast::NodeId, &'a [Box<ast::Item>]) {
|
||||
fn id(self) -> ast::NodeId {
|
||||
self.0
|
||||
}
|
||||
fn attrs(self) -> &'a [ast::Attribute] {
|
||||
self.1
|
||||
&[]
|
||||
}
|
||||
fn check<'ecx, 'tcx, T: EarlyLintPass>(self, cx: &mut EarlyContextAndPass<'ecx, 'tcx, T>) {
|
||||
walk_list!(cx, visit_attribute, self.1);
|
||||
walk_list!(cx, visit_item, self.2);
|
||||
walk_list!(cx, visit_item, self.1);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -367,7 +435,7 @@ fn check_ast_node_inner<'a, T: EarlyLintPass>(
|
||||
) {
|
||||
let mut cx = EarlyContextAndPass { context, tcx, pass };
|
||||
|
||||
cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx));
|
||||
cx.with_lint_attrs(check_node.id(), check_node.attrs(), |cx| check_node.check(cx), DUMMY_SP);
|
||||
|
||||
// All of the buffered lints should have been emitted at this point.
|
||||
// If not, that means that we somehow buffered a lint for a node id
|
||||
|
||||
@@ -351,6 +351,28 @@ fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> {
|
||||
&AttributeLintKind::MissingOptionsForOnMove => {
|
||||
lints::MissingOptionsForOnMoveAttr.into_diag(dcx, level)
|
||||
}
|
||||
&AttributeLintKind::RenamedLint { name, replace, suggestion } => lints::RenamedLint {
|
||||
name,
|
||||
replace,
|
||||
suggestion: lints::RenamedLintSuggestion::WithSpan { suggestion, replace },
|
||||
}
|
||||
.into_diag(dcx, level),
|
||||
&AttributeLintKind::DeprecatedLintName { name, suggestion, replace } => {
|
||||
lints::DeprecatedLintName { name, suggestion, replace }.into_diag(dcx, level)
|
||||
}
|
||||
&AttributeLintKind::RemovedLint { name, ref reason } => {
|
||||
lints::RemovedLint { name, reason }.into_diag(dcx, level)
|
||||
}
|
||||
&AttributeLintKind::UnknownLint { name, span, suggestion } => lints::UnknownLint {
|
||||
name,
|
||||
suggestion: suggestion.map(|(replace, from_rustc)| {
|
||||
lints::UnknownLintSuggestion::WithSpan { suggestion: span, replace, from_rustc }
|
||||
}),
|
||||
}
|
||||
.into_diag(dcx, level),
|
||||
&AttributeLintKind::IgnoredUnlessCrateSpecified { level: attr_level, name } => {
|
||||
lints::IgnoredUnlessCrateSpecified { level: attr_level, name }.into_diag(dcx, level)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,36 +44,6 @@ fn add_to_diag<G: EmissionGuarantee>(self, diag: &mut Diag<'_, G>) {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("malformed lint attribute input", code = E0452)]
|
||||
pub(crate) struct MalformedAttribute {
|
||||
#[primary_span]
|
||||
pub span: Span,
|
||||
#[subdiagnostic]
|
||||
pub sub: MalformedAttributeSub,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum MalformedAttributeSub {
|
||||
#[label("bad attribute argument")]
|
||||
BadAttributeArgument(#[primary_span] Span),
|
||||
#[label("reason must be a string literal")]
|
||||
ReasonMustBeStringLiteral(#[primary_span] Span),
|
||||
#[label("reason in lint attribute must come last")]
|
||||
ReasonMustComeLast(#[primary_span] Span),
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("unknown tool name `{$tool_name}` found in scoped lint: `{$tool_name}::{$lint_name}`", code = E0710)]
|
||||
pub(crate) struct UnknownToolInScopedLint {
|
||||
#[primary_span]
|
||||
pub span: Option<Span>,
|
||||
pub tool_name: Symbol,
|
||||
pub lint_name: String,
|
||||
#[help("add `#![register_tool({$tool_name})]` to the crate root")]
|
||||
pub is_nightly_build: bool,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("`...` range patterns are deprecated", code = E0783)]
|
||||
pub(crate) struct BuiltinEllipsisInclusiveRangePatterns {
|
||||
|
||||
@@ -18,33 +18,33 @@ fn lint_expectations(tcx: TyCtxt<'_>, (): ()) -> Vec<(LintExpectationId, LintExp
|
||||
let mut expectations = Vec::new();
|
||||
|
||||
for owner in krate.owners() {
|
||||
// Deduplicate expectations
|
||||
let mut inner_expectations = Vec::new();
|
||||
let lints = tcx.shallow_lint_levels_on(owner);
|
||||
expectations.extend_from_slice(&lints.expectations);
|
||||
for expectation in &lints.expectations {
|
||||
let canonicalized = canonicalize_id(&expectation.0);
|
||||
if !inner_expectations.iter().any(|(id, _)| canonicalize_id(id) == canonicalized) {
|
||||
inner_expectations.push(expectation.clone());
|
||||
}
|
||||
}
|
||||
expectations.extend(inner_expectations);
|
||||
}
|
||||
|
||||
expectations
|
||||
}
|
||||
|
||||
fn canonicalize_id(expect_id: &LintExpectationId) -> (rustc_span::AttrId, u16) {
|
||||
match *expect_id {
|
||||
LintExpectationId::Unstable { attr_id, lint_index, .. } => (attr_id, lint_index),
|
||||
LintExpectationId::Stable { attr_id, lint_index, .. } => (attr_id, lint_index),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expectations(tcx: TyCtxt<'_>, tool_filter: Option<Symbol>) {
|
||||
let lint_expectations = tcx.lint_expectations(());
|
||||
let fulfilled_expectations = tcx.dcx().steal_fulfilled_expectation_ids();
|
||||
|
||||
// Turn a `LintExpectationId` into a `(AttrId, lint_index)` pair.
|
||||
let canonicalize_id = |expect_id: &LintExpectationId| {
|
||||
match *expect_id {
|
||||
LintExpectationId::Unstable { attr_id, lint_index: Some(lint_index) } => {
|
||||
(attr_id, lint_index)
|
||||
}
|
||||
LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
|
||||
// We are an `eval_always` query, so looking at the attribute's `AttrId` is ok.
|
||||
let attr_id = tcx.hir_attrs(hir_id)[attr_index as usize].id();
|
||||
|
||||
(attr_id, lint_index)
|
||||
}
|
||||
_ => panic!("fulfilled expectations must have a lint index"),
|
||||
}
|
||||
};
|
||||
|
||||
let fulfilled_expectations: FxHashSet<_> =
|
||||
fulfilled_expectations.iter().map(canonicalize_id).collect();
|
||||
|
||||
|
||||
+143
-306
@@ -1,13 +1,13 @@
|
||||
use rustc_ast as ast;
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_ast_pretty::pprust;
|
||||
use rustc_ast::{DUMMY_NODE_ID, NodeId};
|
||||
use rustc_attr_parsing::AttributeParser;
|
||||
use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
|
||||
use rustc_data_structures::unord::UnordSet;
|
||||
use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, MultiSpan, msg};
|
||||
use rustc_feature::{Features, GateIssue};
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::attrs::{LintAttribute, LintAttributeKind, LintInstance};
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{self as hir, HirId, Target, find_attr};
|
||||
use rustc_index::IndexVec;
|
||||
use rustc_middle::bug;
|
||||
use rustc_middle::hir::nested_filter;
|
||||
@@ -20,26 +20,37 @@
|
||||
use rustc_session::Session;
|
||||
use rustc_session::lint::builtin::{
|
||||
self, FORBIDDEN_LINT_GROUPS, RENAMED_AND_REMOVED_LINTS, SINGLE_USE_LIFETIMES,
|
||||
UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES,
|
||||
UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS,
|
||||
};
|
||||
use rustc_session::lint::{
|
||||
CheckLintNameResult, Level, Lint, LintExpectationId, LintId, TargetLint,
|
||||
};
|
||||
use rustc_session::lint::{Level, Lint, LintExpectationId, LintId};
|
||||
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use crate::builtin::MISSING_DOCS;
|
||||
use crate::context::{CheckLintNameResult, LintStore};
|
||||
use crate::context::LintStore;
|
||||
use crate::errors::{
|
||||
CheckNameUnknownTool, MalformedAttribute, MalformedAttributeSub, OverruledAttribute,
|
||||
OverruledAttributeSub, RequestedLevel, UnknownToolInScopedLint, UnsupportedGroup,
|
||||
CheckNameUnknownTool, OverruledAttribute, OverruledAttributeSub, RequestedLevel,
|
||||
UnsupportedGroup,
|
||||
};
|
||||
use crate::late::unerased_lint_store;
|
||||
use crate::lints::{
|
||||
DeprecatedLintName, DeprecatedLintNameFromCommandLine, IgnoredUnlessCrateSpecified,
|
||||
OverruledAttributeLint, RemovedLint, RemovedLintFromCommandLine, RenamedLint,
|
||||
RenamedLintFromCommandLine, RenamedLintSuggestion, UnknownLint, UnknownLintFromCommandLine,
|
||||
DeprecatedLintNameFromCommandLine, OverruledAttributeLint, RemovedLintFromCommandLine,
|
||||
RenamedLintFromCommandLine, RenamedLintSuggestion, UnknownLintFromCommandLine,
|
||||
UnknownLintSuggestion,
|
||||
};
|
||||
|
||||
const ALLOW_LISTED_ATTRS: &[Symbol] = &[
|
||||
sym::allow,
|
||||
sym::deny,
|
||||
sym::expect,
|
||||
sym::forbid,
|
||||
sym::warn,
|
||||
sym::automatically_derived,
|
||||
sym::doc,
|
||||
];
|
||||
|
||||
/// Collection of lint levels for the whole crate.
|
||||
/// This is used by AST-based lints, which do not
|
||||
/// wait until we have built HIR to be emitted.
|
||||
@@ -266,11 +277,7 @@ fn push_expectation(&mut self, id: LintExpectationId, expectation: LintExpectati
|
||||
impl<'tcx> LintLevelsBuilder<'_, LintLevelQueryMap<'tcx>> {
|
||||
fn add_id(&mut self, hir_id: HirId) {
|
||||
self.provider.cur = hir_id;
|
||||
self.add(
|
||||
self.provider.attrs.get(hir_id.local_id),
|
||||
hir_id == hir::CRATE_HIR_ID,
|
||||
Some(hir_id),
|
||||
);
|
||||
self.add(self.provider.attrs.get(hir_id.local_id), Some(hir_id));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -390,7 +397,19 @@ pub fn crate_root(
|
||||
crate_attrs: &[ast::Attribute],
|
||||
) -> Self {
|
||||
let mut builder = Self::new(sess, features, lint_added_lints, store, registered_tools);
|
||||
builder.add(crate_attrs, true, None);
|
||||
let parsed_crate_attrs = AttributeParser::parse_limited_all_filtered(
|
||||
sess,
|
||||
crate_attrs,
|
||||
ALLOW_LISTED_ATTRS,
|
||||
Target::Crate,
|
||||
DUMMY_SP,
|
||||
DUMMY_NODE_ID,
|
||||
Some(features),
|
||||
rustc_attr_parsing::ShouldEmit::Nothing,
|
||||
registered_tools,
|
||||
);
|
||||
|
||||
builder.add(&parsed_crate_attrs, None);
|
||||
builder
|
||||
}
|
||||
|
||||
@@ -420,18 +439,31 @@ fn process_command_line(&mut self) {
|
||||
pub(crate) fn push(
|
||||
&mut self,
|
||||
attrs: &[ast::Attribute],
|
||||
is_crate_node: bool,
|
||||
source_hir_id: Option<HirId>,
|
||||
node_id: NodeId,
|
||||
target_span: Span,
|
||||
) -> BuilderPush {
|
||||
let prev = self.provider.cur;
|
||||
self.provider.cur =
|
||||
self.provider.sets.list.push(LintSet { specs: FxIndexMap::default(), parent: prev });
|
||||
if !attrs.is_empty() {
|
||||
let attrs = AttributeParser::parse_limited_all_filtered(
|
||||
self.sess,
|
||||
attrs,
|
||||
ALLOW_LISTED_ATTRS,
|
||||
Target::Fn,
|
||||
target_span,
|
||||
node_id,
|
||||
Some(self.features),
|
||||
rustc_attr_parsing::ShouldEmit::Nothing,
|
||||
self.registered_tools,
|
||||
);
|
||||
|
||||
self.add(attrs, is_crate_node, source_hir_id);
|
||||
self.add(&attrs, None);
|
||||
|
||||
if self.provider.current_specs().is_empty() {
|
||||
self.provider.sets.list.pop();
|
||||
self.provider.cur = prev;
|
||||
if self.provider.current_specs().is_empty() {
|
||||
self.provider.sets.list.pop();
|
||||
self.provider.cur = prev;
|
||||
}
|
||||
}
|
||||
|
||||
BuilderPush { prev }
|
||||
@@ -478,7 +510,7 @@ fn add_command_line(&mut self) {
|
||||
.emit_err(UnsupportedGroup { lint_group: crate::WARNINGS.name_lower() });
|
||||
}
|
||||
match self.store.check_lint_name(lint_name_only, tool_name, self.registered_tools) {
|
||||
CheckLintNameResult::Renamed(ref replace) => {
|
||||
CheckLintNameResult::Renamed(replace) => {
|
||||
let name = lint_name.as_str();
|
||||
let suggestion = RenamedLintSuggestion::WithoutSpan { replace };
|
||||
let requested_level = RequestedLevel { level, lint_name };
|
||||
@@ -638,297 +670,102 @@ fn insert_spec(&mut self, id: LintId, LevelAndSource { level, lint_id, src }: Le
|
||||
};
|
||||
}
|
||||
|
||||
fn add(
|
||||
fn simple_add(
|
||||
&mut self,
|
||||
attrs: &[impl AttributeExt],
|
||||
is_crate_node: bool,
|
||||
source_hir_id: Option<HirId>,
|
||||
level: Level,
|
||||
lint: &LintInstance,
|
||||
reason: Option<Symbol>,
|
||||
expect_lint_id: Option<LintExpectationId>,
|
||||
) {
|
||||
let sess = self.sess;
|
||||
for (attr_index, attr) in attrs.iter().enumerate() {
|
||||
if attr.is_automatically_derived_attr() {
|
||||
self.insert(
|
||||
LintId::of(SINGLE_USE_LIFETIMES),
|
||||
LevelAndSource {
|
||||
level: Level::Allow,
|
||||
lint_id: None,
|
||||
src: LintLevelSource::Default,
|
||||
},
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// If this function returns none, it means the attribute parser has already emitted appropriate errors
|
||||
|
||||
// `#[doc(hidden)]` disables missing_docs check.
|
||||
if attr.is_doc_hidden() {
|
||||
self.insert(
|
||||
LintId::of(MISSING_DOCS),
|
||||
LevelAndSource {
|
||||
level: Level::Allow,
|
||||
lint_id: None,
|
||||
src: LintLevelSource::Default,
|
||||
},
|
||||
);
|
||||
continue;
|
||||
}
|
||||
let src =
|
||||
LintLevelSource::Node { name: lint.original_lint_name(), span: lint.span(), reason };
|
||||
|
||||
let (level, lint_id) = match Level::from_attr(attr) {
|
||||
None => continue,
|
||||
// This is the only lint level with a `LintExpectationId` that can be created from
|
||||
// an attribute.
|
||||
Some((Level::Expect, Some(unstable_id))) if let Some(hir_id) = source_hir_id => {
|
||||
let LintExpectationId::Unstable { lint_index: None, attr_id: _ } = unstable_id
|
||||
else {
|
||||
bug!("stable id Level::from_attr")
|
||||
};
|
||||
let id = match self.store.get_lint_by_name(lint.full_lint().as_str()) {
|
||||
Some(TargetLint::Id(id)) => id,
|
||||
None | Some(_) => bug!(
|
||||
"guaranteed to find id due to previous parsing, happened while parsing {:?}",
|
||||
lint,
|
||||
),
|
||||
};
|
||||
|
||||
let stable_id = LintExpectationId::Stable {
|
||||
hir_id,
|
||||
attr_index: attr_index.try_into().unwrap(),
|
||||
lint_index: None,
|
||||
};
|
||||
if self.check_gated_lint(*id, lint.span(), false) {
|
||||
self.insert_spec(*id, LevelAndSource { level, lint_id: expect_lint_id, src });
|
||||
}
|
||||
}
|
||||
|
||||
(Level::Expect, Some(stable_id))
|
||||
}
|
||||
Some((lvl, id)) => (lvl, id),
|
||||
};
|
||||
|
||||
let Some(mut metas) = attr.meta_item_list() else { continue };
|
||||
|
||||
// Check whether `metas` is empty, and get its last element.
|
||||
let Some(tail_li) = metas.last() else {
|
||||
// This emits the unused_attributes lint for `#[level()]`
|
||||
continue;
|
||||
};
|
||||
|
||||
// Before processing the lint names, look for a reason (RFC 2383)
|
||||
// at the end.
|
||||
let mut reason = None;
|
||||
if let Some(item) = tail_li.meta_item() {
|
||||
match item.kind {
|
||||
ast::MetaItemKind::Word => {} // actual lint names handled later
|
||||
ast::MetaItemKind::NameValue(ref name_value) => {
|
||||
if item.path == sym::reason {
|
||||
if let ast::LitKind::Str(rationale, _) = name_value.kind {
|
||||
reason = Some(rationale);
|
||||
} else {
|
||||
sess.dcx().emit_err(MalformedAttribute {
|
||||
span: name_value.span,
|
||||
sub: MalformedAttributeSub::ReasonMustBeStringLiteral(
|
||||
name_value.span,
|
||||
),
|
||||
});
|
||||
}
|
||||
// found reason, reslice meta list to exclude it
|
||||
metas.pop().unwrap();
|
||||
} else {
|
||||
sess.dcx().emit_err(MalformedAttribute {
|
||||
span: item.span,
|
||||
sub: MalformedAttributeSub::BadAttributeArgument(item.span),
|
||||
});
|
||||
}
|
||||
}
|
||||
ast::MetaItemKind::List(_) => {
|
||||
sess.dcx().emit_err(MalformedAttribute {
|
||||
span: item.span,
|
||||
sub: MalformedAttributeSub::BadAttributeArgument(item.span),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (lint_index, li) in metas.iter_mut().enumerate() {
|
||||
let mut lint_id = lint_id;
|
||||
if let Some(id) = &mut lint_id {
|
||||
id.set_lint_index(Some(lint_index as u16));
|
||||
}
|
||||
|
||||
let sp = li.span();
|
||||
let meta_item = match li {
|
||||
ast::MetaItemInner::MetaItem(meta_item) if meta_item.is_word() => meta_item,
|
||||
_ => {
|
||||
let sub = if let Some(item) = li.meta_item()
|
||||
&& let ast::MetaItemKind::NameValue(_) = item.kind
|
||||
&& item.path == sym::reason
|
||||
{
|
||||
MalformedAttributeSub::ReasonMustComeLast(sp)
|
||||
} else {
|
||||
MalformedAttributeSub::BadAttributeArgument(sp)
|
||||
};
|
||||
|
||||
sess.dcx().emit_err(MalformedAttribute { span: sp, sub });
|
||||
continue;
|
||||
}
|
||||
};
|
||||
let tool_ident = if meta_item.path.segments.len() > 1 {
|
||||
Some(meta_item.path.segments.remove(0).ident)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
let tool_name = tool_ident.map(|ident| ident.name);
|
||||
let name = pprust::path_to_string(&meta_item.path);
|
||||
let lint_result =
|
||||
self.store.check_lint_name(&name, tool_name, self.registered_tools);
|
||||
|
||||
let (ids, name) = match lint_result {
|
||||
CheckLintNameResult::Ok(ids) => {
|
||||
let name =
|
||||
meta_item.path.segments.last().expect("empty lint name").ident.name;
|
||||
(ids, name)
|
||||
}
|
||||
|
||||
CheckLintNameResult::Tool(ids, new_lint_name) => {
|
||||
let name = match new_lint_name {
|
||||
None => {
|
||||
let complete_name =
|
||||
&format!("{}::{}", tool_ident.unwrap().name, name);
|
||||
Symbol::intern(complete_name)
|
||||
}
|
||||
Some(new_lint_name) => {
|
||||
self.emit_span_lint(
|
||||
builtin::RENAMED_AND_REMOVED_LINTS,
|
||||
sp.into(),
|
||||
DeprecatedLintName {
|
||||
name,
|
||||
suggestion: sp,
|
||||
replace: &new_lint_name,
|
||||
},
|
||||
);
|
||||
Symbol::intern(&new_lint_name)
|
||||
}
|
||||
};
|
||||
(ids, name)
|
||||
}
|
||||
|
||||
CheckLintNameResult::MissingTool => {
|
||||
// If `MissingTool` is returned, then either the lint does not
|
||||
// exist in the tool or the code was not compiled with the tool and
|
||||
// therefore the lint was never added to the `LintStore`. To detect
|
||||
// this is the responsibility of the lint tool.
|
||||
continue;
|
||||
}
|
||||
|
||||
CheckLintNameResult::NoTool => {
|
||||
sess.dcx().emit_err(UnknownToolInScopedLint {
|
||||
span: tool_ident.map(|ident| ident.span),
|
||||
tool_name: tool_name.unwrap(),
|
||||
lint_name: pprust::path_to_string(&meta_item.path),
|
||||
is_nightly_build: sess.is_nightly_build(),
|
||||
});
|
||||
continue;
|
||||
}
|
||||
|
||||
CheckLintNameResult::Renamed(ref replace) => {
|
||||
if self.lint_added_lints {
|
||||
let suggestion =
|
||||
RenamedLintSuggestion::WithSpan { suggestion: sp, replace };
|
||||
let name =
|
||||
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
|
||||
self.emit_span_lint(
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
sp.into(),
|
||||
RenamedLint { name: name.as_str(), replace, suggestion },
|
||||
);
|
||||
}
|
||||
|
||||
// If this lint was renamed, apply the new lint instead of ignoring the
|
||||
// attribute. Ignore any errors or warnings that happen because the new
|
||||
// name is inaccurate.
|
||||
// NOTE: `new_name` already includes the tool name, so we don't
|
||||
// have to add it again.
|
||||
let CheckLintNameResult::Ok(ids) =
|
||||
self.store.check_lint_name(replace, None, self.registered_tools)
|
||||
else {
|
||||
panic!("renamed lint does not exist: {replace}");
|
||||
};
|
||||
|
||||
(ids, Symbol::intern(&replace))
|
||||
}
|
||||
|
||||
CheckLintNameResult::Removed(ref reason) => {
|
||||
if self.lint_added_lints {
|
||||
let name =
|
||||
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
|
||||
self.emit_span_lint(
|
||||
RENAMED_AND_REMOVED_LINTS,
|
||||
sp.into(),
|
||||
RemovedLint { name: name.as_str(), reason },
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
CheckLintNameResult::NoLint(suggestion) => {
|
||||
if self.lint_added_lints {
|
||||
let name =
|
||||
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
|
||||
let suggestion = suggestion.map(|(replace, from_rustc)| {
|
||||
UnknownLintSuggestion::WithSpan {
|
||||
suggestion: sp,
|
||||
replace,
|
||||
from_rustc,
|
||||
}
|
||||
});
|
||||
self.emit_span_lint(
|
||||
UNKNOWN_LINTS,
|
||||
sp.into(),
|
||||
UnknownLint { name, suggestion },
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
let src = LintLevelSource::Node { name, span: sp, reason };
|
||||
for &id in ids {
|
||||
if self.check_gated_lint(id, sp, false) {
|
||||
self.insert_spec(id, LevelAndSource { level, lint_id, src });
|
||||
}
|
||||
}
|
||||
|
||||
// This checks for instances where the user writes
|
||||
// `#[expect(unfulfilled_lint_expectations)]` in that case we want to avoid
|
||||
// overriding the lint level but instead add an expectation that can't be
|
||||
// fulfilled. The lint message will include an explanation, that the
|
||||
// `unfulfilled_lint_expectations` lint can't be expected.
|
||||
if let (Level::Expect, Some(expect_id)) = (level, lint_id) {
|
||||
// The `unfulfilled_lint_expectations` lint is not part of any lint
|
||||
// groups. Therefore. we only need to check the slice if it contains a
|
||||
// single lint.
|
||||
let is_unfulfilled_lint_expectations = match ids {
|
||||
[lint] => *lint == LintId::of(UNFULFILLED_LINT_EXPECTATIONS),
|
||||
_ => false,
|
||||
};
|
||||
self.provider.push_expectation(
|
||||
expect_id,
|
||||
LintExpectation::new(
|
||||
reason,
|
||||
sp,
|
||||
is_unfulfilled_lint_expectations,
|
||||
tool_name,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
fn add(&mut self, attrs: &[hir::Attribute], source_hir_id: Option<HirId>) {
|
||||
if find_attr!(attrs, AutomaticallyDerived(..)) {
|
||||
self.insert(
|
||||
LintId::of(SINGLE_USE_LIFETIMES),
|
||||
LevelAndSource {
|
||||
level: Level::Allow,
|
||||
lint_id: None,
|
||||
src: LintLevelSource::Default,
|
||||
},
|
||||
);
|
||||
}
|
||||
// `#[doc(hidden)]` disables missing_docs check.
|
||||
if find_attr!(attrs, Doc(d) if d.hidden.is_some()) {
|
||||
self.insert(
|
||||
LintId::of(MISSING_DOCS),
|
||||
LevelAndSource {
|
||||
level: Level::Allow,
|
||||
lint_id: None,
|
||||
src: LintLevelSource::Default,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
if self.lint_added_lints && !is_crate_node {
|
||||
for (id, &LevelAndSource { level, ref src, .. }) in self.current_specs().iter() {
|
||||
if !id.lint.crate_level_only {
|
||||
let Some(attrs) = find_attr!(attrs, LintAttributes(sub_attrs) => sub_attrs.into_iter())
|
||||
else {
|
||||
return;
|
||||
};
|
||||
|
||||
for (attr_index, LintAttribute { reason, lint_instances, attr_id, kind, .. }) in
|
||||
attrs.enumerate()
|
||||
{
|
||||
let attr_id = attr_id.attr_id;
|
||||
let level = match kind {
|
||||
LintAttributeKind::Allow => Level::Allow,
|
||||
LintAttributeKind::Deny => Level::Deny,
|
||||
LintAttributeKind::Forbid => Level::Forbid,
|
||||
LintAttributeKind::Warn => Level::Warn,
|
||||
LintAttributeKind::Expect => {
|
||||
for lint in lint_instances {
|
||||
let lint_index = lint.lint_index().try_into().unwrap();
|
||||
let attr_index = attr_index.try_into().unwrap();
|
||||
let expectation_id = match source_hir_id {
|
||||
None => LintExpectationId::Unstable { attr_id, lint_index },
|
||||
Some(hir_id) => LintExpectationId::Stable {
|
||||
hir_id,
|
||||
attr_id,
|
||||
lint_index,
|
||||
attr_index,
|
||||
},
|
||||
};
|
||||
|
||||
self.simple_add(Level::Expect, lint, *reason, Some(expectation_id));
|
||||
|
||||
let is_unfulfilled_lint_expectations =
|
||||
lint.lint_name().as_str() == UNFULFILLED_LINT_EXPECTATIONS.name_lower();
|
||||
self.provider.push_expectation(
|
||||
expectation_id,
|
||||
LintExpectation::new(
|
||||
*reason,
|
||||
lint.span(),
|
||||
is_unfulfilled_lint_expectations,
|
||||
lint.tool_name(),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
let LintLevelSource::Node { name: lint_attr_name, span: lint_attr_span, .. } = *src
|
||||
else {
|
||||
continue;
|
||||
};
|
||||
|
||||
self.emit_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
lint_attr_span.into(),
|
||||
IgnoredUnlessCrateSpecified { level: level.as_str(), name: lint_attr_name },
|
||||
);
|
||||
// don't set a separate error for every lint in the group
|
||||
break;
|
||||
};
|
||||
for lint in lint_instances {
|
||||
self.simple_add(level, lint, *reason, None);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -128,7 +128,7 @@
|
||||
|
||||
#[rustfmt::skip]
|
||||
pub use builtin::{MissingDoc, SoftLints};
|
||||
pub use context::{CheckLintNameResult, EarlyContext, LateContext, LintContext, LintStore};
|
||||
pub use context::{EarlyContext, LateContext, LintContext, LintStore};
|
||||
pub use early::diagnostics::{DecorateAttrLint, DecorateBuiltinLint};
|
||||
pub use early::{EarlyCheckNode, check_ast_node};
|
||||
pub use late::{check_crate, late_lint_mod, unerased_lint_store};
|
||||
@@ -136,7 +136,9 @@
|
||||
pub use passes::{EarlyLintPass, LateLintPass};
|
||||
pub use rustc_errors::BufferedEarlyLint;
|
||||
pub use rustc_session::lint::Level::{self, *};
|
||||
pub use rustc_session::lint::{FutureIncompatibleInfo, Lint, LintId, LintPass, LintVec};
|
||||
pub use rustc_session::lint::{
|
||||
CheckLintNameResult, FutureIncompatibleInfo, Lint, LintId, LintPass, LintVec,
|
||||
};
|
||||
|
||||
pub fn provide(providers: &mut Providers) {
|
||||
levels::provide(providers);
|
||||
|
||||
@@ -1238,11 +1238,11 @@ pub(crate) struct OverruledAttributeLint<'a> {
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("lint name `{$name}` is deprecated and may not have an effect in the future")]
|
||||
pub(crate) struct DeprecatedLintName<'a> {
|
||||
pub name: String,
|
||||
pub(crate) struct DeprecatedLintName {
|
||||
pub name: Symbol,
|
||||
#[suggestion("change it to", code = "{replace}", applicability = "machine-applicable")]
|
||||
pub suggestion: Span,
|
||||
pub replace: &'a str,
|
||||
pub replace: Symbol,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
@@ -1257,32 +1257,32 @@ pub(crate) struct DeprecatedLintNameFromCommandLine<'a> {
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("lint `{$name}` has been renamed to `{$replace}`")]
|
||||
pub(crate) struct RenamedLint<'a> {
|
||||
pub name: &'a str,
|
||||
pub replace: &'a str,
|
||||
pub(crate) struct RenamedLint {
|
||||
pub name: Symbol,
|
||||
pub replace: Symbol,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: RenamedLintSuggestion<'a>,
|
||||
pub suggestion: RenamedLintSuggestion,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
pub(crate) enum RenamedLintSuggestion<'a> {
|
||||
pub(crate) enum RenamedLintSuggestion {
|
||||
#[suggestion("use the new name", code = "{replace}", applicability = "machine-applicable")]
|
||||
WithSpan {
|
||||
#[primary_span]
|
||||
suggestion: Span,
|
||||
replace: &'a str,
|
||||
replace: Symbol,
|
||||
},
|
||||
#[help("use the new name `{$replace}`")]
|
||||
WithoutSpan { replace: &'a str },
|
||||
WithoutSpan { replace: Symbol },
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("lint `{$name}` has been renamed to `{$replace}`")]
|
||||
pub(crate) struct RenamedLintFromCommandLine<'a> {
|
||||
pub name: &'a str,
|
||||
pub replace: &'a str,
|
||||
pub replace: Symbol,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: RenamedLintSuggestion<'a>,
|
||||
pub suggestion: RenamedLintSuggestion,
|
||||
#[subdiagnostic]
|
||||
pub requested_level: RequestedLevel<'a>,
|
||||
}
|
||||
@@ -1290,7 +1290,7 @@ pub(crate) struct RenamedLintFromCommandLine<'a> {
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("lint `{$name}` has been removed: {$reason}")]
|
||||
pub(crate) struct RemovedLint<'a> {
|
||||
pub name: &'a str,
|
||||
pub name: Symbol,
|
||||
pub reason: &'a str,
|
||||
}
|
||||
|
||||
@@ -1306,7 +1306,7 @@ pub(crate) struct RemovedLintFromCommandLine<'a> {
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("unknown lint: `{$name}`")]
|
||||
pub(crate) struct UnknownLint {
|
||||
pub name: String,
|
||||
pub name: Symbol,
|
||||
#[subdiagnostic]
|
||||
pub suggestion: Option<UnknownLintSuggestion>,
|
||||
}
|
||||
@@ -1348,8 +1348,8 @@ pub(crate) struct UnknownLintFromCommandLine<'a> {
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag("{$level}({$name}) is ignored unless specified at crate level")]
|
||||
pub(crate) struct IgnoredUnlessCrateSpecified<'a> {
|
||||
pub level: &'a str,
|
||||
pub(crate) struct IgnoredUnlessCrateSpecified {
|
||||
pub level: Symbol,
|
||||
pub name: Symbol,
|
||||
}
|
||||
|
||||
|
||||
@@ -5,7 +5,6 @@ edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
# tidy-alphabetical-start
|
||||
rustc_ast = { path = "../rustc_ast" }
|
||||
rustc_data_structures = { path = "../rustc_data_structures" }
|
||||
rustc_error_messages = { path = "../rustc_error_messages" }
|
||||
rustc_hir_id = { path = "../rustc_hir_id" }
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::borrow::Cow;
|
||||
use std::fmt::Display;
|
||||
|
||||
use rustc_ast::AttrId;
|
||||
use rustc_ast::attr::AttributeExt;
|
||||
use rustc_data_structures::fx::FxIndexSet;
|
||||
use rustc_data_structures::stable_hasher::{
|
||||
HashStable, StableCompare, StableHasher, ToStableHashKey,
|
||||
@@ -12,7 +10,7 @@
|
||||
use rustc_macros::{Decodable, Encodable, HashStable_Generic};
|
||||
use rustc_span::def_id::DefPathHash;
|
||||
pub use rustc_span::edition::Edition;
|
||||
use rustc_span::{HashStableContext, Ident, Span, Symbol, sym};
|
||||
use rustc_span::{AttrId, HashStableContext, Ident, Span, Symbol, sym};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
pub use self::Level::*;
|
||||
@@ -107,12 +105,12 @@ pub enum Applicability {
|
||||
pub enum LintExpectationId {
|
||||
/// Used for lints emitted during the `EarlyLintPass`. This id is not
|
||||
/// hash stable and should not be cached.
|
||||
Unstable { attr_id: AttrId, lint_index: Option<u16> },
|
||||
Unstable { attr_id: AttrId, lint_index: u16 },
|
||||
/// The [`HirId`] that the lint expectation is attached to. This id is
|
||||
/// stable and can be cached. The additional index ensures that nodes with
|
||||
/// several expectations can correctly match diagnostics to the individual
|
||||
/// expectation.
|
||||
Stable { hir_id: HirId, attr_index: u16, lint_index: Option<u16> },
|
||||
Stable { hir_id: HirId, attr_id: AttrId, attr_index: u16, lint_index: u16 },
|
||||
}
|
||||
|
||||
impl LintExpectationId {
|
||||
@@ -123,14 +121,14 @@ pub fn is_stable(&self) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_lint_index(&self) -> Option<u16> {
|
||||
pub fn get_lint_index(&self) -> u16 {
|
||||
let (LintExpectationId::Unstable { lint_index, .. }
|
||||
| LintExpectationId::Stable { lint_index, .. }) = self;
|
||||
|
||||
*lint_index
|
||||
}
|
||||
|
||||
pub fn set_lint_index(&mut self, new_lint_index: Option<u16>) {
|
||||
pub fn set_lint_index(&mut self, new_lint_index: u16) {
|
||||
let (LintExpectationId::Unstable { lint_index, .. }
|
||||
| LintExpectationId::Stable { lint_index, .. }) = self;
|
||||
|
||||
@@ -142,7 +140,7 @@ impl<Hcx: HashStableContext> HashStable<Hcx> for LintExpectationId {
|
||||
#[inline]
|
||||
fn hash_stable(&self, hcx: &mut Hcx, hasher: &mut StableHasher) {
|
||||
match self {
|
||||
LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
|
||||
LintExpectationId::Stable { hir_id, attr_index, lint_index, .. } => {
|
||||
hir_id.hash_stable(hcx, hasher);
|
||||
attr_index.hash_stable(hcx, hasher);
|
||||
lint_index.hash_stable(hcx, hasher);
|
||||
@@ -162,7 +160,7 @@ impl<Hcx: HashStableContext> ToStableHashKey<Hcx> for LintExpectationId {
|
||||
#[inline]
|
||||
fn to_stable_hash_key(&self, hcx: &Hcx) -> Self::KeyType {
|
||||
match self {
|
||||
LintExpectationId::Stable { hir_id, attr_index, lint_index: Some(lint_index) } => {
|
||||
LintExpectationId::Stable { hir_id, attr_index, lint_index, .. } => {
|
||||
let (def_path_hash, lint_idx) = hir_id.to_stable_hash_key(hcx);
|
||||
(def_path_hash, lint_idx, *attr_index, *lint_index)
|
||||
}
|
||||
@@ -235,6 +233,17 @@ pub fn as_str(self) -> &'static str {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn from_symbol(x: Symbol) -> Option<Self> {
|
||||
match x {
|
||||
sym::allow => Some(Level::Allow),
|
||||
sym::deny => Some(Level::Deny),
|
||||
sym::expect => Some(Level::Expect),
|
||||
sym::forbid => Some(Level::Forbid),
|
||||
sym::warn => Some(Level::Warn),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts a lower-case string to a level. This will never construct the expect
|
||||
/// level as that would require a [`LintExpectationId`].
|
||||
pub fn from_str(x: &str) -> Option<Self> {
|
||||
@@ -247,35 +256,6 @@ pub fn from_str(x: &str) -> Option<Self> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Converts an `Attribute` to a level.
|
||||
pub fn from_attr(attr: &impl AttributeExt) -> Option<(Self, Option<LintExpectationId>)> {
|
||||
attr.name().and_then(|name| Self::from_symbol(name, || Some(attr.id())))
|
||||
}
|
||||
|
||||
/// Converts a `Symbol` to a level.
|
||||
pub fn from_symbol(
|
||||
s: Symbol,
|
||||
id: impl FnOnce() -> Option<AttrId>,
|
||||
) -> Option<(Self, Option<LintExpectationId>)> {
|
||||
match s {
|
||||
sym::allow => Some((Level::Allow, None)),
|
||||
sym::expect => {
|
||||
if let Some(attr_id) = id() {
|
||||
Some((
|
||||
Level::Expect,
|
||||
Some(LintExpectationId::Unstable { attr_id, lint_index: None }),
|
||||
))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
sym::warn => Some((Level::Warn, None)),
|
||||
sym::deny => Some((Level::Deny, None)),
|
||||
sym::forbid => Some((Level::Forbid, None)),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_cmd_flag(self) -> &'static str {
|
||||
match self {
|
||||
Level::Warn => "-W",
|
||||
@@ -583,6 +563,26 @@ pub fn default_level(&self, edition: Edition) -> Level {
|
||||
}
|
||||
}
|
||||
|
||||
/// The target of the `by_name` map, which accounts for renaming/deprecation.
|
||||
#[derive(Debug)]
|
||||
pub enum TargetLint {
|
||||
/// A direct lint target
|
||||
Id(LintId),
|
||||
|
||||
/// Temporary renaming, used for easing migration pain; see #16545
|
||||
Renamed(String, LintId),
|
||||
|
||||
/// Lint with this name existed previously, but has been removed/deprecated.
|
||||
/// The string argument is the reason for removal.
|
||||
Removed(String),
|
||||
|
||||
/// A lint name that should give no warnings and have no effect.
|
||||
///
|
||||
/// This is used by rustc to avoid warning about old rustdoc lints before rustdoc registers
|
||||
/// them as tool lints.
|
||||
Ignored,
|
||||
}
|
||||
|
||||
/// Identifies a lint known to the compiler.
|
||||
#[derive(Clone, Copy, Debug)]
|
||||
pub struct LintId {
|
||||
@@ -802,6 +802,29 @@ pub enum AttributeLintKind {
|
||||
name: Symbol,
|
||||
},
|
||||
OnMoveMalformedAttrExpectedLiteralOrDelimiter,
|
||||
RenamedLint {
|
||||
name: Symbol,
|
||||
replace: Symbol,
|
||||
suggestion: Span,
|
||||
},
|
||||
DeprecatedLintName {
|
||||
name: Symbol,
|
||||
suggestion: Span,
|
||||
replace: Symbol,
|
||||
},
|
||||
RemovedLint {
|
||||
name: Symbol,
|
||||
reason: String,
|
||||
},
|
||||
UnknownLint {
|
||||
name: Symbol,
|
||||
span: Span,
|
||||
suggestion: Option<(Symbol, bool)>,
|
||||
},
|
||||
IgnoredUnlessCrateSpecified {
|
||||
level: Symbol,
|
||||
name: Symbol,
|
||||
},
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, HashStable_Generic)]
|
||||
@@ -810,6 +833,31 @@ pub enum FormatWarning {
|
||||
InvalidSpecifier { name: String, span: Span },
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum CheckLintNameResult<'a> {
|
||||
Ok(&'a [LintId]),
|
||||
/// Lint doesn't exist. Potentially contains a suggestion for a correct lint name.
|
||||
NoLint(Option<(Symbol, bool)>),
|
||||
/// The lint refers to a tool that has not been registered.
|
||||
NoTool,
|
||||
/// The lint has been renamed to a new name.
|
||||
Renamed(Symbol),
|
||||
/// Lint that previously was part of rustc, but now is part of external lint tool
|
||||
RenamedToolLint(Symbol),
|
||||
/// The lint has been removed due to the given reason.
|
||||
Removed(String),
|
||||
|
||||
/// The lint is from a tool. The `LintId` will be returned as if it were a
|
||||
/// rustc lint. The `Option<String>` indicates if the lint has been
|
||||
/// renamed.
|
||||
Tool(&'a [LintId], Option<String>),
|
||||
|
||||
/// The lint is from a tool. Either the lint does not exist in the tool or
|
||||
/// the code was not compiled with the tool and therefore the lint was
|
||||
/// never added to the `LintStore`.
|
||||
MissingTool,
|
||||
}
|
||||
|
||||
pub type RegisteredTools = FxIndexSet<Ident>;
|
||||
|
||||
/// Declares a static item of type `&'static Lint`.
|
||||
|
||||
@@ -85,7 +85,8 @@
|
||||
|
||||
use interpret::ErrorHandled;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::HirId;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::{Attribute, HirId};
|
||||
use rustc_index::{IndexSlice, IndexVec};
|
||||
use rustc_middle::middle::region;
|
||||
use rustc_middle::mir::{self, *};
|
||||
@@ -93,7 +94,6 @@
|
||||
use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_pattern_analysis::rustc::RustcPatCtxt;
|
||||
use rustc_session::lint::Level;
|
||||
use rustc_span::{DUMMY_SP, Span, Spanned};
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
@@ -1298,7 +1298,12 @@ fn maybe_lint_level_root_bounded(&mut self, orig_id: HirId) -> HirId {
|
||||
break;
|
||||
}
|
||||
|
||||
if self.tcx.hir_attrs(id).iter().any(|attr| Level::from_attr(attr).is_some()) {
|
||||
if self
|
||||
.tcx
|
||||
.hir_attrs(id)
|
||||
.iter()
|
||||
.any(|attr| matches!(attr, Attribute::Parsed(AttributeKind::LintAttributes { .. })))
|
||||
{
|
||||
// This is a rare case. It's for a node path that doesn't reach the root due to an
|
||||
// intervening lint level attribute. This result doesn't get cached.
|
||||
return id;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
use std::slice;
|
||||
|
||||
use rustc_abi::ExternAbi;
|
||||
use rustc_ast::{AttrStyle, MetaItemKind, ast};
|
||||
use rustc_ast::ast;
|
||||
use rustc_attr_parsing::{AttributeParser, Late};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::thin_vec::ThinVec;
|
||||
@@ -19,8 +19,8 @@
|
||||
use rustc_feature::{AttributeDuplicates, AttributeType, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute};
|
||||
use rustc_hir::attrs::diagnostic::Directive;
|
||||
use rustc_hir::attrs::{
|
||||
AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr,
|
||||
ReprAttr, SanitizerSet,
|
||||
AttributeKind, CrateType, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution,
|
||||
InlineAttr, LintAttribute, ReprAttr, SanitizerSet,
|
||||
};
|
||||
use rustc_hir::def::DefKind;
|
||||
use rustc_hir::def_id::LocalModDefId;
|
||||
@@ -37,7 +37,6 @@
|
||||
use rustc_middle::ty::error::{ExpectedFound, TypeError};
|
||||
use rustc_middle::ty::{self, TyCtxt, TypingMode};
|
||||
use rustc_middle::{bug, span_bug};
|
||||
use rustc_session::config::CrateType;
|
||||
use rustc_session::lint;
|
||||
use rustc_session::lint::builtin::{
|
||||
CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_FORMAT_LITERALS,
|
||||
@@ -141,7 +140,6 @@ fn check_attributes(
|
||||
let mut seen = FxHashMap::default();
|
||||
let attrs = self.tcx.hir_attrs(hir_id);
|
||||
for attr in attrs {
|
||||
let mut style = None;
|
||||
match attr {
|
||||
Attribute::Parsed(AttributeKind::ProcMacro(_)) => {
|
||||
self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
|
||||
@@ -223,6 +221,7 @@ fn check_attributes(
|
||||
Attribute::Parsed(AttributeKind::OnMove { span, directive }) => {
|
||||
self.check_diagnostic_on_move(*span, hir_id, target, directive.as_deref())
|
||||
},
|
||||
Attribute::Parsed(AttributeKind::LintAttributes(sub_attrs)) => self.check_lint_attr(hir_id, sub_attrs),
|
||||
Attribute::Parsed(
|
||||
// tidy-alphabetical-start
|
||||
AttributeKind::RustcAllowIncoherentImpl(..)
|
||||
@@ -380,18 +379,8 @@ fn check_attributes(
|
||||
| AttributeKind::WindowsSubsystem(..)
|
||||
// tidy-alphabetical-end
|
||||
) => { /* do nothing */ }
|
||||
Attribute::Unparsed(attr_item) => {
|
||||
style = Some(attr_item.style);
|
||||
Attribute::Unparsed(_) => {
|
||||
match attr.path().as_slice() {
|
||||
[
|
||||
// ok
|
||||
sym::allow
|
||||
| sym::expect
|
||||
| sym::warn
|
||||
| sym::deny
|
||||
| sym::forbid,
|
||||
..
|
||||
] => {}
|
||||
[name, rest@..] => {
|
||||
match BUILTIN_ATTRIBUTE_MAP.get(name) {
|
||||
Some(_) => {
|
||||
@@ -473,8 +462,7 @@ fn check_attributes(
|
||||
&mut seen,
|
||||
);
|
||||
}
|
||||
|
||||
self.check_unused_attribute(hir_id, attr, style)
|
||||
self.check_unused_attribute(hir_id, attr)
|
||||
}
|
||||
|
||||
self.check_repr(attrs, span, target, item, hir_id);
|
||||
@@ -1583,88 +1571,76 @@ fn check_macro_export(&self, hir_id: HirId, attr_span: Span, target: Target) {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute, style: Option<AttrStyle>) {
|
||||
// Warn on useless empty attributes.
|
||||
// FIXME(jdonszelmann): this lint should be moved to attribute parsing, see `AcceptContext::warn_empty_attribute`
|
||||
let note =
|
||||
if attr.has_any_name(&[sym::allow, sym::expect, sym::warn, sym::deny, sym::forbid])
|
||||
&& attr.meta_item_list().is_some_and(|list| list.is_empty())
|
||||
{
|
||||
errors::UnusedNote::EmptyList { name: attr.name().unwrap() }
|
||||
} else if attr.has_any_name(&[
|
||||
sym::allow,
|
||||
sym::warn,
|
||||
sym::deny,
|
||||
sym::forbid,
|
||||
sym::expect,
|
||||
]) && let Some(meta) = attr.meta_item_list()
|
||||
&& let [meta] = meta.as_slice()
|
||||
&& let Some(item) = meta.meta_item()
|
||||
&& let MetaItemKind::NameValue(_) = &item.kind
|
||||
&& item.path == sym::reason
|
||||
{
|
||||
errors::UnusedNote::NoLints { name: attr.name().unwrap() }
|
||||
} else if attr.has_any_name(&[
|
||||
sym::allow,
|
||||
sym::warn,
|
||||
sym::deny,
|
||||
sym::forbid,
|
||||
sym::expect,
|
||||
]) && let Some(meta) = attr.meta_item_list()
|
||||
&& meta.iter().any(|meta| {
|
||||
meta.meta_item().map_or(false, |item| {
|
||||
item.path == sym::linker_messages || item.path == sym::linker_info
|
||||
})
|
||||
})
|
||||
{
|
||||
if hir_id != CRATE_HIR_ID {
|
||||
match style {
|
||||
Some(ast::AttrStyle::Outer) => {
|
||||
let attr_span = attr.span();
|
||||
let bang_position = self
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_until_char(attr_span, '[')
|
||||
.shrink_to_hi();
|
||||
fn check_lint_attr(&self, hir_id: HirId, sub_attrs: &[LintAttribute]) {
|
||||
for LintAttribute { attr_span, lint_instances, attr_style, .. } in sub_attrs {
|
||||
if !lint_instances.iter().any(|id| {
|
||||
id.lint_name() == sym::linker_messages || id.lint_name() == sym::linker_info
|
||||
}) {
|
||||
continue;
|
||||
};
|
||||
let note = if hir_id != CRATE_HIR_ID {
|
||||
match attr_style {
|
||||
ast::AttrStyle::Outer => {
|
||||
let attr_span = attr_span;
|
||||
let bang_position = self
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_until_char(*attr_span, '[')
|
||||
.shrink_to_hi();
|
||||
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr_span,
|
||||
errors::OuterCrateLevelAttr {
|
||||
suggestion: errors::OuterCrateLevelAttrSuggestion {
|
||||
bang_position,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span(),
|
||||
errors::InnerCrateLevelAttr,
|
||||
),
|
||||
};
|
||||
return;
|
||||
} else {
|
||||
let never_needs_link = self
|
||||
.tcx
|
||||
.crate_types()
|
||||
.iter()
|
||||
.all(|kind| matches!(kind, CrateType::Rlib | CrateType::StaticLib));
|
||||
if never_needs_link {
|
||||
errors::UnusedNote::LinkerMessagesBinaryCrateOnly
|
||||
} else {
|
||||
return;
|
||||
*attr_span,
|
||||
errors::OuterCrateLevelAttr {
|
||||
suggestion: errors::OuterCrateLevelAttrSuggestion { bang_position },
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
} else if attr.has_name(sym::default_method_body_is_const) {
|
||||
errors::UnusedNote::DefaultMethodBodyConst
|
||||
ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
*attr_span,
|
||||
errors::InnerCrateLevelAttr,
|
||||
),
|
||||
};
|
||||
continue;
|
||||
} else {
|
||||
return;
|
||||
let never_needs_link = self
|
||||
.tcx
|
||||
.crate_types()
|
||||
.iter()
|
||||
.all(|kind| matches!(kind, CrateType::Rlib | CrateType::StaticLib));
|
||||
if never_needs_link {
|
||||
errors::UnusedNote::LinkerMessagesBinaryCrateOnly
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
*attr_span,
|
||||
errors::Unused { attr_span: *attr_span, note },
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) {
|
||||
// Warn on useless empty attributes.
|
||||
// FIXME(jdonszelmann): this lint should be moved to attribute parsing, see `AcceptContext::warn_empty_attribute`
|
||||
let note = if attr.has_any_name(&[sym::feature])
|
||||
&& attr.meta_item_list().is_some_and(|list| list.is_empty())
|
||||
{
|
||||
errors::UnusedNote::EmptyList { name: attr.name().unwrap() }
|
||||
} else if attr.has_name(sym::default_method_body_is_const) {
|
||||
errors::UnusedNote::DefaultMethodBodyConst
|
||||
} else {
|
||||
return;
|
||||
};
|
||||
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
|
||||
@@ -294,8 +294,6 @@ pub(crate) enum MacroExport {
|
||||
pub(crate) enum UnusedNote {
|
||||
#[note("attribute `{$name}` with an empty list has no effect")]
|
||||
EmptyList { name: Symbol },
|
||||
#[note("attribute `{$name}` without any lints has no effect")]
|
||||
NoLints { name: Symbol },
|
||||
#[note("`default_method_body_is_const` has been replaced with `const` on traits")]
|
||||
DefaultMethodBodyConst,
|
||||
#[note(
|
||||
|
||||
@@ -146,7 +146,7 @@ fn visit_item(&mut self, i: &'a Item) {
|
||||
let mut parser = AttributeParser::<'_, Early>::new(
|
||||
&self.resolver.tcx.sess,
|
||||
self.resolver.tcx.features(),
|
||||
Vec::new(),
|
||||
self.resolver.tcx().registered_tools(()),
|
||||
Early { emit_errors: ShouldEmit::Nothing },
|
||||
);
|
||||
let attrs = parser.parse_attribute_list(
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
Input, InstrumentCoverage, OptLevel, OutFileName, OutputType, SwitchWithOptPath,
|
||||
};
|
||||
use crate::filesearch::FileSearch;
|
||||
use crate::lint::LintId;
|
||||
use crate::lint::{CheckLintNameResult, LintId, RegisteredTools};
|
||||
use crate::parse::{ParseSess, add_feature_diagnostics};
|
||||
use crate::search_paths::SearchPath;
|
||||
use crate::{errors, filesearch, lint};
|
||||
@@ -81,6 +81,15 @@ pub struct CompilerIO {
|
||||
pub trait DynLintStore: Any + DynSync + DynSend {
|
||||
/// Provides a way to access lint groups without depending on `rustc_lint`
|
||||
fn lint_groups_iter(&self) -> Box<dyn Iterator<Item = LintGroup> + '_>;
|
||||
|
||||
fn check_lint_name(
|
||||
&self,
|
||||
lint_name: &str,
|
||||
tool_name: Option<Symbol>,
|
||||
registered_tools: &RegisteredTools,
|
||||
) -> CheckLintNameResult<'_>;
|
||||
|
||||
fn find_lints(&self, lint_name: &str) -> Option<&[LintId]>;
|
||||
}
|
||||
|
||||
/// Represents the data associated with a compilation
|
||||
|
||||
@@ -142,7 +142,7 @@ pub fn span_data_to_lines_and_cols(
|
||||
lo_line_number,
|
||||
span_data.lo - lo_line_bounds.start,
|
||||
hi_line_number,
|
||||
span_data.hi - hi_line_bounds.start,
|
||||
span_data.hi,
|
||||
))
|
||||
}
|
||||
|
||||
|
||||
@@ -583,7 +583,7 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if matches!(name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
|
||||
allow_attributes_without_reason::check(cx, name, items, attr);
|
||||
}
|
||||
if is_lint_level(name, attr.id) {
|
||||
if is_lint_level(name) {
|
||||
blanket_clippy_restriction_lints::check(cx, name, items);
|
||||
}
|
||||
if items.is_empty() || !attr.has_name(sym::deprecated) {
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
use crate::attrs::is_lint_level;
|
||||
|
||||
use super::{Attribute, UNNECESSARY_CLIPPY_CFG};
|
||||
use clippy_utils::diagnostics::{span_lint_and_note, span_lint_and_sugg};
|
||||
use clippy_utils::source::SpanRangeExt;
|
||||
use itertools::Itertools;
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, Level};
|
||||
use rustc_lint::{EarlyContext};
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(
|
||||
@@ -13,9 +15,10 @@ pub(super) fn check(
|
||||
behind_cfg_attr: &rustc_ast::MetaItem,
|
||||
attr: &Attribute,
|
||||
) {
|
||||
// FIXME use proper attr parsing here
|
||||
if cfg_attr.has_name(sym::clippy)
|
||||
&& let Some(ident) = behind_cfg_attr.ident()
|
||||
&& Level::from_symbol(ident.name, || Some(attr.id)).is_some()
|
||||
&& is_lint_level(ident.name)
|
||||
&& let Some(items) = behind_cfg_attr.meta_item_list()
|
||||
{
|
||||
let nb_items = items.len();
|
||||
|
||||
@@ -15,7 +15,7 @@ pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
|
||||
return;
|
||||
}
|
||||
if let Some(lint_list) = &attr.meta_item_list()
|
||||
&& attr.name().is_some_and(|name| is_lint_level(name, attr.id))
|
||||
&& attr.name().is_some_and(is_lint_level)
|
||||
{
|
||||
for lint in lint_list {
|
||||
match item.kind {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
use clippy_utils::macros::{is_panic, macro_backtrace};
|
||||
use rustc_ast::{AttrId, MetaItemInner};
|
||||
use rustc_ast::{MetaItemInner};
|
||||
use rustc_hir::{
|
||||
Block, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, StmtKind, TraitFn, TraitItem, TraitItemKind,
|
||||
};
|
||||
@@ -16,8 +16,8 @@ pub(super) fn is_word(nmi: &MetaItemInner, expected: Symbol) -> bool {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn is_lint_level(symbol: Symbol, attr_id: AttrId) -> bool {
|
||||
Level::from_symbol(symbol, || Some(attr_id)).is_some()
|
||||
pub(super) fn is_lint_level(symbol: Symbol) -> bool {
|
||||
Level::from_symbol(symbol).is_some()
|
||||
}
|
||||
|
||||
pub(super) fn is_relevant_item(cx: &LateContext<'_>, item: &Item<'_>) -> bool {
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
use clippy_utils::msrvs::Msrv;
|
||||
use clippy_utils::source::{HasSession, IntoSpan as _, SpanRangeExt, snippet, snippet_block_with_applicability};
|
||||
use clippy_utils::{can_use_if_let_chains, span_contains_non_whitespace, sym, tokenize_with_text};
|
||||
use rustc_ast::{BinOpKind, MetaItemInner};
|
||||
use rustc_ast::BinOpKind;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::{Block, Expr, ExprKind, StmtKind};
|
||||
use rustc_hir::attrs::{AttributeKind, LintAttributeKind};
|
||||
use rustc_hir::{Attribute, Block, Expr, ExprKind, StmtKind};
|
||||
use rustc_lexer::TokenKind;
|
||||
use rustc_lint::{LateContext, LateLintPass, Level};
|
||||
use rustc_lint::{LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::{BytePos, Span, Symbol};
|
||||
|
||||
@@ -237,19 +238,26 @@ fn check_significant_tokens_and_expect_attrs(
|
||||
!span_contains_non_whitespace(cx, span, self.lint_commented_code)
|
||||
},
|
||||
|
||||
[attr]
|
||||
if matches!(Level::from_attr(attr), Some((Level::Expect, _)))
|
||||
&& let Some(metas) = attr.meta_item_list()
|
||||
&& let Some(MetaItemInner::MetaItem(meta_item)) = metas.first()
|
||||
&& let [tool, lint_name] = meta_item.path.segments.as_slice()
|
||||
&& tool.ident.name == sym::clippy
|
||||
&& [expected_lint_name, sym::style, sym::all].contains(&lint_name.ident.name) =>
|
||||
{
|
||||
// There is an `expect` attribute -- check that there is no _other_ significant text
|
||||
let span_before_attr = inner_if.span.split_at(1).1.until(attr.span());
|
||||
let span_after_attr = attr.span().between(inner_if_expr.span);
|
||||
!span_contains_non_whitespace(cx, span_before_attr, self.lint_commented_code)
|
||||
&& !span_contains_non_whitespace(cx, span_after_attr, self.lint_commented_code)
|
||||
[
|
||||
Attribute::Parsed(AttributeKind::LintAttributes(sub_attrs)),
|
||||
] => {
|
||||
sub_attrs
|
||||
.into_iter()
|
||||
.filter(|attr|attr.kind == LintAttributeKind::Expect)
|
||||
.flat_map(|attr| attr.lint_instances.iter().map(|group| (attr.attr_span, group)))
|
||||
.filter(|(_, lint_id)| {
|
||||
lint_id.tool_is_named(sym::clippy)
|
||||
&& (expected_lint_name == lint_id.lint_name()
|
||||
|| [expected_lint_name, sym::style, sym::all]
|
||||
.contains(&lint_id.original_name_without_tool()))
|
||||
})
|
||||
.any(|(attr_span, _)| {
|
||||
// There is an `expect` attribute -- check that there is no _other_ significant text
|
||||
let span_before_attr = inner_if.span.split_at(1).1.until(attr_span);
|
||||
let span_after_attr = attr_span.between(inner_if_expr.span);
|
||||
!span_contains_non_whitespace(cx, span_before_attr, self.lint_commented_code)
|
||||
&& !span_contains_non_whitespace(cx, span_after_attr, self.lint_commented_code)
|
||||
})
|
||||
},
|
||||
|
||||
// There are other attributes, which are significant tokens -- check failed
|
||||
|
||||
@@ -4,11 +4,11 @@
|
||||
binary_expr_needs_parentheses, is_from_proc_macro, leaks_droppable_temporary_with_limited_lifetime,
|
||||
span_contains_cfg, span_find_starting_semi, sym,
|
||||
};
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_hir::attrs::{AttributeKind, LintAttributeKind};
|
||||
use rustc_hir::intravisit::FnKind;
|
||||
use rustc_hir::{Body, Expr, ExprKind, HirId, LangItem, MatchSource, StmtKind};
|
||||
use rustc_lint::{LateContext, Level, LintContext};
|
||||
use rustc_hir::{Attribute, Body, Expr, ExprKind, HirId, LangItem, MatchSource, StmtKind};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_middle::ty::{self, Ty};
|
||||
use rustc_span::{BytePos, Pos, Span};
|
||||
use std::borrow::Cow;
|
||||
@@ -180,20 +180,18 @@ fn check_final_expr<'tcx>(
|
||||
// actually fulfill the expectation (clippy::#12998)
|
||||
match cx.tcx.hir_attrs(expr.hir_id) {
|
||||
[] => {},
|
||||
[attr] => {
|
||||
if matches!(Level::from_attr(attr), Some((Level::Expect, _)))
|
||||
&& let metas = attr.meta_item_list()
|
||||
&& let Some(lst) = metas
|
||||
&& let [MetaItemInner::MetaItem(meta_item), ..] = lst.as_slice()
|
||||
&& let [tool, lint_name] = meta_item.path.segments.as_slice()
|
||||
&& tool.ident.name == sym::clippy
|
||||
&& matches!(
|
||||
lint_name.ident.name,
|
||||
sym::needless_return | sym::style | sym::all | sym::warnings
|
||||
)
|
||||
[Attribute::Parsed(AttributeKind::LintAttributes(sub_attrs))] => {
|
||||
if !sub_attrs
|
||||
.into_iter()
|
||||
.filter(|attr| attr.kind == LintAttributeKind::Expect)
|
||||
.flat_map(|attr| &attr.lint_instances)
|
||||
.any(|lint| {
|
||||
matches!(
|
||||
lint.original_name_without_tool(),
|
||||
sym::needless_return | sym::style | sym::all | sym::warnings
|
||||
)
|
||||
})
|
||||
{
|
||||
// This is an expectation of the `needless_return` lint
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
},
|
||||
|
||||
@@ -36,8 +36,6 @@ pub fn rustc_lints() {
|
||||
|
||||
#[expect(invalid_nan_comparisons)]
|
||||
//~^ ERROR: this lint expectation is unfulfilled
|
||||
//~| NOTE: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
//~| ERROR: this lint expectation is unfulfilled
|
||||
let _b = x == 5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,36 +14,28 @@ LL | #[expect(invalid_nan_comparisons)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this lint expectation is unfulfilled
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:37:18
|
||||
|
|
||||
LL | #[expect(invalid_nan_comparisons)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: this lint expectation is unfulfilled
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:110:14
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:108:14
|
||||
|
|
||||
LL | #[expect(clippy::almost_swapped)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this lint expectation is unfulfilled
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:118:14
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:116:14
|
||||
|
|
||||
LL | #[expect(clippy::bytes_nth)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this lint expectation is unfulfilled
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:124:14
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:122:14
|
||||
|
|
||||
LL | #[expect(clippy::if_same_then_else)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this lint expectation is unfulfilled
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:130:14
|
||||
--> tests/ui/expect_tool_lint_rfc_2383.rs:128:14
|
||||
|
|
||||
LL | #[expect(clippy::overly_complex_bool_expr)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
|
||||
@@ -1,23 +1,11 @@
|
||||
error: unknown lint: `clippy::All`
|
||||
--> tests/ui/unknown_clippy_lints.rs:3:10
|
||||
|
|
||||
LL | #![allow(clippy::All)]
|
||||
| ^^^^^^^^^^^ help: did you mean: `clippy::all`
|
||||
|
|
||||
= note: `-D unknown-lints` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(unknown_lints)]`
|
||||
|
||||
error: unknown lint: `clippy::CMP_OWNED`
|
||||
--> tests/ui/unknown_clippy_lints.rs:5:9
|
||||
|
|
||||
LL | #![warn(clippy::CMP_OWNED)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_owned`
|
||||
|
||||
error: unknown lint: `clippy::if_not_els`
|
||||
--> tests/ui/unknown_clippy_lints.rs:9:8
|
||||
|
|
||||
LL | #[warn(clippy::if_not_els)]
|
||||
| ^^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::if_not_else`
|
||||
|
|
||||
= note: `-D unknown-lints` implied by `-D warnings`
|
||||
= help: to override `-D warnings` add `#[allow(unknown_lints)]`
|
||||
|
||||
error: unknown lint: `clippy::UNNecsaRy_cAst`
|
||||
--> tests/ui/unknown_clippy_lints.rs:11:8
|
||||
@@ -67,5 +55,17 @@ LL - #[warn(clippy::missing_docs)]
|
||||
LL + #[warn(missing_docs)]
|
||||
|
|
||||
|
||||
error: unknown lint: `clippy::All`
|
||||
--> tests/ui/unknown_clippy_lints.rs:3:10
|
||||
|
|
||||
LL | #![allow(clippy::All)]
|
||||
| ^^^^^^^^^^^ help: did you mean: `clippy::all`
|
||||
|
||||
error: unknown lint: `clippy::CMP_OWNED`
|
||||
--> tests/ui/unknown_clippy_lints.rs:5:9
|
||||
|
|
||||
LL | #![warn(clippy::CMP_OWNED)]
|
||||
| ^^^^^^^^^^^^^^^^^ help: did you mean: `clippy::cmp_owned`
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
|
||||
|
||||
@@ -1,14 +1,15 @@
|
||||
#![attr = LintAttributes([LintAttribute {kind: Allow, attr_style: Inner,
|
||||
lint_instances: [incomplete_features]}])]
|
||||
#![attr = Feature([fn_delegation#0])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use std::prelude::rust_2021::*;
|
||||
//@ edition:2021
|
||||
//@ aux-crate:to_reuse_functions=to-reuse-functions.rs
|
||||
//@ pretty-mode:hir
|
||||
//@ pretty-compare-only
|
||||
//@ pp-exact:delegation-inherit-attributes.pp
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![attr = Feature([fn_delegation#0])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use std::prelude::rust_2021::*;
|
||||
|
||||
extern crate to_reuse_functions;
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//@ pretty-compare-only
|
||||
//@ pretty-mode:hir
|
||||
//@ pp-exact:delegation-inline-attribute.pp
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![attr = LintAttributes([LintAttribute {kind: Allow, attr_style: Inner,
|
||||
lint_instances: [incomplete_features]}])]
|
||||
#![attr = Feature([fn_delegation#0])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
//@ pretty-compare-only
|
||||
//@ pretty-mode:hir
|
||||
//@ pp-exact:delegation-inline-attribute.pp
|
||||
|
||||
|
||||
mod to_reuse {
|
||||
fn foo(x: usize) -> usize { x }
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//@ pretty-compare-only
|
||||
//@ pretty-mode:hir
|
||||
//@ pp-exact:hir-delegation.pp
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![attr = LintAttributes([LintAttribute {kind: Allow, attr_style: Inner,
|
||||
lint_instances: [incomplete_features]}])]
|
||||
#![attr = Feature([fn_delegation#0])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
//@ pretty-compare-only
|
||||
//@ pretty-mode:hir
|
||||
//@ pp-exact:hir-delegation.pp
|
||||
|
||||
|
||||
fn b<C>(e: C) { }
|
||||
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
#![attr = LintAttributes([LintAttribute {kind: Allow, attr_style: Inner,
|
||||
lint_instances: [unused_imports, unused_variables, unused_visibilities,
|
||||
unused_assignments, dead_code, unused_mut, unreachable_code,
|
||||
unreachable_patterns, unused_must_use, unused_unsafe, path_statements,
|
||||
unused_attributes, unused_macros, unused_macro_rules, unused_allocation,
|
||||
unused_doc_comments, unused_extern_crates, unused_features, unused_labels,
|
||||
unused_parens, unused_braces, redundant_semicolons, map_unit_fn]}])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
//@ pretty-compare-only
|
||||
//@ pretty-mode:hir
|
||||
//@ pp-exact:hir-lifetimes.pp
|
||||
|
||||
// This tests the pretty-printing of lifetimes in lots of ways.
|
||||
|
||||
#![allow(unused)]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
|
||||
struct Foo<'a> {
|
||||
x: &'a u32,
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
#![attr = Feature([pin_ergonomics#0])]
|
||||
#![attr = LintAttributes([LintAttribute {kind: Allow, attr_style: Inner,
|
||||
lint_instances: [dead_code, incomplete_features]}])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
//@ pretty-compare-only
|
||||
//@ pretty-mode:hir
|
||||
//@ pp-exact:pin-ergonomics-hir.pp
|
||||
|
||||
#![allow(dead_code, incomplete_features)]
|
||||
#![attr = Feature([pin_ergonomics#0])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
|
||||
use std::pin::Pin;
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// compile-args: --crate-type lib
|
||||
|
||||
// This file does not emit the rename warnings
|
||||
// due to compilation aborting before we emit delayed lints
|
||||
|
||||
#![deny(broken_intra_doc_links)]
|
||||
//! [x]
|
||||
//~^ ERROR unresolved link
|
||||
|
||||
#![deny(rustdoc::non_autolinks)]
|
||||
//! http://example.com
|
||||
//~^ ERROR not a hyperlink
|
||||
@@ -0,0 +1,32 @@
|
||||
error: unresolved link to `x`
|
||||
--> $DIR/renamed-lint-still-applies-2.rs:7:6
|
||||
|
|
||||
LL | //! [x]
|
||||
| ^ no item named `x` in scope
|
||||
|
|
||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||
note: the lint level is defined here
|
||||
--> $DIR/renamed-lint-still-applies-2.rs:6:9
|
||||
|
|
||||
LL | #![deny(broken_intra_doc_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this URL is not a hyperlink
|
||||
--> $DIR/renamed-lint-still-applies-2.rs:11:5
|
||||
|
|
||||
LL | //! http://example.com
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: bare URLs are not automatically turned into clickable links
|
||||
note: the lint level is defined here
|
||||
--> $DIR/renamed-lint-still-applies-2.rs:10:9
|
||||
|
|
||||
LL | #![deny(rustdoc::non_autolinks)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use an automatic link instead
|
||||
|
|
||||
LL | //! <http://example.com>
|
||||
| + +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
//@ check-pass
|
||||
// compile-args: --crate-type lib
|
||||
#![deny(broken_intra_doc_links)]
|
||||
//~^ WARNING renamed to `rustdoc::broken_intra_doc_links`
|
||||
//! [x]
|
||||
//~^ ERROR unresolved link
|
||||
|
||||
#![deny(rustdoc::non_autolinks)]
|
||||
//~^ WARNING renamed to `rustdoc::bare_urls`
|
||||
//! http://example.com
|
||||
//~^ ERROR not a hyperlink
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
warning: lint `broken_intra_doc_links` has been renamed to `rustdoc::broken_intra_doc_links`
|
||||
--> $DIR/renamed-lint-still-applies.rs:2:9
|
||||
--> $DIR/renamed-lint-still-applies.rs:3:9
|
||||
|
|
||||
LL | #![deny(broken_intra_doc_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::broken_intra_doc_links`
|
||||
@@ -7,40 +7,10 @@ LL | #![deny(broken_intra_doc_links)]
|
||||
= note: `#[warn(renamed_and_removed_lints)]` on by default
|
||||
|
||||
warning: lint `rustdoc::non_autolinks` has been renamed to `rustdoc::bare_urls`
|
||||
--> $DIR/renamed-lint-still-applies.rs:7:9
|
||||
--> $DIR/renamed-lint-still-applies.rs:6:9
|
||||
|
|
||||
LL | #![deny(rustdoc::non_autolinks)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `rustdoc::bare_urls`
|
||||
|
||||
error: unresolved link to `x`
|
||||
--> $DIR/renamed-lint-still-applies.rs:4:6
|
||||
|
|
||||
LL | //! [x]
|
||||
| ^ no item named `x` in scope
|
||||
|
|
||||
= help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`
|
||||
note: the lint level is defined here
|
||||
--> $DIR/renamed-lint-still-applies.rs:2:9
|
||||
|
|
||||
LL | #![deny(broken_intra_doc_links)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: this URL is not a hyperlink
|
||||
--> $DIR/renamed-lint-still-applies.rs:9:5
|
||||
|
|
||||
LL | //! http://example.com
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: bare URLs are not automatically turned into clickable links
|
||||
note: the lint level is defined here
|
||||
--> $DIR/renamed-lint-still-applies.rs:7:9
|
||||
|
|
||||
LL | #![deny(rustdoc::non_autolinks)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use an automatic link instead
|
||||
|
|
||||
LL | //! <http://example.com>
|
||||
| + +
|
||||
|
||||
error: aborting due to 2 previous errors; 2 warnings emitted
|
||||
warning: 2 warnings emitted
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<svg width="944px" height="434px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="740px" height="434px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
|
||||
|
Before Width: | Height: | Size: 3.8 KiB After Width: | Height: | Size: 3.8 KiB |
@@ -26,86 +26,6 @@ error[E0463]: can't find crate for `wloop`
|
||||
LL | extern crate wloop;
|
||||
| ^^^^^^^^^^^^^^^^^^^ can't find crate
|
||||
|
||||
error: malformed `allow` attribute input
|
||||
--> $DIR/malformed-attrs.rs:180:1
|
||||
|
|
||||
LL | #[allow]
|
||||
| ^^^^^^^^
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL | #[allow(lint1)]
|
||||
| +++++++
|
||||
LL | #[allow(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[allow(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: malformed `expect` attribute input
|
||||
--> $DIR/malformed-attrs.rs:182:1
|
||||
|
|
||||
LL | #[expect]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL | #[expect(lint1)]
|
||||
| +++++++
|
||||
LL | #[expect(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[expect(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: malformed `warn` attribute input
|
||||
--> $DIR/malformed-attrs.rs:184:1
|
||||
|
|
||||
LL | #[warn]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL | #[warn(lint1)]
|
||||
| +++++++
|
||||
LL | #[warn(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[warn(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: malformed `deny` attribute input
|
||||
--> $DIR/malformed-attrs.rs:186:1
|
||||
|
|
||||
LL | #[deny]
|
||||
| ^^^^^^^
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL | #[deny(lint1)]
|
||||
| +++++++
|
||||
LL | #[deny(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[deny(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: malformed `forbid` attribute input
|
||||
--> $DIR/malformed-attrs.rs:188:1
|
||||
|
|
||||
LL | #[forbid]
|
||||
| ^^^^^^^^^
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: the following are the possible correct uses
|
||||
|
|
||||
LL | #[forbid(lint1)]
|
||||
| +++++++
|
||||
LL | #[forbid(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[forbid(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error: the `#[proc_macro]` attribute is only usable with crates of the `proc-macro` crate type
|
||||
--> $DIR/malformed-attrs.rs:103:1
|
||||
|
|
||||
@@ -593,6 +513,96 @@ error[E0539]: malformed `linkage` attribute input
|
||||
LL | #[linkage]
|
||||
| ^^^^^^^^^^ expected this to be of the form `linkage = "..."`
|
||||
|
||||
error[E0539]: malformed `allow` attribute input
|
||||
--> $DIR/malformed-attrs.rs:180:1
|
||||
|
|
||||
LL | #[allow]
|
||||
| ^^-----^
|
||||
| |
|
||||
| expected this to be a list
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL | #[allow(lint1)]
|
||||
| +++++++
|
||||
LL | #[allow(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[allow(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0539]: malformed `expect` attribute input
|
||||
--> $DIR/malformed-attrs.rs:182:1
|
||||
|
|
||||
LL | #[expect]
|
||||
| ^^------^
|
||||
| |
|
||||
| expected this to be a list
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL | #[expect(lint1)]
|
||||
| +++++++
|
||||
LL | #[expect(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[expect(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0539]: malformed `warn` attribute input
|
||||
--> $DIR/malformed-attrs.rs:184:1
|
||||
|
|
||||
LL | #[warn]
|
||||
| ^^----^
|
||||
| |
|
||||
| expected this to be a list
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL | #[warn(lint1)]
|
||||
| +++++++
|
||||
LL | #[warn(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[warn(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0539]: malformed `deny` attribute input
|
||||
--> $DIR/malformed-attrs.rs:186:1
|
||||
|
|
||||
LL | #[deny]
|
||||
| ^^----^
|
||||
| |
|
||||
| expected this to be a list
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL | #[deny(lint1)]
|
||||
| +++++++
|
||||
LL | #[deny(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[deny(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0539]: malformed `forbid` attribute input
|
||||
--> $DIR/malformed-attrs.rs:188:1
|
||||
|
|
||||
LL | #[forbid]
|
||||
| ^^------^
|
||||
| |
|
||||
| expected this to be a list
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL | #[forbid(lint1)]
|
||||
| +++++++
|
||||
LL | #[forbid(lint1, lint2, ...)]
|
||||
| +++++++++++++++++++
|
||||
LL | #[forbid(lint1, lint2, lint3, reason = "...")]
|
||||
| +++++++++++++++++++++++++++++++++++++
|
||||
|
||||
error[E0539]: malformed `debugger_visualizer` attribute input
|
||||
--> $DIR/malformed-attrs.rs:190:1
|
||||
|
|
||||
|
||||
@@ -26,13 +26,10 @@ pub fn e() {}
|
||||
|
||||
#[unsafe(allow(unsafe(dead_code)))]
|
||||
//~^ ERROR: is not an unsafe attribute
|
||||
//~| ERROR: malformed lint attribute input
|
||||
//~| ERROR: malformed lint attribute input
|
||||
//~| ERROR: malformed
|
||||
//~| ERROR: expected identifier, found keyword `unsafe`
|
||||
//~| ERROR: expected identifier, found keyword `unsafe`
|
||||
//~| ERROR: expected identifier, found keyword `unsafe`
|
||||
//~| ERROR: malformed lint attribute input
|
||||
//~| ERROR: malformed lint attribute input
|
||||
//~| ERROR: malformed lint attribute input
|
||||
//~| ERROR: malformed lint attribute input
|
||||
pub fn f() {}
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -1,17 +1,3 @@
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/proc-unsafe-attributes.rs:27:16
|
||||
|
|
||||
LL | #[unsafe(allow(unsafe(dead_code)))]
|
||||
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/proc-unsafe-attributes.rs:27:16
|
||||
|
|
||||
LL | #[unsafe(allow(unsafe(dead_code)))]
|
||||
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: expected identifier, found keyword `unsafe`
|
||||
--> $DIR/proc-unsafe-attributes.rs:27:16
|
||||
|
|
||||
@@ -47,21 +33,17 @@ error: the `#[proc_macro_attribute]` attribute is only usable with crates of the
|
||||
LL | #[unsafe(proc_macro_attribute)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
error: expected identifier, found keyword `unsafe`
|
||||
--> $DIR/proc-unsafe-attributes.rs:27:16
|
||||
|
|
||||
LL | #[unsafe(allow(unsafe(dead_code)))]
|
||||
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
| ^^^^^^ expected identifier, found keyword
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/proc-unsafe-attributes.rs:27:16
|
||||
help: escape `unsafe` to use it as an identifier
|
||||
|
|
||||
LL | #[unsafe(allow(unsafe(dead_code)))]
|
||||
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
LL | #[unsafe(allow(r#unsafe(dead_code)))]
|
||||
| ++
|
||||
|
||||
error: `proc_macro` is not an unsafe attribute
|
||||
--> $DIR/proc-unsafe-attributes.rs:1:3
|
||||
@@ -132,23 +114,39 @@ LL | #[unsafe(allow(unsafe(dead_code)))]
|
||||
|
|
||||
= note: extraneous unsafe is not allowed in attributes
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
error: expected identifier, found keyword `unsafe`
|
||||
--> $DIR/proc-unsafe-attributes.rs:27:16
|
||||
|
|
||||
LL | #[unsafe(allow(unsafe(dead_code)))]
|
||||
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
| ^^^^^^ expected identifier, found keyword
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
help: escape `unsafe` to use it as an identifier
|
||||
|
|
||||
LL | #[unsafe(allow(r#unsafe(dead_code)))]
|
||||
| ++
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/proc-unsafe-attributes.rs:27:16
|
||||
error[E0565]: malformed `allow` attribute input
|
||||
--> $DIR/proc-unsafe-attributes.rs:27:1
|
||||
|
|
||||
LL | #[unsafe(allow(unsafe(dead_code)))]
|
||||
| ^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
| ^^^^^^^^^^^^^^^^^^^^^-----------^^^
|
||||
| |
|
||||
| didn't expect any arguments here
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #[unsafe(allow(unsafe(dead_code)))]
|
||||
LL + #[allow(lint1)]
|
||||
|
|
||||
LL - #[unsafe(allow(unsafe(dead_code)))]
|
||||
LL + #[allow(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #[unsafe(allow(unsafe(dead_code)))]
|
||||
LL + #[allow(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 18 previous errors
|
||||
error: aborting due to 15 previous errors
|
||||
|
||||
Some errors have detailed explanations: E0452, E0565.
|
||||
For more information about an error, try `rustc --explain E0452`.
|
||||
For more information about this error, try `rustc --explain E0565`.
|
||||
|
||||
@@ -1,15 +1,30 @@
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/deduplicate-diagnostics.rs:10:8
|
||||
|
|
||||
LL | #[deny("literal")]
|
||||
| ^^^^^^^^^ bad attribute argument
|
||||
|
||||
error: cannot find derive macro `Unresolved` in this scope
|
||||
--> $DIR/deduplicate-diagnostics.rs:6:10
|
||||
|
|
||||
LL | #[derive(Unresolved)]
|
||||
| ^^^^^^^^^^
|
||||
|
||||
error[E0539]: malformed `deny` attribute input
|
||||
--> $DIR/deduplicate-diagnostics.rs:10:1
|
||||
|
|
||||
LL | #[deny("literal")]
|
||||
| ^^^^^^^---------^^
|
||||
| |
|
||||
| expected a valid identifier here
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #[deny("literal")]
|
||||
LL + #[deny(lint1)]
|
||||
|
|
||||
LL - #[deny("literal")]
|
||||
LL + #[deny(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #[deny("literal")]
|
||||
LL + #[deny(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0452`.
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/deduplicate-diagnostics.rs:10:8
|
||||
|
|
||||
LL | #[deny("literal")]
|
||||
| ^^^^^^^^^ bad attribute argument
|
||||
|
||||
error: cannot find derive macro `Unresolved` in this scope
|
||||
--> $DIR/deduplicate-diagnostics.rs:6:10
|
||||
|
|
||||
@@ -18,22 +12,27 @@ LL | #[derive(Unresolved)]
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/deduplicate-diagnostics.rs:10:8
|
||||
error[E0539]: malformed `deny` attribute input
|
||||
--> $DIR/deduplicate-diagnostics.rs:10:1
|
||||
|
|
||||
LL | #[deny("literal")]
|
||||
| ^^^^^^^^^ bad attribute argument
|
||||
| ^^^^^^^---------^^
|
||||
| |
|
||||
| expected a valid identifier here
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/deduplicate-diagnostics.rs:10:8
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL | #[deny("literal")]
|
||||
| ^^^^^^^^^ bad attribute argument
|
||||
LL - #[deny("literal")]
|
||||
LL + #[deny(lint1)]
|
||||
|
|
||||
LL - #[deny("literal")]
|
||||
LL + #[deny(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #[deny("literal")]
|
||||
LL + #[deny(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0452`.
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
||||
@@ -7,7 +7,5 @@
|
||||
//[duplicate]~| ERROR cannot find derive macro `Unresolved` in this scope
|
||||
struct S;
|
||||
|
||||
#[deny("literal")] //~ ERROR malformed lint attribute input
|
||||
//[duplicate]~| ERROR malformed lint attribute input
|
||||
//[duplicate]~| ERROR malformed lint attribute input
|
||||
#[deny("literal")] //~ ERROR malformed `deny` attribute input [E0539]
|
||||
fn main() {}
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
#![allow(foo = "")] //~ ERROR E0452
|
||||
//~| ERROR E0452
|
||||
//~| ERROR E0452
|
||||
//~| ERROR E0452
|
||||
//~| ERROR E0452
|
||||
//~| ERROR E0452
|
||||
fn main() {
|
||||
}
|
||||
@@ -1,49 +0,0 @@
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/E0452.rs:1:10
|
||||
|
|
||||
LL | #![allow(foo = "")]
|
||||
| ^^^^^^^^ bad attribute argument
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/E0452.rs:1:10
|
||||
|
|
||||
LL | #![allow(foo = "")]
|
||||
| ^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/E0452.rs:1:10
|
||||
|
|
||||
LL | #![allow(foo = "")]
|
||||
| ^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/E0452.rs:1:10
|
||||
|
|
||||
LL | #![allow(foo = "")]
|
||||
| ^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/E0452.rs:1:10
|
||||
|
|
||||
LL | #![allow(foo = "")]
|
||||
| ^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/E0452.rs:1:10
|
||||
|
|
||||
LL | #![allow(foo = "")]
|
||||
| ^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0452`.
|
||||
@@ -12,41 +12,102 @@ warning: `#[macro_escape]` is a deprecated synonym for `#[macro_use]`
|
||||
LL | #[macro_escape]
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unknown lint: `x5400`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:42:9
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:1
|
||||
|
|
||||
LL | #![warn(x5400)]
|
||||
| ^^^^^
|
||||
LL | #[link(name = "x")]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | / mod link {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | mod inner { #![link(name = "x")] }
|
||||
... |
|
||||
LL | | }
|
||||
| |_- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:36:28
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:36:9
|
||||
|
|
||||
LL | #![warn(unused_attributes, unknown_lints)]
|
||||
| ^^^^^^^^^^^^^
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: unknown lint: `x5300`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:43:10
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
|
||||
|
|
||||
LL | #![allow(x5300)]
|
||||
| ^^^^^
|
||||
LL | #![link(name = "x")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: unknown lint: `x5200`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:11
|
||||
warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:98:12
|
||||
|
|
||||
LL | #![forbid(x5200)]
|
||||
| ^^^^^
|
||||
LL | #![feature(rust1)]
|
||||
| ^^^^^
|
||||
|
|
||||
= note: `#[warn(stable_features)]` on by default
|
||||
|
||||
warning: unknown lint: `x5100`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:9
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17
|
||||
|
|
||||
LL | #![deny(x5100)]
|
||||
| ^^^^^
|
||||
LL | mod inner { #![link(name = "x")] }
|
||||
| ------------^^^^^^^^^^^^^^^^^^^^-- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
|
||||
|
|
||||
LL | #[link(name = "x")] fn f() { }
|
||||
| ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5
|
||||
|
|
||||
LL | #[link(name = "x")] struct S;
|
||||
| ^^^^^^^^^^^^^^^^^^^ --------- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
|
||||
|
|
||||
LL | #[link(name = "x")] type T = S;
|
||||
| ^^^^^^^^^^^^^^^^^^^ ----------- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
|
||||
|
|
||||
LL | #[link(name = "x")] impl S { }
|
||||
| ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5
|
||||
|
|
||||
LL | #[link(name = "x")] extern "Rust" {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: unknown lint: `x5400`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:109:8
|
||||
|
|
||||
LL | #[warn(x5400)]
|
||||
| ^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:36:28
|
||||
|
|
||||
LL | #![warn(unused_attributes, unknown_lints)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
warning: unknown lint: `x5400`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:112:25
|
||||
@@ -186,91 +247,6 @@ warning: unknown lint: `x5100`
|
||||
LL | #[deny(x5100)] impl S { }
|
||||
| ^^^^^
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:685:1
|
||||
|
|
||||
LL | #[link(name = "x")]
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
...
|
||||
LL | / mod link {
|
||||
LL | |
|
||||
LL | |
|
||||
LL | | mod inner { #![link(name = "x")] }
|
||||
... |
|
||||
LL | | }
|
||||
| |_- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:36:9
|
||||
|
|
||||
LL | #![warn(unused_attributes, unknown_lints)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:70:1
|
||||
|
|
||||
LL | #![link(name = "x")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^ not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: the feature `rust1` has been stable since 1.0.0 and no longer requires an attribute to enable
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:98:12
|
||||
|
|
||||
LL | #![feature(rust1)]
|
||||
| ^^^^^
|
||||
|
|
||||
= note: `#[warn(stable_features)]` on by default
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:691:17
|
||||
|
|
||||
LL | mod inner { #![link(name = "x")] }
|
||||
| ------------^^^^^^^^^^^^^^^^^^^^-- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:696:5
|
||||
|
|
||||
LL | #[link(name = "x")] fn f() { }
|
||||
| ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:701:5
|
||||
|
|
||||
LL | #[link(name = "x")] struct S;
|
||||
| ^^^^^^^^^^^^^^^^^^^ --------- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:706:5
|
||||
|
|
||||
LL | #[link(name = "x")] type T = S;
|
||||
| ^^^^^^^^^^^^^^^^^^^ ----------- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:711:5
|
||||
|
|
||||
LL | #[link(name = "x")] impl S { }
|
||||
| ^^^^^^^^^^^^^^^^^^^ ---------- not an `extern` block
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: attribute should be applied to an `extern` block with non-Rust ABI
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:716:5
|
||||
|
|
||||
LL | #[link(name = "x")] extern "Rust" {}
|
||||
| ^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
|
||||
warning: `#[macro_use]` attribute cannot be used on functions
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:189:5
|
||||
|
|
||||
@@ -1522,6 +1498,30 @@ note: this attribute does not have an `!`, which means it is applied to this imp
|
||||
LL | #[type_length_limit="0100"] impl S { }
|
||||
| ^^^^^^^^^^
|
||||
|
||||
warning: unknown lint: `x5400`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:42:9
|
||||
|
|
||||
LL | #![warn(x5400)]
|
||||
| ^^^^^
|
||||
|
||||
warning: unknown lint: `x5300`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:43:10
|
||||
|
|
||||
LL | #![allow(x5300)]
|
||||
| ^^^^^
|
||||
|
||||
warning: unknown lint: `x5200`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:44:11
|
||||
|
|
||||
LL | #![forbid(x5200)]
|
||||
| ^^^^^
|
||||
|
||||
warning: unknown lint: `x5100`
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:9
|
||||
|
|
||||
LL | #![deny(x5100)]
|
||||
| ^^^^^
|
||||
|
||||
warning: `#[should_panic]` attribute cannot be used on crates
|
||||
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:49:1
|
||||
|
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
<svg width="1188px" height="470px" xmlns="http://www.w3.org/2000/svg">
|
||||
<svg width="1062px" height="470px" xmlns="http://www.w3.org/2000/svg">
|
||||
<style>
|
||||
.fg { fill: #AAAAAA }
|
||||
.bg { fill: #000000 }
|
||||
|
||||
|
Before Width: | Height: | Size: 5.1 KiB After Width: | Height: | Size: 5.1 KiB |
@@ -4,7 +4,7 @@ warning: unused attribute
|
||||
LL | #[forbid()]
|
||||
| ^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `forbid` with an empty list has no effect
|
||||
= note: using `forbid` with an empty list has no effect
|
||||
= note: requested on the command line with `-W unused-attributes`
|
||||
|
||||
warning: unused attribute
|
||||
@@ -13,7 +13,7 @@ warning: unused attribute
|
||||
LL | #[deny(reason = "ultion")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `deny` without any lints has no effect
|
||||
= note: using `deny` with an empty list has no effect
|
||||
|
||||
warning: unused attribute
|
||||
--> $DIR/empty-lint-attributes.rs:6:1
|
||||
@@ -21,7 +21,7 @@ warning: unused attribute
|
||||
LL | #![allow()]
|
||||
| ^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `allow` with an empty list has no effect
|
||||
= note: using `allow` with an empty list has no effect
|
||||
|
||||
warning: unused attribute
|
||||
--> $DIR/empty-lint-attributes.rs:7:1
|
||||
@@ -29,7 +29,7 @@ warning: unused attribute
|
||||
LL | #![warn(reason = "observationalism")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `warn` without any lints has no effect
|
||||
= note: using `warn` with an empty list has no effect
|
||||
|
||||
warning: 4 warnings emitted
|
||||
|
||||
|
||||
@@ -12,8 +12,10 @@ fn main() {
|
||||
|
||||
// This does nothing, since `#[allow(warnings)]` is itself
|
||||
// an inert attribute on a macro call
|
||||
#[allow(warnings)] #[inline] foo!(); //~ WARN unused attribute `allow`
|
||||
//~^ WARN `#[inline]` attribute cannot be used on macro calls
|
||||
#[allow(warnings)] #[inline] foo!();
|
||||
//~^ WARN `#[allow]` attribute cannot be used on macro calls [unused_attributes]
|
||||
//~| WARN previously accepted
|
||||
//~| WARN `#[inline]` attribute cannot be used on macro calls
|
||||
//~| WARN previously accepted
|
||||
|
||||
// This does work, since the attribute is on a parent
|
||||
|
||||
@@ -13,17 +13,14 @@ LL | #![warn(unused)]
|
||||
| ^^^^^^
|
||||
= note: `#[warn(unused_attributes)]` implied by `#[warn(unused)]`
|
||||
|
||||
warning: unused attribute `allow`
|
||||
warning: `#[allow]` attribute cannot be used on macro calls
|
||||
--> $DIR/inert-attr-macro.rs:15:5
|
||||
|
|
||||
LL | #[allow(warnings)] #[inline] foo!();
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
|
||||
--> $DIR/inert-attr-macro.rs:15:34
|
||||
|
|
||||
LL | #[allow(warnings)] #[inline] foo!();
|
||||
| ^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= help: `#[allow]` can be applied to associated consts, associated types, const parameters, const parameters, constants, crates, data types, enum variants, extern crates, foreign modules, foreign statics, function params, functions, global asms, impl blocks, lifetime parameters, lifetime parameters, macro defs, match arms, modules, pattern fields, statics, struct fields, struct fields, trait aliases, traits, type aliases, type parameters, type parameters, and use statements
|
||||
|
||||
warning: `#[inline]` attribute cannot be used on macro calls
|
||||
--> $DIR/inert-attr-macro.rs:15:24
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
error: unknown lint: `nonex_lint_top_level`
|
||||
--> $DIR/issue-97094.rs:5:25
|
||||
error: unknown lint: `nonex_lint_mod`
|
||||
--> $DIR/issue-97094.rs:10:24
|
||||
|
|
||||
LL | #![cfg_attr(true, allow(nonex_lint_top_level))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
LL | #[cfg_attr(true, allow(nonex_lint_mod))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the lint level is defined here
|
||||
--> $DIR/issue-97094.rs:1:9
|
||||
@@ -11,20 +11,6 @@ LL | #![deny(warnings)]
|
||||
| ^^^^^^^^
|
||||
= note: `#[deny(unknown_lints)]` implied by `#[deny(warnings)]`
|
||||
|
||||
error: lint `bare_trait_object` has been renamed to `bare_trait_objects`
|
||||
--> $DIR/issue-97094.rs:7:25
|
||||
|
|
||||
LL | #![cfg_attr(true, allow(bare_trait_object))]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects`
|
||||
|
|
||||
= note: `#[deny(renamed_and_removed_lints)]` implied by `#[deny(warnings)]`
|
||||
|
||||
error: unknown lint: `nonex_lint_mod`
|
||||
--> $DIR/issue-97094.rs:10:24
|
||||
|
|
||||
LL | #[cfg_attr(true, allow(nonex_lint_mod))]
|
||||
| ^^^^^^^^^^^^^^
|
||||
|
||||
error: unknown lint: `nonex_lint_mod_inner`
|
||||
--> $DIR/issue-97094.rs:13:29
|
||||
|
|
||||
@@ -49,5 +35,19 @@ error: unknown lint: `nonex_lint_fn`
|
||||
LL | #[allow(nonex_lint_fn)]
|
||||
| ^^^^^^^^^^^^^
|
||||
|
||||
error: unknown lint: `nonex_lint_top_level`
|
||||
--> $DIR/issue-97094.rs:5:25
|
||||
|
|
||||
LL | #![cfg_attr(true, allow(nonex_lint_top_level))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: lint `bare_trait_object` has been renamed to `bare_trait_objects`
|
||||
--> $DIR/issue-97094.rs:7:25
|
||||
|
|
||||
LL | #![cfg_attr(true, allow(bare_trait_object))]
|
||||
| ^^^^^^^^^^^^^^^^^ help: use the new name: `bare_trait_objects`
|
||||
|
|
||||
= note: `#[deny(renamed_and_removed_lints)]` implied by `#[deny(warnings)]`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
#![deny(keyword_idents)] // Should affect the submodule, but doesn't.
|
||||
#![deny(keyword_idents)]
|
||||
//@ edition: 2015
|
||||
//@ known-bug: #132218
|
||||
//@ check-pass (known bug; should be check-fail)
|
||||
|
||||
// Because `keyword_idents_2018` and `keyword_idents_2024` are pre-expansion
|
||||
// lints, configuring them via lint attributes doesn't propagate to submodules
|
||||
// in other files.
|
||||
// <https://github.com/rust-lang/rust/issues/132218>
|
||||
|
||||
#[path = "./auxiliary/multi_file_submod.rs"]
|
||||
mod multi_file_submod;
|
||||
//~? ERROR `async` is a keyword
|
||||
//~? WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
//~? ERROR `await` is a keyword
|
||||
//~? WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
//~? ERROR `try` is a keyword
|
||||
//~? WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
//~? ERROR `dyn` is a keyword
|
||||
//~? WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
//~? ERROR `gen` is a keyword
|
||||
//~? WARN this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
error: `async` is a keyword in the 2018 edition
|
||||
--> $DIR/./auxiliary/multi_file_submod.rs:4:4
|
||||
|
|
||||
LL | fn async() {}
|
||||
| ^^^^^ help: you can use a raw identifier to stay compatible: `r#async`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2018/new-keywords.html>
|
||||
note: the lint level is defined here
|
||||
--> $DIR/multi-file.rs:1:9
|
||||
|
|
||||
LL | #![deny(keyword_idents)]
|
||||
| ^^^^^^^^^^^^^^
|
||||
= note: `#[deny(keyword_idents_2018)]` implied by `#[deny(keyword_idents)]`
|
||||
|
||||
error: `await` is a keyword in the 2018 edition
|
||||
--> $DIR/./auxiliary/multi_file_submod.rs:5:4
|
||||
|
|
||||
LL | fn await() {}
|
||||
| ^^^^^ help: you can use a raw identifier to stay compatible: `r#await`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2018/new-keywords.html>
|
||||
|
||||
error: `try` is a keyword in the 2018 edition
|
||||
--> $DIR/./auxiliary/multi_file_submod.rs:6:4
|
||||
|
|
||||
LL | fn try() {}
|
||||
| ^^^ help: you can use a raw identifier to stay compatible: `r#try`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2018/new-keywords.html>
|
||||
|
||||
error: `dyn` is a keyword in the 2018 edition
|
||||
--> $DIR/./auxiliary/multi_file_submod.rs:7:4
|
||||
|
|
||||
LL | fn dyn() {}
|
||||
| ^^^ help: you can use a raw identifier to stay compatible: `r#dyn`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
|
||||
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2018/new-keywords.html>
|
||||
|
||||
error: `gen` is a keyword in the 2024 edition
|
||||
--> $DIR/./auxiliary/multi_file_submod.rs:10:4
|
||||
|
|
||||
LL | fn gen() {}
|
||||
| ^^^ help: you can use a raw identifier to stay compatible: `r#gen`
|
||||
|
|
||||
= warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024!
|
||||
= note: for more information, see <https://doc.rust-lang.org/edition-guide/rust-2024/gen-keyword.html>
|
||||
= note: `#[deny(keyword_idents_2024)]` implied by `#[deny(keyword_idents)]`
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
@@ -1,8 +1,4 @@
|
||||
#![deny = "foo"] //~ ERROR malformed `deny` attribute input
|
||||
#![allow(bar = "baz")] //~ ERROR malformed lint attribute
|
||||
//~| ERROR malformed lint attribute
|
||||
//~| ERROR malformed lint attribute
|
||||
//~| ERROR malformed lint attribute
|
||||
//~| ERROR malformed lint attribute
|
||||
//~| ERROR malformed lint attribute
|
||||
#![allow(bar = "baz")]
|
||||
//~^ ERROR malformed `allow` attribute input [E0539]
|
||||
fn main() { }
|
||||
|
||||
@@ -1,25 +1,13 @@
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/lint-malformed.rs:2:10
|
||||
|
|
||||
LL | #![allow(bar = "baz")]
|
||||
| ^^^^^^^^^^^ bad attribute argument
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/lint-malformed.rs:2:10
|
||||
|
|
||||
LL | #![allow(bar = "baz")]
|
||||
| ^^^^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: malformed `deny` attribute input
|
||||
error[E0539]: malformed `deny` attribute input
|
||||
--> $DIR/lint-malformed.rs:1:1
|
||||
|
|
||||
LL | #![deny = "foo"]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
| ^^^^^^^^-------^
|
||||
| |
|
||||
| expected this to be a list
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: the following are the possible correct uses
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #![deny = "foo"]
|
||||
LL + #![deny(lint1)]
|
||||
@@ -31,38 +19,27 @@ LL - #![deny = "foo"]
|
||||
LL + #![deny(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/lint-malformed.rs:2:10
|
||||
error[E0539]: malformed `allow` attribute input
|
||||
--> $DIR/lint-malformed.rs:2:1
|
||||
|
|
||||
LL | #![allow(bar = "baz")]
|
||||
| ^^^^^^^^^^^ bad attribute argument
|
||||
| ^^^^^^^^^-----------^^
|
||||
| |
|
||||
| the only valid argument here is `reason`
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #![allow(bar = "baz")]
|
||||
LL + #![allow(lint1)]
|
||||
|
|
||||
LL - #![allow(bar = "baz")]
|
||||
LL + #![allow(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #![allow(bar = "baz")]
|
||||
LL + #![allow(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/lint-malformed.rs:2:10
|
||||
|
|
||||
LL | #![allow(bar = "baz")]
|
||||
| ^^^^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/lint-malformed.rs:2:10
|
||||
|
|
||||
LL | #![allow(bar = "baz")]
|
||||
| ^^^^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/lint-malformed.rs:2:10
|
||||
|
|
||||
LL | #![allow(bar = "baz")]
|
||||
| ^^^^^^^^^^^ bad attribute argument
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 7 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0452`.
|
||||
For more information about this error, try `rustc --explain E0539`.
|
||||
|
||||
@@ -1,26 +1,32 @@
|
||||
//@ compile-flags: -Zdeduplicate-diagnostics=yes
|
||||
|
||||
#![warn(absolute_paths_not_starting_with_crate, reason = 0)]
|
||||
//~^ ERROR malformed lint attribute
|
||||
//~| NOTE reason must be a string literal
|
||||
//~^ ERROR malformed
|
||||
//~| NOTE expected a string literal here
|
||||
//~| NOTE for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
#![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
|
||||
//~^ ERROR malformed lint attribute
|
||||
//~| NOTE reason must be a string literal
|
||||
//~^ ERROR malformed
|
||||
//~| NOTE expected a normal string literal, not a byte string literal
|
||||
#![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
|
||||
//~^ ERROR malformed lint attribute
|
||||
//~| NOTE bad attribute argument
|
||||
//~^ ERROR malformed
|
||||
//~| NOTE the only valid argument here is `reason`
|
||||
//~| NOTE for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
#![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")]
|
||||
//~^ ERROR malformed lint attribute
|
||||
//~| NOTE bad attribute argument
|
||||
//~^ ERROR malformed
|
||||
//~| NOTE the only valid argument here is `reason`
|
||||
//~| NOTE for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
#![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
|
||||
//~^ ERROR malformed lint attribute
|
||||
//~| NOTE bad attribute argument
|
||||
//~^ ERROR malformed
|
||||
//~| NOTE didn't expect any arguments here
|
||||
//~| NOTE for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
#![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
|
||||
//~^ ERROR malformed lint attribute
|
||||
//~| NOTE reason in lint attribute must come last
|
||||
//~^ ERROR malformed
|
||||
//~| NOTE expected reason = "..." to be the last argument
|
||||
//~| NOTE for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
#![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
|
||||
//~^ ERROR malformed lint attribute
|
||||
//~| NOTE reason in lint attribute must come last
|
||||
//~^ ERROR malformed
|
||||
//~| NOTE expected reason = "..." to be the last argument
|
||||
//~| NOTE for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
#![warn(missing_copy_implementations, reason)]
|
||||
//~^ WARN unknown lint
|
||||
//~| NOTE `#[warn(unknown_lints)]` on by default
|
||||
|
||||
@@ -1,47 +1,141 @@
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/reasons-erroneous.rs:3:58
|
||||
error[E0539]: malformed `warn` attribute input
|
||||
--> $DIR/reasons-erroneous.rs:3:1
|
||||
|
|
||||
LL | #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
|
||||
| ^ reason must be a string literal
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^
|
||||
| |
|
||||
| expected a string literal here
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
|
||||
LL + #![warn(lint1)]
|
||||
|
|
||||
LL - #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
|
||||
LL + #![warn(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #![warn(absolute_paths_not_starting_with_crate, reason = 0)]
|
||||
LL + #![warn(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/reasons-erroneous.rs:6:40
|
||||
error[E0539]: malformed `warn` attribute input
|
||||
--> $DIR/reasons-erroneous.rs:7:1
|
||||
|
|
||||
LL | #![warn(anonymous_parameters, reason = b"consider these, for we have condemned them")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ reason must be a string literal
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| help: consider removing the prefix
|
||||
|
|
||||
= note: expected a normal string literal, not a byte string literal
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/reasons-erroneous.rs:9:29
|
||||
error[E0539]: malformed `warn` attribute input
|
||||
--> $DIR/reasons-erroneous.rs:10:1
|
||||
|
|
||||
LL | #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^---------------------------------------------------------------^^
|
||||
| |
|
||||
| the only valid argument here is `reason`
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
|
||||
LL + #![warn(lint1)]
|
||||
|
|
||||
LL - #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
|
||||
LL + #![warn(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #![warn(bare_trait_objects, reasons = "leaders to no sure land, guides their bearings lost")]
|
||||
LL + #![warn(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/reasons-erroneous.rs:12:22
|
||||
error[E0539]: malformed `warn` attribute input
|
||||
--> $DIR/reasons-erroneous.rs:14:1
|
||||
|
|
||||
LL | #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
| ^^^^^^^^^^^^^^^^^^^^^---------------------------------------------------------------^^
|
||||
| |
|
||||
| the only valid argument here is `reason`
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")]
|
||||
LL + #![warn(lint1)]
|
||||
|
|
||||
LL - #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")]
|
||||
LL + #![warn(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #![warn(unsafe_code, blerp = "or in league with robbers have reversed the signposts")]
|
||||
LL + #![warn(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/reasons-erroneous.rs:15:36
|
||||
error[E0565]: malformed `warn` attribute input
|
||||
--> $DIR/reasons-erroneous.rs:18:1
|
||||
|
|
||||
LL | #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ bad attribute argument
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--------------------------------------------------------^^
|
||||
| |
|
||||
| didn't expect any arguments here
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
|
||||
LL + #![warn(lint1)]
|
||||
|
|
||||
LL - #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
|
||||
LL + #![warn(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #![warn(elided_lifetimes_in_paths, reason("disrespectful to ancestors", "irresponsible to heirs"))]
|
||||
LL + #![warn(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/reasons-erroneous.rs:18:44
|
||||
error[E0539]: malformed `warn` attribute input
|
||||
--> $DIR/reasons-erroneous.rs:22:1
|
||||
|
|
||||
LL | #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected reason = "..." to be the last argument
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
|
||||
LL + #![warn(lint1)]
|
||||
|
|
||||
LL - #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
|
||||
LL + #![warn(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #![warn(ellipsis_inclusive_range_patterns, reason = "born barren", reason = "a freak growth")]
|
||||
LL + #![warn(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
|
||||
error[E0452]: malformed lint attribute input
|
||||
--> $DIR/reasons-erroneous.rs:21:25
|
||||
error[E0539]: malformed `warn` attribute input
|
||||
--> $DIR/reasons-erroneous.rs:26:1
|
||||
|
|
||||
LL | #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^ reason in lint attribute must come last
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^-------------------------^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
| |
|
||||
| expected reason = "..." to be the last argument
|
||||
|
|
||||
= note: for more information, visit <https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes>
|
||||
help: try changing it to one of the following valid forms of the attribute
|
||||
|
|
||||
LL - #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
|
||||
LL + #![warn(lint1)]
|
||||
|
|
||||
LL - #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
|
||||
LL + #![warn(lint1, lint2, ...)]
|
||||
|
|
||||
LL - #![warn(keyword_idents, reason = "root in rubble", macro_use_extern_crate)]
|
||||
LL + #![warn(lint1, lint2, lint3, reason = "...")]
|
||||
|
|
||||
|
||||
warning: unknown lint: `reason`
|
||||
--> $DIR/reasons-erroneous.rs:24:39
|
||||
--> $DIR/reasons-erroneous.rs:30:39
|
||||
|
|
||||
LL | #![warn(missing_copy_implementations, reason)]
|
||||
| ^^^^^^
|
||||
@@ -50,4 +144,5 @@ LL | #![warn(missing_copy_implementations, reason)]
|
||||
|
||||
error: aborting due to 7 previous errors; 1 warning emitted
|
||||
|
||||
For more information about this error, try `rustc --explain E0452`.
|
||||
Some errors have detailed explanations: E0539, E0565.
|
||||
For more information about an error, try `rustc --explain E0539`.
|
||||
|
||||
@@ -5,5 +5,3 @@
|
||||
#![warn(abc::my_lint)]
|
||||
//~^ ERROR unknown tool name `abc` found in scoped lint
|
||||
//~| HELP add `#![register_tool(abc)]`
|
||||
//~| ERROR unknown tool name `abc`
|
||||
//~| HELP add `#![register_tool(abc)]`
|
||||
|
||||
@@ -6,15 +6,6 @@ LL | #![warn(abc::my_lint)]
|
||||
|
|
||||
= help: add `#![register_tool(abc)]` to the crate root
|
||||
|
||||
error[E0710]: unknown tool name `abc` found in scoped lint: `abc::my_lint`
|
||||
--> $DIR/register-tool-lint.rs:5:9
|
||||
|
|
||||
LL | #![warn(abc::my_lint)]
|
||||
| ^^^
|
||||
|
|
||||
= help: add `#![register_tool(abc)]` to the crate root
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0710`.
|
||||
|
||||
@@ -1,11 +1,3 @@
|
||||
warning: lint `single_use_lifetime` has been renamed to `single_use_lifetimes`
|
||||
--> $DIR/renamed-lints-still-apply.rs:2:9
|
||||
|
|
||||
LL | #![deny(single_use_lifetime)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `single_use_lifetimes`
|
||||
|
|
||||
= note: `#[warn(renamed_and_removed_lints)]` on by default
|
||||
|
||||
error: lifetime parameter `'a` only used once
|
||||
--> $DIR/renamed-lints-still-apply.rs:6:9
|
||||
|
|
||||
@@ -25,5 +17,13 @@ LL - fn _foo<'a>(_x: &'a u32) {}
|
||||
LL + fn _foo(_x: &u32) {}
|
||||
|
|
||||
|
||||
warning: lint `single_use_lifetime` has been renamed to `single_use_lifetimes`
|
||||
--> $DIR/renamed-lints-still-apply.rs:2:9
|
||||
|
|
||||
LL | #![deny(single_use_lifetime)]
|
||||
| ^^^^^^^^^^^^^^^^^^^ help: use the new name: `single_use_lifetimes`
|
||||
|
|
||||
= note: `#[warn(renamed_and_removed_lints)]` on by default
|
||||
|
||||
error: aborting due to 1 previous error; 1 warning emitted
|
||||
|
||||
|
||||
@@ -23,7 +23,9 @@ pub fn check_expect_on_item() {
|
||||
|
||||
pub fn check_expect_on_macro() {
|
||||
// This should be fulfilled by the macro
|
||||
#[expect(unused_variables)] //~ WARN unused attribute
|
||||
#[expect(unused_variables)]
|
||||
//~^ WARN cannot be used on
|
||||
//~| WARN this was previously accepted
|
||||
trigger_unused_variables_macro!();
|
||||
|
||||
// FIXME: Lint attributes currently don't work directly on macros, and
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
warning: unused attribute `expect`
|
||||
warning: `#[expect]` attribute cannot be used on macro calls
|
||||
--> $DIR/expect_lint_from_macro.rs:26:5
|
||||
|
|
||||
LL | #[expect(unused_variables)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the built-in attribute `expect` will be ignored, since it's applied to the macro invocation `trigger_unused_variables_macro`
|
||||
--> $DIR/expect_lint_from_macro.rs:27:5
|
||||
|
|
||||
LL | trigger_unused_variables_macro!();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= help: `#[expect]` can be applied to associated consts, associated types, const parameters, const parameters, constants, crates, data types, enum variants, extern crates, foreign modules, foreign statics, function params, functions, global asms, impl blocks, lifetime parameters, lifetime parameters, macro defs, match arms, modules, pattern fields, statics, struct fields, struct fields, trait aliases, traits, type aliases, type parameters, type parameters, and use statements
|
||||
= note: requested on the command line with `-W unused-attributes`
|
||||
|
||||
warning: unused variable: `x`
|
||||
|
||||
@@ -37,8 +37,6 @@ pub fn rustc_lints() {
|
||||
|
||||
#[expect(invalid_nan_comparisons)]
|
||||
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
|
||||
//~| WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
|
||||
//~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
let _b = x == 5;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,13 +12,5 @@ warning: this lint expectation is unfulfilled
|
||||
LL | #[expect(invalid_nan_comparisons)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
warning: this lint expectation is unfulfilled
|
||||
--> $DIR/expect_tool_lint_rfc_2383.rs:38:18
|
||||
|
|
||||
LL | #[expect(invalid_nan_comparisons)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: 3 warnings emitted
|
||||
warning: 2 warnings emitted
|
||||
|
||||
|
||||
@@ -16,22 +16,15 @@
|
||||
pub fn normal_test_fn() {
|
||||
#[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")]
|
||||
//~^ WARNING this lint expectation is unfulfilled
|
||||
//~| WARNING this lint expectation is unfulfilled
|
||||
//~| NOTE this expectation will create a diagnostic with the default lint level
|
||||
//~| NOTE this expectation will create a diagnostic with the default lint level
|
||||
//~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
let mut v = vec![1, 1, 2, 3, 5];
|
||||
v.sort();
|
||||
|
||||
// Check that lint lists including `unfulfilled_lint_expectations` are also handled correctly
|
||||
#[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")]
|
||||
//~^ WARNING this lint expectation is unfulfilled
|
||||
//~| WARNING this lint expectation is unfulfilled
|
||||
//~| NOTE the expectation for `unused` should be fulfilled
|
||||
//~| NOTE the expectation for `unused` should be fulfilled
|
||||
//~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
|
||||
//~| NOTE the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
|
||||
//~| NOTE duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
let value = "I'm unused";
|
||||
}
|
||||
|
||||
|
||||
@@ -26,16 +26,7 @@ LL | #[expect(unused_mut, reason = "this expectation will create a diagnosti
|
||||
= note: this expectation will create a diagnostic with the default lint level
|
||||
|
||||
warning: this lint expectation is unfulfilled
|
||||
--> $DIR/expect_unfulfilled_expectation.rs:17:14
|
||||
|
|
||||
LL | #[expect(unused_mut, reason = "this expectation will create a diagnostic with the default lint level")]
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= note: this expectation will create a diagnostic with the default lint level
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: this lint expectation is unfulfilled
|
||||
--> $DIR/expect_unfulfilled_expectation.rs:27:22
|
||||
--> $DIR/expect_unfulfilled_expectation.rs:24:22
|
||||
|
|
||||
LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
@@ -43,15 +34,5 @@ LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectati
|
||||
= note: the expectation for `unused` should be fulfilled
|
||||
= note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
|
||||
|
||||
warning: this lint expectation is unfulfilled
|
||||
--> $DIR/expect_unfulfilled_expectation.rs:27:22
|
||||
|
|
||||
LL | #[expect(unused, unfulfilled_lint_expectations, reason = "the expectation for `unused` should be fulfilled")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= note: the expectation for `unused` should be fulfilled
|
||||
= note: the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: 6 warnings emitted
|
||||
warning: 4 warnings emitted
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ error: unused attribute
|
||||
LL | #[allow(reason = "I want to allow something")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `allow` without any lints has no effect
|
||||
= note: using `allow` with an empty list has no effect
|
||||
note: the lint level is defined here
|
||||
--> $DIR/lint-attribute-only-with-reason.rs:1:9
|
||||
|
|
||||
@@ -17,7 +17,7 @@ error: unused attribute
|
||||
LL | #[expect(reason = "I don't know what I'm waiting for")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `expect` without any lints has no effect
|
||||
= note: using `expect` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/lint-attribute-only-with-reason.rs:5:1
|
||||
@@ -25,7 +25,7 @@ error: unused attribute
|
||||
LL | #[warn(reason = "This should be warn by default")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `warn` without any lints has no effect
|
||||
= note: using `warn` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/lint-attribute-only-with-reason.rs:6:1
|
||||
@@ -33,7 +33,7 @@ error: unused attribute
|
||||
LL | #[deny(reason = "All listed lints are denied")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `deny` without any lints has no effect
|
||||
= note: using `deny` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/lint-attribute-only-with-reason.rs:7:1
|
||||
@@ -41,7 +41,7 @@ error: unused attribute
|
||||
LL | #[forbid(reason = "Just some reason")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `forbid` without any lints has no effect
|
||||
= note: using `forbid` with an empty list has no effect
|
||||
|
||||
error: aborting due to 5 previous errors
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
#![warn(unused)]
|
||||
|
||||
#[warn(unused_variables)]
|
||||
#[expect(unused_variables)]
|
||||
//~^ WARNING this lint expectation is unfulfilled [unfulfilled_lint_expectations]
|
||||
//~| NOTE `#[warn(unfulfilled_lint_expectations)]` on by default
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
warning: this lint expectation is unfulfilled
|
||||
--> $DIR/multiple_expect_attrs.rs:6:10
|
||||
--> $DIR/multiple_expect_attrs.rs:5:10
|
||||
|
|
||||
LL | #[expect(unused_variables)]
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
||||
+2
-1
@@ -48,5 +48,6 @@ fn inner() {
|
||||
// This `#[allow]` does not work, since the attribute gets dropped
|
||||
// when we expand the macro
|
||||
let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work);
|
||||
//~^ WARN unused attribute
|
||||
//~^ WARN attribute cannot be used on
|
||||
//~| WARN this was previously accepted
|
||||
}
|
||||
|
||||
+3
-6
@@ -31,17 +31,14 @@ LL | let _ = foo!(warn_in_expr);
|
||||
= note: for more information, see issue #79813 <https://github.com/rust-lang/rust/issues/79813>
|
||||
= note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
|
||||
|
||||
warning: unused attribute `allow`
|
||||
warning: `#[allow]` attribute cannot be used on macro calls
|
||||
--> $DIR/semicolon-in-expressions-from-macros.rs:50:13
|
||||
|
|
||||
LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: the built-in attribute `allow` will be ignored, since it's applied to the macro invocation `foo`
|
||||
--> $DIR/semicolon-in-expressions-from-macros.rs:50:60
|
||||
|
|
||||
LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_not_work);
|
||||
| ^^^
|
||||
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
|
||||
= help: `#[allow]` can be applied to associated consts, associated types, const parameters, const parameters, constants, crates, data types, enum variants, expressions, extern crates, foreign modules, foreign statics, function params, functions, global asms, impl blocks, lifetime parameters, lifetime parameters, macro defs, match arms, modules, pattern fields, statements, statics, struct fields, struct fields, trait aliases, traits, type aliases, type parameters, type parameters, and use statements
|
||||
= note: requested on the command line with `-W unused-attributes`
|
||||
|
||||
warning: trailing semicolon in macro used in expression position
|
||||
|
||||
@@ -1,48 +1,3 @@
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:2:1
|
||||
|
|
||||
LL | #![allow()]
|
||||
| ^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `allow` with an empty list has no effect
|
||||
note: the lint level is defined here
|
||||
--> $DIR/empty-attributes.rs:1:9
|
||||
|
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:3:1
|
||||
|
|
||||
LL | #![expect()]
|
||||
| ^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `expect` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:4:1
|
||||
|
|
||||
LL | #![warn()]
|
||||
| ^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `warn` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:5:1
|
||||
|
|
||||
LL | #![deny()]
|
||||
| ^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `deny` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:6:1
|
||||
|
|
||||
LL | #![forbid()]
|
||||
| ^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `forbid` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:9:1
|
||||
|
|
||||
@@ -50,6 +5,11 @@ LL | #[repr()]
|
||||
| ^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: using `repr` with an empty list has no effect
|
||||
note: the lint level is defined here
|
||||
--> $DIR/empty-attributes.rs:1:9
|
||||
|
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:12:1
|
||||
@@ -59,6 +19,46 @@ LL | #[target_feature()]
|
||||
|
|
||||
= note: using `target_feature` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:2:1
|
||||
|
|
||||
LL | #![allow()]
|
||||
| ^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: using `allow` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:3:1
|
||||
|
|
||||
LL | #![expect()]
|
||||
| ^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: using `expect` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:4:1
|
||||
|
|
||||
LL | #![warn()]
|
||||
| ^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: using `warn` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:5:1
|
||||
|
|
||||
LL | #![deny()]
|
||||
| ^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: using `deny` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:6:1
|
||||
|
|
||||
LL | #![forbid()]
|
||||
| ^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: using `forbid` with an empty list has no effect
|
||||
|
||||
error: unused attribute
|
||||
--> $DIR/empty-attributes.rs:7:1
|
||||
|
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
#![rustc_dummy=5z] //~ ERROR invalid suffix `z` for number literal
|
||||
#![rustc_dummy=5z]
|
||||
//~^ ERROR invalid suffix `z` for number literal
|
||||
|
||||
fn main() {}
|
||||
|
||||
@@ -4,7 +4,7 @@ warning: unused attribute
|
||||
LL | #[cfg_attr(true, allow())]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
||||
|
|
||||
= note: attribute `allow` with an empty list has no effect
|
||||
= note: using `allow` with an empty list has no effect
|
||||
= note: requested on the command line with `-W unused-attributes`
|
||||
|
||||
warning: 1 warning emitted
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
#[warn(foo::bar)]
|
||||
//~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
fn main() {}
|
||||
|
||||
@@ -6,24 +6,6 @@ LL | #[warn(foo::bar)]
|
||||
|
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
|
||||
error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
--> $DIR/tool_lints.rs:1:8
|
||||
|
|
||||
LL | #[warn(foo::bar)]
|
||||
| ^^^
|
||||
|
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
--> $DIR/tool_lints.rs:1:8
|
||||
|
|
||||
LL | #[warn(foo::bar)]
|
||||
| ^^^
|
||||
|
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0710`.
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
#![deny(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
#![deny(foo::bar)]
|
||||
//~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
|
||||
#[allow(foo::bar)] //~ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
//~| ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
#[allow(foo::bar)]
|
||||
//~^ ERROR unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
fn main() {}
|
||||
|
||||
@@ -7,49 +7,13 @@ LL | #![deny(foo::bar)]
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
|
||||
error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
--> $DIR/unknown-lint-tool-name.rs:5:9
|
||||
--> $DIR/unknown-lint-tool-name.rs:4:9
|
||||
|
|
||||
LL | #[allow(foo::bar)]
|
||||
| ^^^
|
||||
|
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
|
||||
error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
--> $DIR/unknown-lint-tool-name.rs:1:9
|
||||
|
|
||||
LL | #![deny(foo::bar)]
|
||||
| ^^^
|
||||
|
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
--> $DIR/unknown-lint-tool-name.rs:5:9
|
||||
|
|
||||
LL | #[allow(foo::bar)]
|
||||
| ^^^
|
||||
|
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
--> $DIR/unknown-lint-tool-name.rs:1:9
|
||||
|
|
||||
LL | #![deny(foo::bar)]
|
||||
| ^^^
|
||||
|
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error[E0710]: unknown tool name `foo` found in scoped lint: `foo::bar`
|
||||
--> $DIR/unknown-lint-tool-name.rs:5:9
|
||||
|
|
||||
LL | #[allow(foo::bar)]
|
||||
| ^^^
|
||||
|
|
||||
= help: add `#![register_tool(foo)]` to the crate root
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
error: aborting due to 6 previous errors
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
For more information about this error, try `rustc --explain E0710`.
|
||||
|
||||
@@ -1,3 +1,14 @@
|
||||
#![attr = Feature([auto_traits#0, box_patterns#0, builtin_syntax#0,
|
||||
const_trait_impl#0, coroutines#0, decl_macro#0, deref_patterns#0,
|
||||
explicit_tail_calls#0, gen_blocks#0, more_qualified_paths#0, never_patterns#0,
|
||||
never_type#0, pattern_types#0, pattern_type_macro#0, prelude_import#0,
|
||||
specialization#0, trace_macros#0, trait_alias#0, try_blocks#0,
|
||||
try_blocks_heterogeneous#0, yeet_expr#0])]
|
||||
#![attr = LintAttributes([LintAttribute {kind: Allow, attr_style: Inner,
|
||||
lint_instances: [incomplete_features]}])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use std::prelude::rust_2024::*;
|
||||
//@ revisions: expanded hir
|
||||
//@[expanded]compile-flags: -Zunpretty=expanded
|
||||
//@[expanded]check-pass
|
||||
@@ -8,16 +19,6 @@
|
||||
// Note: the HIR revision includes a `.stderr` file because there are some
|
||||
// errors that only occur once we get past the AST.
|
||||
|
||||
#![allow(incomplete_features)]
|
||||
#![attr = Feature([auto_traits#0, box_patterns#0, builtin_syntax#0,
|
||||
const_trait_impl#0, coroutines#0, decl_macro#0, deref_patterns#0,
|
||||
explicit_tail_calls#0, gen_blocks#0, more_qualified_paths#0, never_patterns#0,
|
||||
never_type#0, pattern_types#0, pattern_type_macro#0, prelude_import#0,
|
||||
specialization#0, trace_macros#0, trait_alias#0, try_blocks#0,
|
||||
try_blocks_heterogeneous#0, yeet_expr#0])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use std::prelude::rust_2024::*;
|
||||
|
||||
mod prelude {
|
||||
use std::prelude::rust_2024::*;
|
||||
@@ -39,7 +40,8 @@ use self::prelude::*;
|
||||
* inner multi-line doc comment
|
||||
*/
|
||||
#[doc = "inner doc attribute"]
|
||||
#[allow(dead_code, unused_variables)]
|
||||
#[attr = LintAttributes([LintAttribute {kind: Allow, attr_style: Inner,
|
||||
lint_instances: [dead_code, unused_variables]}])]
|
||||
#[attr = NoStd]
|
||||
mod attributes {
|
||||
|
||||
@@ -49,7 +51,9 @@ mod attributes {
|
||||
*/
|
||||
#[doc = "outer doc attribute"]
|
||||
#[doc = "macro"]
|
||||
#[allow()]
|
||||
#[attr = LintAttributes([LintAttribute {kind: Allow,
|
||||
attr_style: Outer,
|
||||
lint_instances: []}])]
|
||||
#[attr = Repr {reprs: [ReprC]}]
|
||||
struct Struct;
|
||||
}
|
||||
@@ -212,9 +216,13 @@ mod expressions {
|
||||
{ }
|
||||
unsafe { }
|
||||
'a: { }
|
||||
#[allow()]
|
||||
#[attr = LintAttributes([LintAttribute {kind: Allow,
|
||||
attr_style: Outer,
|
||||
lint_instances: []}])]
|
||||
{ }
|
||||
#[allow()]
|
||||
#[attr = LintAttributes([LintAttribute {kind: Allow,
|
||||
attr_style: Inner,
|
||||
lint_instances: []}])]
|
||||
{ }
|
||||
}
|
||||
|
||||
@@ -244,9 +252,15 @@ mod expressions {
|
||||
type_ascribe!({ from_output(()) }, Option<_>);
|
||||
type_ascribe!({
|
||||
from_output(match branch(None) {
|
||||
Break { 0: residual } => #[allow(unreachable_code)]
|
||||
Break { 0: residual } =>
|
||||
#[attr = LintAttributes([LintAttribute {kind: Allow,
|
||||
attr_style: Outer,
|
||||
lint_instances: [unreachable_code]}])]
|
||||
break from_residual(residual),
|
||||
Continue { 0: val } => #[allow(unreachable_code)]
|
||||
Continue { 0: val } =>
|
||||
#[attr = LintAttributes([LintAttribute {kind: Allow,
|
||||
attr_style: Outer,
|
||||
lint_instances: [unreachable_code]}])]
|
||||
val,
|
||||
})
|
||||
}, Option<String>)
|
||||
@@ -368,9 +382,15 @@ mod expressions {
|
||||
fn expr_try() {
|
||||
let expr;
|
||||
match branch(expr) {
|
||||
Break { 0: residual } => #[allow(unreachable_code)]
|
||||
Break { 0: residual } =>
|
||||
#[attr = LintAttributes([LintAttribute {kind: Allow,
|
||||
attr_style: Outer,
|
||||
lint_instances: [unreachable_code]}])]
|
||||
return from_residual(residual),
|
||||
Continue { 0: val } => #[allow(unreachable_code)]
|
||||
Continue { 0: val } =>
|
||||
#[attr = LintAttributes([LintAttribute {kind: Allow,
|
||||
attr_style: Outer,
|
||||
lint_instances: [unreachable_code]}])]
|
||||
val,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
//@ compile-flags: -Zunpretty=hir
|
||||
//@ check-pass
|
||||
|
||||
#![expect(incomplete_features)]
|
||||
#![allow(dead_code)]
|
||||
#![attr = Feature([min_generic_const_args#0, adt_const_params#0])]
|
||||
#![attr = LintAttributes([LintAttribute {kind: Expect, attr_style: Inner,
|
||||
lint_instances: [incomplete_features]}, LintAttribute {kind: Allow,
|
||||
attr_style: Inner, lint_instances: [dead_code]}])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
//@ compile-flags: -Zunpretty=hir
|
||||
//@ check-pass
|
||||
|
||||
|
||||
use std::marker::ConstParamTy;
|
||||
|
||||
|
||||
@@ -1,3 +1,8 @@
|
||||
#![attr = LintAttributes([LintAttribute {kind: Allow, attr_style: Inner,
|
||||
lint_instances: [dead_code]}])]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
// Regression test for the ICE described in #82328. The pretty-printer for
|
||||
// `-Zunpretty=hir,typed` would previously retrieve type-checking results
|
||||
// when entering a body, which means that type information was not available
|
||||
@@ -7,10 +12,6 @@
|
||||
//@ check-pass
|
||||
//@ compile-flags: -Zunpretty=hir,typed
|
||||
//@ edition: 2015
|
||||
#![allow(dead_code)]
|
||||
extern crate std;
|
||||
#[attr = PreludeImport]
|
||||
use ::std::prelude::rust_2015::*;
|
||||
|
||||
fn main() ({ } as ())
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ fn foo<'a, T>()
|
||||
#[should_panic] 'a: 'static, //~ ERROR attribute cannot be used on
|
||||
#[macro_use] T: Trait, //~ ERROR attribute cannot be used on
|
||||
#[macro_use] 'a: 'static, //~ ERROR attribute cannot be used on
|
||||
#[allow(unused)] T: Trait, //~ ERROR most attributes are not supported in `where` clauses
|
||||
#[allow(unused)] 'a: 'static, //~ ERROR most attributes are not supported in `where` clauses
|
||||
#[allow(unused)] T: Trait, //~ ERROR attribute cannot be used on
|
||||
#[allow(unused)] 'a: 'static, //~ ERROR attribute cannot be used on
|
||||
#[deprecated] T: Trait, //~ ERROR attribute cannot be used on
|
||||
#[deprecated] 'a: 'static, //~ ERROR attribute cannot be used on
|
||||
#[automatically_derived] T: Trait, //~ ERROR attribute cannot be used on
|
||||
|
||||
@@ -74,21 +74,21 @@ LL | #[macro_use] 'a: 'static,
|
||||
|
|
||||
= help: `#[macro_use]` can be applied to crates, extern crates, and modules
|
||||
|
||||
error: most attributes are not supported in `where` clauses
|
||||
error: `#[allow]` attribute cannot be used on where predicates
|
||||
--> $DIR/unsupported_attribute.rs:21:5
|
||||
|
|
||||
LL | #[allow(unused)] T: Trait,
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: only `#[cfg]` and `#[cfg_attr]` are supported
|
||||
= help: `#[allow]` can be applied to associated consts, associated types, const parameters, const parameters, constants, crates, data types, enum variants, extern crates, foreign modules, foreign statics, function params, functions, global asms, impl blocks, lifetime parameters, lifetime parameters, macro defs, match arms, modules, pattern fields, statics, struct fields, struct fields, trait aliases, traits, type aliases, type parameters, type parameters, and use statements
|
||||
|
||||
error: most attributes are not supported in `where` clauses
|
||||
error: `#[allow]` attribute cannot be used on where predicates
|
||||
--> $DIR/unsupported_attribute.rs:22:5
|
||||
|
|
||||
LL | #[allow(unused)] 'a: 'static,
|
||||
| ^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: only `#[cfg]` and `#[cfg_attr]` are supported
|
||||
= help: `#[allow]` can be applied to associated consts, associated types, const parameters, const parameters, constants, crates, data types, enum variants, extern crates, foreign modules, foreign statics, function params, functions, global asms, impl blocks, lifetime parameters, lifetime parameters, macro defs, match arms, modules, pattern fields, statics, struct fields, struct fields, trait aliases, traits, type aliases, type parameters, type parameters, and use statements
|
||||
|
||||
error: `#[deprecated]` attribute cannot be used on where predicates
|
||||
--> $DIR/unsupported_attribute.rs:23:5
|
||||
|
||||
Reference in New Issue
Block a user