Skip to content

Commit 0e844e5

Browse files
committed
Meow
1 parent facf96a commit 0e844e5

File tree

6 files changed

+132
-60
lines changed

6 files changed

+132
-60
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Session.vim
3030
!/tests/run-make/thumb-none-qemu/example/.cargo
3131

3232
## Configuration
33+
config.toml
3334
/Makefile
3435
config.mk
3536
config.stamp

compiler/rustc_ast/src/attr/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,7 @@ impl AttrItem {
210210
self.args.span().map_or(self.path.span, |args_span| self.path.span.to(args_span))
211211
}
212212

213-
fn meta_item_list(&self) -> Option<ThinVec<NestedMetaItem>> {
213+
pub fn meta_item_list(&self) -> Option<ThinVec<NestedMetaItem>> {
214214
match &self.args {
215215
AttrArgs::Delimited(args) if args.delim == Delimiter::Parenthesis => {
216216
MetaItemKind::list_from_tokens(args.tokens.clone())

compiler/rustc_lint/src/levels.rs

Lines changed: 72 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ use crate::{
1515
};
1616
use rustc_ast as ast;
1717
use rustc_ast_pretty::pprust;
18-
use rustc_data_structures::{fx::FxIndexMap, sync::Lrc};
18+
use rustc_data_structures::{fx::FxIndexMap, sync::{Lrc, par_for_each_in, Lock}};
1919
use rustc_errors::{Diag, DiagMessage, LintDiagnostic, MultiSpan};
2020
use rustc_feature::{Features, GateIssue};
2121
use rustc_hir as hir;
@@ -160,11 +160,11 @@ pub fn lints_that_can_emit(tcx: TyCtxt<'_>, (): ()) -> Lrc<(Vec<Symbol>, Vec<Sym
160160
// builder.add_command_line();
161161
// builder.add_id(hir::CRATE_HIR_ID);
162162

163-
let mut visitor = LintLevelMinimumVisitor::new(tcx);
163+
let mut visitor = LintLevelMinimum::new(tcx);
164164
visitor.process_opts();
165-
tcx.hir().walk_attributes(&mut visitor);
165+
visitor.lint_level_minimums(tcx);
166166

167-
Lrc::new((visitor.lints_to_emit, visitor.lints_allowed))
167+
Lrc::new((visitor.lints_to_emit.into_inner(), visitor.lints_allowed.into_inner()))
168168
}
169169

170170
#[instrument(level = "trace", skip(tcx), ret)]
@@ -471,81 +471,97 @@ impl<'tcx> Visitor<'tcx> for LintLevelsBuilder<'_, QueryMapExpectationsWrapper<'
471471
///
472472
/// E.g., if a crate has a global #![allow(lint)] attribute, but a single item
473473
/// uses #[warn(lint)], this visitor will set that lint level as `Warn`
474-
struct LintLevelMinimumVisitor<'tcx> {
474+
struct LintLevelMinimum<'tcx> {
475475
tcx: TyCtxt<'tcx>,
476476
/// The actual list of detected lints.
477-
lints_to_emit: Vec<Symbol>,
478-
lints_allowed: Vec<Symbol>,
477+
lints_to_emit: Lock<Vec<Symbol>>,
478+
lints_allowed: Lock<Vec<Symbol>>,
479479
}
480480

481-
impl<'tcx> LintLevelMinimumVisitor<'tcx> {
481+
impl<'tcx> LintLevelMinimum<'tcx> {
482482
pub fn new(tcx: TyCtxt<'tcx>) -> Self {
483483
Self {
484484
tcx,
485485
// That magic number is the current number of lints + some more for possible future lints
486-
lints_to_emit: Vec::with_capacity(230),
487-
lints_allowed: Vec::with_capacity(100),
486+
lints_to_emit: Lock::new(Vec::with_capacity(230)),
487+
lints_allowed: Lock::new(Vec::with_capacity(100)),
488488
}
489489
}
490490

491491
fn process_opts(&mut self) {
492492
for (lint, level) in &self.tcx.sess.opts.lint_opts {
493493
if *level == Level::Allow {
494-
self.lints_allowed.push(Symbol::intern(&lint));
494+
self.lints_allowed.with_lock(|lints_allowed|{lints_allowed.push(Symbol::intern(&lint)) });
495495
} else {
496-
self.lints_to_emit.push(Symbol::intern(&lint));
496+
self.lints_to_emit.with_lock(|lints_to_emit| {lints_to_emit.push(Symbol::intern(&lint)) });
497497
}
498498
}
499499
}
500-
}
501-
502-
impl<'tcx> Visitor<'tcx> for LintLevelMinimumVisitor<'tcx> {
503-
type NestedFilter = nested_filter::All;
504-
505-
fn nested_visit_map(&mut self) -> Self::Map {
506-
self.tcx.hir()
507-
}
508500

509-
fn visit_attribute(&mut self, attribute: &'tcx ast::Attribute) {
510-
if let Some(meta) = attribute.meta() {
511-
if [sym::warn, sym::deny, sym::forbid, sym::expect]
512-
.iter()
513-
.any(|kind| meta.has_name(*kind))
514-
{
515-
// SAFETY: Lint attributes are always a metalist inside a
516-
// metalist (even with just one lint).
517-
for meta_list in meta.meta_item_list().unwrap() {
518-
// If it's a tool lint (e.g. clippy::my_clippy_lint)
519-
if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
520-
if meta_item.path.segments.len() == 1 {
521-
self.lints_to_emit.push(
522-
// SAFETY: Lint attributes can only have literals
523-
meta_list.ident().unwrap().name,
524-
);
525-
} else {
526-
self.lints_to_emit.push(meta_item.path.segments[1].ident.name);
527-
}
528-
}
529-
}
530-
// We handle #![allow]s differently, as these remove checking rather than adding.
531-
} else if meta.has_name(sym::allow)
532-
&& let ast::AttrStyle::Inner = attribute.style
533-
{
534-
for meta_list in meta.meta_item_list().unwrap() {
535-
// If it's a tool lint (e.g. clippy::my_clippy_lint)
536-
if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
537-
if meta_item.path.segments.len() == 1 {
538-
self.lints_allowed.push(meta_list.name_or_empty())
539-
} else {
540-
self.lints_allowed.push(meta_item.path.segments[1].ident.name);
541-
}
542-
}
543-
}
501+
fn lint_level_minimums(&mut self, tcx: TyCtxt<'tcx>) {
502+
tcx.sess.psess.lints_that_can_emit.with_lock(|vec| {
503+
par_for_each_in(vec, |lint_symbol| {
504+
self.lints_to_emit.with_lock(|lints_to_emit| {lints_to_emit.push(*lint_symbol)});
544505
}
545-
}
506+
);
507+
});
508+
tcx.sess.psess.lints_allowed.with_lock(|vec| {
509+
par_for_each_in(vec, |lint_symbol| {
510+
self.lints_allowed.with_lock(|lints_allowed| {lints_allowed.push(*lint_symbol)});
511+
}
512+
);
513+
});
514+
546515
}
547516
}
548517

518+
// impl<'tcx> Visitor<'tcx> for LintLevelMinimum<'tcx> {
519+
// type NestedFilter = nested_filter::All;
520+
521+
// fn nested_visit_map(&mut self) -> Self::Map {
522+
// self.tcx.hir()
523+
// }
524+
525+
// fn visit_attribute(&mut self, attribute: &'tcx ast::Attribute) {
526+
// if let Some(meta) = attribute.meta() {
527+
// if [sym::warn, sym::deny, sym::forbid, sym::expect]
528+
// .iter()
529+
// .any(|kind| meta.has_name(*kind))
530+
// {
531+
// // SAFETY: Lint attributes are always a metalist inside a
532+
// // metalist (even with just one lint).
533+
// for meta_list in meta.meta_item_list().unwrap() {
534+
// // If it's a tool lint (e.g. clippy::my_clippy_lint)
535+
// if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
536+
// if meta_item.path.segments.len() == 1 {
537+
// self.lints_to_emit.push(
538+
// // SAFETY: Lint attributes can only have literals
539+
// meta_list.ident().unwrap().name,
540+
// );
541+
// } else {
542+
// self.lints_to_emit.push(meta_item.path.segments[1].ident.name);
543+
// }
544+
// }
545+
// }
546+
// // We handle #![allow]s differently, as these remove checking rather than adding.
547+
// } else if meta.has_name(sym::allow)
548+
// && let ast::AttrStyle::Inner = attribute.style
549+
// {
550+
// for meta_list in meta.meta_item_list().unwrap() {
551+
// // If it's a tool lint (e.g. clippy::my_clippy_lint)
552+
// if let ast::NestedMetaItem::MetaItem(meta_item) = meta_list {
553+
// if meta_item.path.segments.len() == 1 {
554+
// self.lints_allowed.push(meta_list.name_or_empty())
555+
// } else {
556+
// self.lints_allowed.push(meta_item.path.segments[1].ident.name);
557+
// }
558+
// }
559+
// }
560+
// }
561+
// }
562+
// }
563+
// }
564+
549565
pub struct LintLevelsBuilder<'s, P> {
550566
sess: &'s Session,
551567
features: &'s Features,

compiler/rustc_parse/src/parser/attr.rs

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,7 @@ impl<'a> Parser<'a> {
117117
);
118118
let lo = self.token.span;
119119
// Attributes can't have attributes of their own [Editor's note: not with that attitude]
120-
self.collect_tokens_no_attrs(|this| {
120+
let attribute_result = self.collect_tokens_no_attrs(|this| {
121121
assert!(this.eat(&token::Pound), "parse_attribute called in non-attribute position");
122122

123123
let style =
@@ -132,9 +132,52 @@ impl<'a> Parser<'a> {
132132
if style == ast::AttrStyle::Inner {
133133
this.error_on_forbidden_inner_attr(attr_sp, inner_parse_policy);
134134
}
135-
136135
Ok(attr::mk_attr_from_item(&self.psess.attr_id_generator, item, None, style, attr_sp))
137-
})
136+
});
137+
138+
if let Ok(ref attr) = attribute_result && let Some(meta) = attr.meta() {
139+
if let Some(first) = meta.path.segments.first() {
140+
if [sym::warn, sym::deny, sym::forbid]
141+
.iter()
142+
.any(|symbol| first.ident.name == *symbol)
143+
{
144+
for meta_list in attr.meta_item_list().unwrap() {
145+
// If it's a tool lint (e.g. clippy::my_clippy_lint)
146+
if let ast::NestedMetaItem::MetaItem(ref meta_item) = meta_list {
147+
if meta_item.path.segments.len() == 1 {
148+
self.psess
149+
.lints_that_can_emit.with_lock(|lints_that_can_emit| {
150+
lints_that_can_emit
151+
.push(meta_list.ident().unwrap().name);
152+
})
153+
} else {
154+
self.psess
155+
.lints_that_can_emit.with_lock(|lints_that_can_emit| {
156+
lints_that_can_emit
157+
.push(meta_item.path.segments[1].ident.name);
158+
})
159+
}
160+
}
161+
}
162+
} else if first.ident.name == sym::allow && attr.style == ast::AttrStyle::Inner {
163+
for meta_list in attr.meta_item_list().unwrap() {
164+
// If it's a tool lint (e.g. clippy::my_clippy_lint)
165+
if let ast::NestedMetaItem::MetaItem(ref meta_item) = meta_list {
166+
if meta_item.path.segments.len() == 1 {
167+
self.psess.lints_allowed.with_lock(|lints_allowed| {
168+
lints_allowed.push(meta_list.name_or_empty())
169+
})
170+
} else {
171+
self.psess.lints_allowed.with_lock(|lints_allowed| {
172+
lints_allowed.push(meta_item.path.segments[1].ident.name);
173+
})
174+
}
175+
}
176+
}
177+
}
178+
}
179+
}
180+
attribute_result
138181
}
139182

140183
fn annotate_following_item_if_applicable(

compiler/rustc_session/src/parse.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -232,6 +232,13 @@ pub struct ParseSess {
232232
proc_macro_quoted_spans: AppendOnlyVec<Span>,
233233
/// Used to generate new `AttrId`s. Every `AttrId` is unique.
234234
pub attr_id_generator: AttrIdGenerator,
235+
/// All lints that can emit, even if not emitted (i.e. lints that are mentioned
236+
/// in e.g. #![warn] attributes)
237+
pub lints_that_can_emit: Lock<Vec<Symbol>>,
238+
/// The list of lints that cannot emit, maybe because they are allowed
239+
/// globally, or the default level is Allow and they are not activated
240+
/// manually
241+
pub lints_allowed: Lock<Vec<Symbol>>
235242
}
236243

237244
impl ParseSess {
@@ -266,6 +273,8 @@ impl ParseSess {
266273
assume_incomplete_release: false,
267274
proc_macro_quoted_spans: Default::default(),
268275
attr_id_generator: AttrIdGenerator::new(),
276+
lints_that_can_emit: Lock::new(Vec::with_capacity(230)),
277+
lints_allowed: Lock::new(Vec::with_capacity(100)),
269278
}
270279
}
271280

src/tools/clippy/tests/ui/no_lints.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
#![deny(clippy::all)]
2+
3+
fn main() {}

0 commit comments

Comments
 (0)