Skip to content

Commit 6d9cad0

Browse files
committed
stash
1 parent 6efa357 commit 6d9cad0

20 files changed

Lines changed: 379 additions & 63 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3545,6 +3545,7 @@ dependencies = [
35453545
"rustc_hir",
35463546
"rustc_lexer",
35473547
"rustc_macros",
3548+
"rustc_middle",
35483549
"rustc_parse",
35493550
"rustc_session",
35503551
"rustc_span",

compiler/rustc_ast/src/tokenstream.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ impl<S: SpanEncoder> Encodable<S> for LazyAttrTokenStream {
132132
}
133133
}
134134

135-
impl<D: SpanDecoder> Decodable<D> for LazyAttrTokenStream {
135+
impl< D: SpanDecoder> Decodable< D> for LazyAttrTokenStream {
136136
fn decode(_d: &mut D) -> Self {
137137
panic!("Attempted to decode LazyAttrTokenStream");
138138
}

compiler/rustc_ast_lowering/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@ struct LoweringContext<'a, 'hir> {
151151

152152
impl<'a, 'hir> LoweringContext<'a, 'hir> {
153153
fn new(tcx: TyCtxt<'hir>, resolver: &'a mut ResolverAstLowering) -> Self {
154-
let registered_tools = tcx.registered_tools(()).iter().map(|x| x.name).collect();
154+
let registered_tools = tcx.registered_tools(());
155155
Self {
156156
// Pseudo-globals.
157157
tcx,
@@ -205,7 +205,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
205205
attribute_parser: AttributeParser::new(
206206
tcx.sess,
207207
tcx.features(),
208-
registered_tools,
208+
registered_tools.clone(),
209209
Late,
210210
),
211211
delayed_lints: Vec::new(),

compiler/rustc_attr_parsing/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ rustc_feature = { path = "../rustc_feature" }
1414
rustc_hir = { path = "../rustc_hir" }
1515
rustc_lexer = { path = "../rustc_lexer" }
1616
rustc_macros = { path = "../rustc_macros" }
17+
rustc_middle = {path = "../rustc_middle"}
1718
rustc_parse = { path = "../rustc_parse" }
1819
rustc_session = { path = "../rustc_session" }
1920
rustc_span = { path = "../rustc_span" }

compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -294,10 +294,11 @@ impl<S: Stage> AttributeParser<S> for NakedParser {
294294

295295
let span = self.span?;
296296

297+
let tools = cx.tools.iter().map(|tool|tool.name).collect::<Vec<_>>();
297298
// only if we found a naked attribute do we do the somewhat expensive check
298299
'outer: for other_attr in cx.all_attrs {
299300
for allowed_attr in ALLOW_LIST {
300-
if other_attr.segments().next().is_some_and(|i| cx.tools.contains(&i.name)) {
301+
if other_attr.segments().next().is_some_and(|i| tools.contains(&i.name)) {
301302
// effectively skips the error message being emitted below
302303
// if it's a tool attribute
303304
continue 'outer;
Lines changed: 211 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,211 @@
1+
use std::sync::Arc;
2+
3+
use super::prelude::*;
4+
use rustc_middle::{bug, ty::RegisteredTools};
5+
use rustc_session::{DynLintStore, lint::CheckLintNameResult};
6+
7+
pub(crate) struct AllowParser;
8+
9+
impl<S: Stage> SingleAttributeParser<S> for AllowParser {
10+
const PATH: &[Symbol] = &[sym::allow];
11+
12+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepAll;
13+
14+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
15+
16+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
17+
18+
const TEMPLATE: AttributeTemplate = template!(
19+
List: &["lint1", "lint1, lint2, ...", r#"lint1, lint2, lint3, reason = "...""#],
20+
"https://doc.rust-lang.org/reference/attributes/diagnostics.html#lint-check-attributes"
21+
);
22+
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
23+
let Some(lint_store) = &cx.sess.lint_store else {
24+
bug!("lint_store required while parsing attributes");
25+
};
26+
27+
28+
let Some(list) = args.list().map(MetaItemListParser::mixed) else {
29+
cx.expected_list(cx.inner_span, args);
30+
return None;
31+
};
32+
33+
let mut errored = false;
34+
let mut lint_ids = ThinVec::new();
35+
let mut list = list.peekable();
36+
let mut reason = None;
37+
38+
39+
while let Some(item) = list.next() {
40+
let Some(meta_item ) = item.meta_item() else {
41+
return None;
42+
};
43+
if let Some(args) = meta_item.word_is(sym::reason) {
44+
let ArgParser::NameValue(nv) = args else {
45+
// TODO: proper error
46+
errored = true;
47+
continue;
48+
};
49+
if list.peek().is_some() {
50+
// TODO: proper error
51+
errored = true;
52+
continue;
53+
}
54+
let Some(s) = nv.value_as_str() else {
55+
// TODO: proper error
56+
errored = true;
57+
continue;
58+
};
59+
reason = Some(s);
60+
} else {
61+
62+
let mut segments = meta_item.path().segments();
63+
64+
let Some(tool_or_name) = segments.next() else {
65+
bug!("first segment should always exist");
66+
};
67+
68+
let rest = segments.collect::<Vec<_>>();
69+
let (tool, name): (Option<Symbol>, _) = if rest.is_empty() {
70+
let name = tool_or_name.name;
71+
(None, name.to_string())
72+
} else {
73+
let tool = tool_or_name;
74+
let name = rest.into_iter().map(|ident|ident.to_string()).collect::<Vec<_>>().join("::");
75+
(Some(tool.name), name)
76+
};
77+
78+
79+
if let Some(ids) = check_lint(&name, tool, &cx.tools, lint_store, meta_item.span()) {
80+
lint_ids.extend(ids);
81+
}
82+
83+
84+
}
85+
86+
87+
88+
}
89+
90+
91+
if errored {
92+
None
93+
} else {
94+
95+
96+
97+
Some(AttributeKind::Allow {lint_ids, reason})}
98+
}
99+
}
100+
101+
102+
fn check_lint(name: &str, tool: Option<Symbol>, tools: &RegisteredTools, lint_store: &Arc<dyn DynLintStore>, meta_item_span: Span) -> Option<Vec<(Symbol, Span)>> {
103+
let mut lint_ids = Vec::new();
104+
match lint_store.check_lint_name(name, tool, tools) {
105+
CheckLintNameResult::Ok(ids) => {
106+
for id in ids {
107+
lint_ids.push((Symbol::intern(&id.to_string()), meta_item_span));
108+
}
109+
}
110+
111+
CheckLintNameResult::Tool(ids, new_lint_name) => {
112+
let name = match new_lint_name {
113+
None => {
114+
let complete_name =
115+
&format!("{}::{}", tool.unwrap(), name);
116+
Symbol::intern(complete_name)
117+
}
118+
Some(new_lint_name) => {
119+
/*self.emit_span_lint(
120+
builtin::RENAMED_AND_REMOVED_LINTS,
121+
sp.into(),
122+
DeprecatedLintName {
123+
name,
124+
suggestion: sp,
125+
replace: &new_lint_name,
126+
},
127+
);*/
128+
Symbol::intern(&new_lint_name)
129+
}
130+
};
131+
for id in ids {
132+
lint_ids.push((name, meta_item_span));
133+
}
134+
135+
}
136+
137+
CheckLintNameResult::MissingTool => {
138+
// If `MissingTool` is returned, then either the lint does not
139+
// exist in the tool or the code was not compiled with the tool and
140+
// therefore the lint was never added to the `LintStore`. To detect
141+
// this is the responsibility of the lint tool.
142+
return None;
143+
}
144+
145+
CheckLintNameResult::NoTool => {
146+
/*self.dcx().emit_err(UnknownToolInScopedLint {
147+
span: tool_ident.map(|ident| ident.span),
148+
tool_name: tool_name.unwrap(),
149+
lint_name: pprust::path_to_string(&meta_item.path),
150+
is_nightly_build: sess.is_nightly_build(),
151+
});*/
152+
return None;
153+
}
154+
155+
CheckLintNameResult::Renamed(ref replace) => {
156+
/*if self.lint_added_lints {
157+
let suggestion =
158+
RenamedLintSuggestion::WithSpan { suggestion: sp, replace };
159+
let name =
160+
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
161+
let lint = RenamedLint { name: name.as_str(), replace, suggestion };
162+
self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
163+
}*/
164+
165+
// If this lint was renamed, apply the new lint instead of ignoring the
166+
// attribute. Ignore any errors or warnings that happen because the new
167+
// name is inaccurate.
168+
// NOTE: `new_name` already includes the tool name, so we don't
169+
// have to add it again.
170+
let CheckLintNameResult::Ok(ids) =
171+
lint_store.check_lint_name(replace, None, tools)
172+
else {
173+
panic!("renamed lint does not exist: {replace}");
174+
};
175+
let name = Symbol::intern(replace);
176+
177+
for id in ids {
178+
lint_ids.push((name, meta_item_span));
179+
}
180+
}
181+
182+
CheckLintNameResult::Removed(ref reason) => {
183+
/*if self.lint_added_lints {
184+
let name =
185+
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
186+
let lint = RemovedLint { name: name.as_str(), reason };
187+
self.emit_span_lint(RENAMED_AND_REMOVED_LINTS, sp.into(), lint);
188+
}*/
189+
return None;
190+
}
191+
192+
CheckLintNameResult::NoLint(suggestion) => {
193+
/*if self.lint_added_lints {
194+
let name =
195+
tool_ident.map(|tool| format!("{tool}::{name}")).unwrap_or(name);
196+
let suggestion = suggestion.map(|(replace, from_rustc)| {
197+
UnknownLintSuggestion::WithSpan {
198+
suggestion: sp,
199+
replace,
200+
from_rustc,
201+
}
202+
});
203+
let lint = UnknownLint { name, suggestion };
204+
self.emit_span_lint(UNKNOWN_LINTS, sp.into(), lint);
205+
}
206+
*/
207+
return None;
208+
}
209+
}
210+
Some(lint_ids)
211+
}

compiler/rustc_attr_parsing/src/attributes/mod.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ pub(crate) mod dummy;
4545
pub(crate) mod inline;
4646
pub(crate) mod instruction_set;
4747
pub(crate) mod link_attrs;
48+
pub(crate) mod lint;
4849
pub(crate) mod lint_helpers;
4950
pub(crate) mod loop_match;
5051
pub(crate) mod macro_attrs;
@@ -175,6 +176,10 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
175176
if let Some((_, used)) = group.1 {
176177
T::ON_DUPLICATE.exec::<T>(cx, used, cx.attr_span);
177178
}
179+
},
180+
181+
AttributeOrder::KeepAll => {
182+
178183
}
179184
}
180185

@@ -257,6 +262,8 @@ pub(crate) enum AttributeOrder {
257262
/// #[path="bar.rs"] //~ WARNING duplicated attribute
258263
/// ```
259264
KeepOutermost,
265+
266+
KeepAll,
260267
}
261268

262269
/// An even simpler version of [`SingleAttributeParser`]:

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::attributes::dummy::*;
3232
use crate::attributes::inline::*;
3333
use crate::attributes::instruction_set::*;
3434
use crate::attributes::link_attrs::*;
35+
use crate::attributes::lint::*;
3536
use crate::attributes::lint_helpers::*;
3637
use crate::attributes::loop_match::*;
3738
use crate::attributes::macro_attrs::*;
@@ -168,6 +169,7 @@ attribute_parsers!(
168169
// tidy-alphabetical-end
169170

170171
// tidy-alphabetical-start
172+
Single<AllowParser>,
171173
Single<CfiEncodingParser>,
172174
Single<CollapseDebugInfoParser>,
173175
Single<CoverageParser>,

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use rustc_feature::{AttributeTemplate, Features};
88
use rustc_hir::attrs::AttributeKind;
99
use rustc_hir::lints::AttributeLintKind;
1010
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
11+
use rustc_middle::ty::RegisteredTools;
1112
use rustc_session::Session;
1213
use rustc_session::lint::{BuiltinLintDiag, LintId};
1314
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
@@ -21,7 +22,7 @@ use crate::{Early, Late, OmitDoc, ShouldEmit};
2122
/// Context created once, for example as part of the ast lowering
2223
/// context, through which all attributes can be lowered.
2324
pub struct AttributeParser<'sess, S: Stage = Late> {
24-
pub(crate) tools: Vec<Symbol>,
25+
pub(crate) tools: RegisteredTools,
2526
pub(crate) features: Option<&'sess Features>,
2627
pub(crate) sess: &'sess Session,
2728
pub(crate) stage: S,
@@ -109,7 +110,7 @@ impl<'sess> AttributeParser<'sess, Early> {
109110
emit_errors: ShouldEmit,
110111
) -> Vec<Attribute> {
111112
let mut p =
112-
Self { features, tools: Vec::new(), parse_only, sess, stage: Early { emit_errors } };
113+
Self { features, tools: RegisteredTools::default(), parse_only, sess, stage: Early { emit_errors } };
113114
p.parse_attribute_list(
114115
attrs,
115116
target_span,
@@ -193,7 +194,7 @@ impl<'sess> AttributeParser<'sess, Early> {
193194
) -> T {
194195
let mut parser = Self {
195196
features,
196-
tools: Vec::new(),
197+
tools: RegisteredTools::default(),
197198
parse_only: None,
198199
sess,
199200
stage: Early { emit_errors },
@@ -231,7 +232,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
231232
pub fn new(
232233
sess: &'sess Session,
233234
features: &'sess Features,
234-
tools: Vec<Symbol>,
235+
tools: RegisteredTools,
235236
stage: S,
236237
) -> Self {
237238
Self { features: Some(features), tools, parse_only: None, sess, stage }

compiler/rustc_hir/src/attrs/data_structures.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -797,6 +797,12 @@ pub enum AttributeKind {
797797
// FIXME(#82232, #143834): temporarily renamed to mitigate `#[align]` nameres ambiguity
798798
Align { align: Align, span: Span },
799799

800+
Allow {
801+
lint_ids: ThinVec<(Symbol, Span)>,
802+
reason: Option<Symbol>,
803+
804+
},
805+
800806
/// Represents `#[allow_internal_unsafe]`.
801807
AllowInternalUnsafe(Span),
802808

0 commit comments

Comments
 (0)