Skip to content

Commit 49443bf

Browse files
committed
lint on duplicates during attribute parsing
To do this we stuff them in the diagnostic context to be emitted after hir is constructed
1 parent 1170acb commit 49443bf

File tree

20 files changed

+482
-217
lines changed

20 files changed

+482
-217
lines changed

compiler/rustc_ast_lowering/src/expr.rs

+5-4
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
7474
// Merge attributes into the inner expression.
7575
if !e.attrs.is_empty() {
7676
let old_attrs = self.attrs.get(&ex.hir_id.local_id).copied().unwrap_or(&[]);
77+
let new_attrs = self.lower_attrs_vec(&e.attrs, e.span, ex.hir_id)
78+
.into_iter()
79+
.chain(old_attrs.iter().cloned());
7780
self.attrs.insert(
7881
ex.hir_id.local_id,
7982
&*self.arena.alloc_from_iter(
80-
self.lower_attrs_vec(&e.attrs, e.span)
81-
.into_iter()
82-
.chain(old_attrs.iter().cloned()),
83+
new_attrs,
8384
),
8485
);
8586
}
@@ -2025,7 +2026,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
20252026
let ret_expr = self.checked_return(Some(from_residual_expr));
20262027
self.arena.alloc(self.expr(try_span, ret_expr))
20272028
};
2028-
self.lower_attrs(ret_expr.hir_id, &attrs, ret_expr.span);
2029+
self.lower_attrs(ret_expr.hir_id, &attrs, span);
20292030

20302031
let break_pat = self.pat_cf_break(try_span, residual_local);
20312032
self.arm(break_pat, ret_expr)

compiler/rustc_ast_lowering/src/item.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ impl<'a, 'hir> ItemLowerer<'a, 'hir> {
5858
&mut self,
5959
owner: NodeId,
6060
f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>,
61-
) {
61+
) {
6262
let mut lctx = LoweringContext::new(self.tcx, self.resolver);
6363
lctx.with_hir_id_owner(owner, |lctx| f(lctx));
6464

compiler/rustc_ast_lowering/src/lib.rs

+41-12
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
5151
use rustc_data_structures::tagged_ptr::TaggedRef;
5252
use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, StashKey};
5353
use rustc_hir::def::{DefKind, LifetimeRes, Namespace, PartialRes, PerNS, Res};
54-
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId};
54+
use rustc_hir::def_id::{LocalDefId, CRATE_DEF_ID, LOCAL_CRATE};
5555
use rustc_hir::{
5656
self as hir, ConstArg, GenericArg, HirId, ItemLocalMap, LangItem, ParamName, TraitCandidate,
5757
};
@@ -188,7 +188,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
188188
// interact with `gen`/`async gen` blocks
189189
allow_async_iterator: [sym::gen_future, sym::async_iterator].into(),
190190

191-
attribute_parser: AttributeParser::new(tcx.sess, tcx.features(), registered_tools),
191+
attribute_parser: AttributeParser::new(tcx, tcx.features(), registered_tools),
192192
}
193193
}
194194

@@ -197,6 +197,22 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
197197
}
198198
}
199199

200+
struct SpanLowerer {
201+
is_incremental: bool,
202+
defid: LocalDefId,
203+
}
204+
205+
impl SpanLowerer {
206+
fn lower(&self, span: Span) -> Span {
207+
if self.is_incremental {
208+
span.with_parent(Some(self.defid))
209+
} else {
210+
// Do not make spans relative when not using incremental compilation.
211+
span
212+
}
213+
}
214+
}
215+
200216
#[extension(trait ResolverAstLoweringExt)]
201217
impl ResolverAstLowering {
202218
fn legacy_const_generic_args(&self, expr: &Expr) -> Option<Vec<usize>> {
@@ -740,15 +756,17 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
740756
})
741757
}
742758

759+
fn span_lowerer(&self) -> SpanLowerer {
760+
SpanLowerer {
761+
is_incremental: self.tcx.sess.opts.incremental.is_some(),
762+
defid: self.current_hir_id_owner.def_id,
763+
}
764+
}
765+
743766
/// Intercept all spans entering HIR.
744767
/// Mark a span as relative to the current owning item.
745768
fn lower_span(&self, span: Span) -> Span {
746-
if self.tcx.sess.opts.incremental.is_some() {
747-
span.with_parent(Some(self.current_hir_id_owner.def_id))
748-
} else {
749-
// Do not make spans relative when not using incremental compilation.
750-
span
751-
}
769+
self.span_lowerer().lower(span)
752770
}
753771

754772
fn lower_ident(&self, ident: Ident) -> Ident {
@@ -871,7 +889,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
871889
if attrs.is_empty() {
872890
&[]
873891
} else {
874-
let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span));
892+
let lowered_attrs = self.lower_attrs_vec(attrs, self.lower_span(target_span), id);
875893

876894
debug_assert_eq!(id.owner, self.current_hir_id_owner);
877895
let ret = self.arena.alloc_from_iter(lowered_attrs);
@@ -891,9 +909,20 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
891909
}
892910
}
893911

894-
fn lower_attrs_vec(&self, attrs: &[Attribute], target_span: Span) -> Vec<hir::Attribute> {
895-
self.attribute_parser
896-
.parse_attribute_list(attrs, target_span, OmitDoc::Lower, |s| self.lower_span(s))
912+
fn lower_attrs_vec(
913+
&mut self,
914+
attrs: &[Attribute],
915+
target_span: Span,
916+
target_hir_id: HirId,
917+
) -> Vec<hir::Attribute> {
918+
let l = self.span_lowerer();
919+
self.attribute_parser.parse_attribute_list(
920+
attrs,
921+
target_span,
922+
target_hir_id,
923+
OmitDoc::Lower,
924+
|s| l.lower(s),
925+
)
897926
}
898927

899928
fn alias_attrs(&mut self, id: HirId, target_id: HirId) {

compiler/rustc_attr_parsing/messages.ftl

+10
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,17 @@ attr_parsing_unsupported_literal_generic =
131131
attr_parsing_unsupported_literal_suggestion =
132132
consider removing the prefix
133133
134+
attr_parsing_unused_duplicate =
135+
unused attribute
136+
.suggestion = remove this attribute
137+
.note = attribute also specified here
138+
.warn = {-attr_parsing_previously_accepted}
139+
140+
134141
attr_parsing_unused_multiple =
135142
multiple `{$name}` attributes
136143
.suggestion = remove this attribute
137144
.note = attribute also specified here
145+
146+
-attr_parsing_perviously_accepted =
147+
this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs

+18-16
Original file line numberDiff line numberDiff line change
@@ -4,41 +4,43 @@ use rustc_attr_data_structures::AttributeKind;
44
use rustc_span::{Span, Symbol, sym};
55

66
use super::{CombineAttributeParser, ConvertFn};
7-
use crate::context::AcceptContext;
7+
use crate::context::{AcceptContext, Stage};
88
use crate::parser::ArgParser;
99
use crate::session_diagnostics;
1010

1111
pub(crate) struct AllowInternalUnstableParser;
12-
impl CombineAttributeParser for AllowInternalUnstableParser {
12+
impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
1313
const PATH: &'static [rustc_span::Symbol] = &[sym::allow_internal_unstable];
1414
type Item = (Symbol, Span);
1515
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowInternalUnstable;
1616

17-
fn extend<'a>(
18-
cx: &'a AcceptContext<'a>,
19-
args: &'a ArgParser<'a>,
20-
) -> impl IntoIterator<Item = Self::Item> + 'a {
21-
parse_unstable(cx, args, Self::PATH[0]).into_iter().zip(iter::repeat(cx.attr_span))
17+
fn extend<'c>(
18+
cx: &'c mut AcceptContext<'_, '_, S>,
19+
args: &'c ArgParser<'_>,
20+
) -> impl IntoIterator<Item = Self::Item> {
21+
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
22+
.into_iter()
23+
.zip(iter::repeat(cx.attr_span))
2224
}
2325
}
2426

2527
pub(crate) struct AllowConstFnUnstableParser;
26-
impl CombineAttributeParser for AllowConstFnUnstableParser {
28+
impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
2729
const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_allow_const_fn_unstable];
2830
type Item = Symbol;
2931
const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowConstFnUnstable;
3032

31-
fn extend<'a>(
32-
cx: &'a AcceptContext<'a>,
33-
args: &'a ArgParser<'a>,
34-
) -> impl IntoIterator<Item = Self::Item> + 'a {
35-
parse_unstable(cx, args, Self::PATH[0])
33+
fn extend<'c>(
34+
cx: &'c mut AcceptContext<'_, '_, S>,
35+
args: &'c ArgParser<'_>,
36+
) -> impl IntoIterator<Item = Self::Item> + 'c {
37+
parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
3638
}
3739
}
3840

39-
fn parse_unstable<'a>(
40-
cx: &AcceptContext<'_>,
41-
args: &'a ArgParser<'a>,
41+
fn parse_unstable<S: Stage>(
42+
cx: &AcceptContext<'_, '_, S>,
43+
args: &ArgParser<'_>,
4244
symbol: Symbol,
4345
) -> impl IntoIterator<Item = Symbol> {
4446
let mut res = Vec::new();

compiler/rustc_attr_parsing/src/attributes/confusables.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ use rustc_span::{Span, Symbol, sym};
33
use thin_vec::ThinVec;
44

55
use super::{AcceptMapping, AttributeParser};
6-
use crate::context::FinalizeContext;
6+
use crate::context::{FinalizeContext, Stage};
77
use crate::session_diagnostics;
88

99
#[derive(Default)]
@@ -12,8 +12,8 @@ pub(crate) struct ConfusablesParser {
1212
first_span: Option<Span>,
1313
}
1414

15-
impl AttributeParser for ConfusablesParser {
16-
const ATTRIBUTES: AcceptMapping<Self> = &[(&[sym::rustc_confusables], |this, cx, args| {
15+
impl<S: Stage> AttributeParser<S> for ConfusablesParser {
16+
const ATTRIBUTES: AcceptMapping<Self, S> = &[(&[sym::rustc_confusables], |this, cx, args| {
1717
let Some(list) = args.list() else {
1818
// FIXME(jdonszelmann): error when not a list? Bring validation code here.
1919
// NOTE: currently subsequent attributes are silently ignored using
@@ -45,7 +45,7 @@ impl AttributeParser for ConfusablesParser {
4545
this.first_span.get_or_insert(cx.attr_span);
4646
})];
4747

48-
fn finalize(self, _cx: &FinalizeContext<'_>) -> Option<AttributeKind> {
48+
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
4949
if self.confusables.is_empty() {
5050
return None;
5151
}

compiler/rustc_attr_parsing/src/attributes/deprecation.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -2,18 +2,17 @@ use rustc_attr_data_structures::{AttributeKind, DeprecatedSince, Deprecation};
22
use rustc_span::symbol::Ident;
33
use rustc_span::{Span, Symbol, sym};
44

5-
use super::{AttributeDuplicates, OnDuplicate, SingleAttributeParser};
65
use super::util::parse_version;
7-
use super::{AttributeDuplicates, SingleAttributeParser};
8-
use crate::context::AcceptContext;
6+
use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
7+
use crate::context::{AcceptContext, Stage};
98
use crate::parser::ArgParser;
109
use crate::session_diagnostics;
1110
use crate::session_diagnostics::UnsupportedLiteralReason;
1211

1312
pub(crate) struct DeprecationParser;
1413

15-
fn get(
16-
cx: &AcceptContext<'_>,
14+
fn get<S: Stage>(
15+
cx: &AcceptContext<'_, '_, S>,
1716
ident: Ident,
1817
param_span: Span,
1918
arg: &ArgParser<'_>,
@@ -46,12 +45,12 @@ fn get(
4645
}
4746
}
4847

49-
impl SingleAttributeParser for DeprecationParser {
48+
impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
5049
const PATH: &'static [rustc_span::Symbol] = &[sym::deprecated];
51-
const ON_DUPLICATE_STRATEGY: AttributeDuplicates = AttributeDuplicates::ErrorFollowing;
52-
const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error;
50+
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepFirst;
51+
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
5352

54-
fn convert(cx: &AcceptContext<'_>, args: &ArgParser<'_>) -> Option<AttributeKind> {
53+
fn convert(cx: &AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
5554
let features = cx.features();
5655

5756
let mut since = None;

0 commit comments

Comments
 (0)