Skip to content

Commit 0981955

Browse files
committed
Allow overruling forbidden lints in derive macros
1 parent 410a546 commit 0981955

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

compiler/rustc_lint/src/levels.rs

+41-6
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,11 @@ use rustc_middle::ty::TyCtxt;
2020
use rustc_session::lint::{builtin, Level, Lint, LintId};
2121
use rustc_session::parse::feature_err;
2222
use rustc_session::Session;
23-
use rustc_span::symbol::{sym, Symbol};
2423
use rustc_span::{source_map::MultiSpan, Span, DUMMY_SP};
24+
use rustc_span::{
25+
symbol::{sym, Symbol},
26+
ExpnId,
27+
};
2528

2629
use std::cmp;
2730

@@ -58,6 +61,15 @@ pub struct BuilderPush {
5861
pub changed: bool,
5962
}
6063

64+
/// Returns true when a lint level can override a previously set forbid.
65+
fn can_overrule_forbidden(span: Span, expn: Option<ExpnId>) -> bool {
66+
if let Some(expn_id) = expn {
67+
!span.in_derive_expansion() || span.ctxt().outer_expn() != expn_id
68+
} else {
69+
false
70+
}
71+
}
72+
6173
impl<'s> LintLevelsBuilder<'s> {
6274
pub fn new(sess: &'s Session, warn_about_weird_lints: bool, store: &LintStore) -> Self {
6375
let mut builder = LintLevelsBuilder {
@@ -109,16 +121,23 @@ impl<'s> LintLevelsBuilder<'s> {
109121
specs: &mut FxHashMap<LintId, LevelAndSource>,
110122
id: LintId,
111123
(level, src): LevelAndSource,
124+
derive_expansion: Option<ExpnId>,
112125
) {
113126
// Setting to a non-forbid level is an error if the lint previously had
114127
// a forbid level. Note that this is not necessarily true even with a
115128
// `#[forbid(..)]` attribute present, as that is overriden by `--cap-lints`.
116129
//
117130
// This means that this only errors if we're truly lowering the lint
118131
// level from forbid.
132+
//
133+
// An exception to this is when the lint comes from a different derive macro
134+
// expansion than the previous forbid level.
119135
if level != Level::Forbid {
120-
if let (Level::Forbid, old_src) =
121-
self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess)
136+
let (old_level, old_src) =
137+
self.sets.get_lint_level(id.lint, self.cur, Some(&specs), &self.sess);
138+
139+
if old_level == Level::Forbid
140+
&& !can_overrule_forbidden(old_src.span(), derive_expansion)
122141
{
123142
let mut diag_builder = struct_span_err!(
124143
self.sess,
@@ -178,7 +197,13 @@ impl<'s> LintLevelsBuilder<'s> {
178197
let mut specs = FxHashMap::default();
179198
let sess = self.sess;
180199
let bad_attr = |span| struct_span_err!(sess, span, E0452, "malformed lint attribute input");
200+
181201
for attr in attrs {
202+
let derive_expansion = if attr.span.in_derive_expansion() {
203+
Some(attr.span.ctxt().outer_expn())
204+
} else {
205+
None
206+
};
182207
let level = match Level::from_symbol(attr.name_or_empty()) {
183208
None => continue,
184209
Some(lvl) => lvl,
@@ -281,7 +306,7 @@ impl<'s> LintLevelsBuilder<'s> {
281306
let src = LintLevelSource::Node(name, li.span(), reason);
282307
for &id in ids {
283308
self.check_gated_lint(id, attr.span);
284-
self.insert_spec(&mut specs, id, (level, src));
309+
self.insert_spec(&mut specs, id, (level, src), derive_expansion);
285310
}
286311
}
287312

@@ -295,7 +320,12 @@ impl<'s> LintLevelsBuilder<'s> {
295320
reason,
296321
);
297322
for id in ids {
298-
self.insert_spec(&mut specs, *id, (level, src));
323+
self.insert_spec(
324+
&mut specs,
325+
*id,
326+
(level, src),
327+
derive_expansion,
328+
);
299329
}
300330
}
301331
Err((Some(ids), new_lint_name)) => {
@@ -332,7 +362,12 @@ impl<'s> LintLevelsBuilder<'s> {
332362
reason,
333363
);
334364
for id in ids {
335-
self.insert_spec(&mut specs, *id, (level, src));
365+
self.insert_spec(
366+
&mut specs,
367+
*id,
368+
(level, src),
369+
derive_expansion,
370+
);
336371
}
337372
}
338373
Err((None, _)) => {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// check-pass
2+
#![forbid(unused_qualifications)]
3+
4+
#[derive(Clone)]
5+
pub struct S;
6+
7+
fn main() {}

0 commit comments

Comments
 (0)