Skip to content

Commit d595fce

Browse files
committed
Auto merge of #157329 - JonathanBrouwer:rollup-DyoIgRF, r=JonathanBrouwer
Rollup of 9 pull requests Successful merges: - #157035 (`LivenessValues`: use dedicated enum rather than mutually exclusive `Option`s) - #157182 (Restore simpler Encode/Decode impls for u32 and (on 64bit systems) usize) - #157310 (rustdoc: Render `impl` restriction) - #157070 (Remove `skip_arg` attribute from `Diagnostic` and `Subdiagnostic` proc-macros) - #157137 (rustc_target: Use +spe for powerpcspe targets) - #157215 (Implement argument-dependent target checking for the `#[repr]` parser) - #157235 (additional changes for issue-144595) - #157321 (Remove unnecessary arm in `handle_res`) - #157324 (Add test for undefined EII static error)
2 parents 20e19ee + 51c415a commit d595fce

103 files changed

Lines changed: 1236 additions & 1178 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

compiler/rustc_attr_parsing/src/attributes/repr.rs

Lines changed: 107 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,16 @@ impl CombineAttributeParser for ReprParser {
3737
};
3838

3939
if list.is_empty() {
40+
cx.check_target(
41+
"()",
42+
&AllowedTargets::AllowList(&[
43+
Allow(Target::Struct),
44+
Allow(Target::Enum),
45+
Allow(Target::Union),
46+
Warn(Target::MacroCall),
47+
]),
48+
);
49+
4050
let attr_span = cx.attr_span;
4151
cx.adcx().warn_empty_attribute(attr_span);
4252
return vec![];
@@ -53,51 +63,120 @@ impl CombineAttributeParser for ReprParser {
5363
reprs
5464
}
5565

56-
//FIXME Still checked fully in `check_attr.rs`
57-
//This one is slightly more complicated because the allowed targets depend on the arguments
58-
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS);
66+
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::ManuallyChecked;
5967
const STABILITY: AttributeStability = AttributeStability::Stable;
6068
}
6169

6270
fn parse_repr(cx: &mut AcceptContext<'_, '_>, param: &MetaItemParser) -> Option<ReprAttr> {
6371
use ReprAttr::*;
6472

65-
macro_rules! no_args {
66-
($constructor: expr) => {{
73+
macro_rules! repr_int {
74+
($arg: ident, $constructor: expr) => {{
75+
cx.check_target(
76+
concat!("(", stringify!($arg), ")"),
77+
&AllowedTargets::AllowList(&[Allow(Target::Enum), Warn(Target::MacroCall)]),
78+
);
6779
cx.expect_no_args(param.args())?;
6880
Some($constructor)
6981
}};
7082
}
7183

7284
match param.path().word_sym() {
7385
Some(sym::align) => {
86+
cx.check_target(
87+
"(align(...))",
88+
&AllowedTargets::AllowList(&[
89+
Allow(Target::Struct),
90+
Allow(Target::Enum),
91+
Allow(Target::Union),
92+
Warn(Target::MacroCall),
93+
]),
94+
);
7495
let l = cx.expect_list(param.args(), param.span())?;
7596
parse_repr_align(cx, l, AlignKind::Align)
7697
}
77-
Some(sym::packed) => match param.args() {
78-
ArgParser::NoArgs => Some(ReprPacked(Align::ONE)),
79-
ArgParser::List(l) => parse_repr_align(cx, l, AlignKind::Packed),
80-
ArgParser::NameValue(_) => {
81-
cx.adcx().expected_list_or_no_args(param.span());
82-
None
98+
Some(sym::packed) => {
99+
cx.check_target(
100+
"(packed)",
101+
&AllowedTargets::AllowList(&[
102+
Allow(Target::Struct),
103+
Allow(Target::Union),
104+
Warn(Target::MacroCall),
105+
]),
106+
);
107+
match param.args() {
108+
ArgParser::NoArgs => Some(ReprPacked(Align::ONE)),
109+
ArgParser::List(l) => parse_repr_align(cx, l, AlignKind::Packed),
110+
ArgParser::NameValue(_) => {
111+
cx.adcx().expected_list_or_no_args(param.span());
112+
None
113+
}
83114
}
84-
},
85-
Some(sym::Rust) => no_args!(ReprRust),
86-
Some(sym::C) => no_args!(ReprC),
87-
Some(sym::simd) => no_args!(ReprSimd),
88-
Some(sym::transparent) => no_args!(ReprTransparent),
89-
Some(sym::i8) => no_args!(ReprInt(SignedInt(IntTy::I8))),
90-
Some(sym::u8) => no_args!(ReprInt(UnsignedInt(UintTy::U8))),
91-
Some(sym::i16) => no_args!(ReprInt(SignedInt(IntTy::I16))),
92-
Some(sym::u16) => no_args!(ReprInt(UnsignedInt(UintTy::U16))),
93-
Some(sym::i32) => no_args!(ReprInt(SignedInt(IntTy::I32))),
94-
Some(sym::u32) => no_args!(ReprInt(UnsignedInt(UintTy::U32))),
95-
Some(sym::i64) => no_args!(ReprInt(SignedInt(IntTy::I64))),
96-
Some(sym::u64) => no_args!(ReprInt(UnsignedInt(UintTy::U64))),
97-
Some(sym::i128) => no_args!(ReprInt(SignedInt(IntTy::I128))),
98-
Some(sym::u128) => no_args!(ReprInt(UnsignedInt(UintTy::U128))),
99-
Some(sym::isize) => no_args!(ReprInt(SignedInt(IntTy::Isize))),
100-
Some(sym::usize) => no_args!(ReprInt(UnsignedInt(UintTy::Usize))),
115+
}
116+
117+
Some(sym::Rust) => {
118+
cx.check_target(
119+
"(Rust)",
120+
&AllowedTargets::AllowList(&[
121+
Allow(Target::Struct),
122+
Allow(Target::Enum),
123+
Allow(Target::Union),
124+
Warn(Target::MacroCall),
125+
]),
126+
);
127+
cx.expect_no_args(param.args())?;
128+
Some(ReprRust)
129+
}
130+
Some(sym::C) => {
131+
cx.check_target(
132+
"(C)",
133+
&AllowedTargets::AllowList(&[
134+
Allow(Target::Struct),
135+
Allow(Target::Enum),
136+
Allow(Target::Union),
137+
Warn(Target::MacroCall),
138+
]),
139+
);
140+
cx.expect_no_args(param.args())?;
141+
Some(ReprC)
142+
}
143+
Some(sym::simd) => {
144+
cx.check_target(
145+
"(simd)",
146+
&AllowedTargets::AllowList(&[
147+
Allow(Target::Struct), // Feature gated in `rustc_ast_passes`
148+
Warn(Target::MacroCall), // FIXME: This is not feature gated (!!)
149+
]),
150+
);
151+
cx.expect_no_args(param.args())?;
152+
Some(ReprSimd)
153+
}
154+
Some(sym::transparent) => {
155+
cx.check_target(
156+
"(transparent)",
157+
&AllowedTargets::AllowList(&[
158+
Allow(Target::Struct),
159+
Allow(Target::Enum),
160+
Allow(Target::Union), // Feature gated in `rustc_hir_analysis`
161+
Warn(Target::MacroCall),
162+
]),
163+
);
164+
cx.expect_no_args(param.args())?;
165+
Some(ReprTransparent)
166+
}
167+
168+
Some(sym::i8) => repr_int!(i8, ReprInt(SignedInt(IntTy::I8))),
169+
Some(sym::u8) => repr_int!(u8, ReprInt(UnsignedInt(UintTy::U8))),
170+
Some(sym::i16) => repr_int!(i16, ReprInt(SignedInt(IntTy::I16))),
171+
Some(sym::u16) => repr_int!(u16, ReprInt(UnsignedInt(UintTy::U16))),
172+
Some(sym::i32) => repr_int!(i32, ReprInt(SignedInt(IntTy::I32))),
173+
Some(sym::u32) => repr_int!(u32, ReprInt(UnsignedInt(UintTy::U32))),
174+
Some(sym::i64) => repr_int!(i64, ReprInt(SignedInt(IntTy::I64))),
175+
Some(sym::u64) => repr_int!(u64, ReprInt(UnsignedInt(UintTy::U64))),
176+
Some(sym::i128) => repr_int!(i128, ReprInt(SignedInt(IntTy::I128))),
177+
Some(sym::u128) => repr_int!(u128, ReprInt(UnsignedInt(UintTy::U128))),
178+
Some(sym::isize) => repr_int!(isize, ReprInt(SignedInt(IntTy::Isize))),
179+
Some(sym::usize) => repr_int!(usize, ReprInt(UnsignedInt(UintTy::Usize))),
101180
_ => {
102181
cx.adcx().expected_specific_argument(
103182
param.span(),

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,10 @@ pub struct AcceptContext<'f, 'sess> {
366366

367367
/// The name of the attribute we're currently accepting.
368368
pub(crate) attr_path: AttrPath,
369+
370+
/// Used for `AllowedTargets::ManuallyChecked`, to assert that the manual target check has been done
371+
#[cfg(debug_assertions)]
372+
pub(crate) has_target_been_checked: bool,
369373
}
370374

371375
impl<'f, 'sess: 'f> SharedContext<'f, 'sess> {

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,8 @@ impl<'sess> AttributeParser<'sess> {
240240
template,
241241
attr_safety: attr_safety.unwrap_or(Safety::Default),
242242
attr_path,
243+
#[cfg(debug_assertions)]
244+
has_target_been_checked: false,
243245
};
244246
parse_fn(&mut cx, args)
245247
}
@@ -410,12 +412,14 @@ impl<'sess> AttributeParser<'sess> {
410412
template: &accept.template,
411413
attr_safety: n.item.unsafety,
412414
attr_path: attr_path.clone(),
415+
#[cfg(debug_assertions)]
416+
has_target_been_checked: false,
413417
};
414418

415419
(accept.accept_fn)(&mut cx, &args);
416420
finalizers.push(accept.finalizer);
417421

418-
Self::check_target(&accept.allowed_targets, &mut cx);
422+
Self::check_target(&accept.allowed_targets, "", &mut cx);
419423
#[cfg(debug_assertions)]
420424
if !cx.shared.has_lint_been_emitted.load(Ordering::Relaxed) {
421425
cx.shared.cx.check_args_used(&attr, &args)

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -331,8 +331,8 @@ pub(crate) struct EmptyConfusables {
331331
}
332332

333333
#[derive(Diagnostic)]
334-
#[help("`#[{$name}]` can {$only}be applied to {$applied}")]
335-
#[diag("`#[{$name}]` attribute cannot be used on {$target}")]
334+
#[help("`#[{$name}{$attribute_args}]` can {$only}be applied to {$applied}")]
335+
#[diag("`#[{$name}{$attribute_args}]` attribute cannot be used on {$target}")]
336336
pub(crate) struct InvalidTarget {
337337
#[primary_span]
338338
#[suggestion(
@@ -346,12 +346,23 @@ pub(crate) struct InvalidTarget {
346346
pub target: &'static str,
347347
pub applied: DiagArgValue,
348348
pub only: &'static str,
349+
pub attribute_args: &'static str,
350+
#[subdiagnostic]
351+
pub help: Option<InvalidTargetHelp>,
349352
#[warning(
350353
"this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!"
351354
)]
352355
pub previously_accepted: bool,
353356
}
354357

358+
#[derive(Subdiagnostic)]
359+
pub(crate) enum InvalidTargetHelp {
360+
#[help("use `#[rustc_align(...)]` instead")]
361+
UseRustcAlign,
362+
#[help("use `#[rustc_align_static(...)]` instead")]
363+
UseRustcAlignStatic,
364+
}
365+
355366
#[derive(Diagnostic)]
356367
#[diag("invalid alignment value: {$error_part}", code = E0589)]
357368
pub(crate) struct InvalidAlignmentValue {

compiler/rustc_attr_parsing/src/target_checking.rs

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,18 @@ use crate::context::AcceptContext;
1111
use crate::errors::{
1212
InvalidAttrAtCrateLevel, ItemFollowingInnerAttr, UnsupportedAttributesInWhere,
1313
};
14-
use crate::session_diagnostics::InvalidTarget;
14+
use crate::session_diagnostics::{InvalidTarget, InvalidTargetHelp};
1515
use crate::target_checking::Policy::Allow;
1616
use crate::{AttributeParser, ShouldEmit};
1717

1818
#[derive(Debug)]
1919
pub(crate) enum AllowedTargets {
2020
AllowList(&'static [Policy]),
2121
AllowListWarnRest(&'static [Policy]),
22+
/// This is useful for argument-dependent target checking.
23+
/// If debug assertions are enabled,
24+
/// this emits a delayed bug if the `cx.check_target(...)` method is not called during attribute parsing.
25+
ManuallyChecked,
2226
}
2327

2428
pub(crate) enum AllowedResult {
@@ -52,13 +56,15 @@ impl AllowedTargets {
5256
AllowedResult::Warn
5357
}
5458
}
59+
AllowedTargets::ManuallyChecked => unreachable!(),
5560
}
5661
}
5762

5863
pub(crate) fn allowed_targets(&self) -> Vec<Target> {
5964
match self {
6065
AllowedTargets::AllowList(list) => list,
6166
AllowedTargets::AllowListWarnRest(list) => list,
67+
AllowedTargets::ManuallyChecked => unreachable!(),
6268
}
6369
.iter()
6470
.filter_map(|target| match target {
@@ -89,38 +95,29 @@ pub(crate) enum Policy {
8995
impl<'sess> AttributeParser<'sess> {
9096
pub(crate) fn check_target(
9197
allowed_targets: &AllowedTargets,
98+
attribute_args: &'static str,
9299
cx: &mut AcceptContext<'_, 'sess>,
93100
) {
94101
if matches!(cx.should_emit, ShouldEmit::Nothing) {
95102
return;
96103
}
97104

105+
if let AllowedTargets::ManuallyChecked = allowed_targets {
106+
#[cfg(debug_assertions)]
107+
if !cx.has_target_been_checked {
108+
cx.dcx().delayed_bug("Attribute target has not been checked");
109+
}
110+
111+
return;
112+
}
113+
98114
// For crate-level attributes we emit a specific set of lints to warn
99115
// people about accidentally not using them on the crate.
100116
if let &AllowedTargets::AllowList(&[Allow(Target::Crate)]) = allowed_targets {
101117
Self::check_crate_level(cx);
102118
return;
103119
}
104120

105-
if matches!(cx.attr_path.segments.as_ref(), [sym::repr]) && cx.target == Target::Crate {
106-
// The allowed targets of `repr` depend on its arguments. They can't be checked using
107-
// the `AttributeParser` code.
108-
let span = cx.attr_span;
109-
let item =
110-
cx.cx.first_line_of_next_item(span).map(|span| ItemFollowingInnerAttr { span });
111-
112-
let pound_to_opening_bracket = cx.attr_span.until(cx.inner_span);
113-
114-
cx.dcx()
115-
.create_err(InvalidAttrAtCrateLevel {
116-
span,
117-
pound_to_opening_bracket,
118-
name: sym::repr,
119-
item,
120-
})
121-
.emit();
122-
}
123-
124121
let result = allowed_targets.is_allowed(cx.target);
125122
if matches!(result, AllowedResult::Allowed) {
126123
return;
@@ -134,6 +131,8 @@ impl<'sess> AttributeParser<'sess> {
134131
target: cx.target.plural_name(),
135132
only: if only { "only " } else { "" },
136133
applied: DiagArgValue::StrListSepByAnd(applied.into_iter().map(Cow::Owned).collect()),
134+
attribute_args,
135+
help: Self::target_checking_help(attribute_args, cx),
137136
previously_accepted: matches!(result, AllowedResult::Warn),
138137
};
139138

@@ -164,6 +163,24 @@ impl<'sess> AttributeParser<'sess> {
164163
}
165164
}
166165

166+
fn target_checking_help(
167+
attribute_args: &'static str,
168+
cx: &AcceptContext<'_, '_>,
169+
) -> Option<InvalidTargetHelp> {
170+
match &*cx.attr_path.segments {
171+
[sym::repr] if attribute_args == "(align(...))" => match cx.target {
172+
Target::Fn | Target::Method(..) if cx.features().fn_align() => {
173+
Some(InvalidTargetHelp::UseRustcAlign)
174+
}
175+
Target::Static if cx.features().static_align() => {
176+
Some(InvalidTargetHelp::UseRustcAlignStatic)
177+
}
178+
_ => None,
179+
},
180+
_ => None,
181+
}
182+
}
183+
167184
pub(crate) fn check_crate_level(cx: &mut AcceptContext<'_, 'sess>) {
168185
if cx.target == Target::Crate {
169186
return;
@@ -399,6 +416,20 @@ fn filter_targets(
399416
added_fake_targets.push(target_group_name);
400417
}
401418

419+
impl<'f, 'sess> AcceptContext<'f, 'sess> {
420+
pub(crate) fn check_target(
421+
&mut self,
422+
attribute_args: &'static str,
423+
allowed_targets: &AllowedTargets,
424+
) {
425+
#[cfg(debug_assertions)]
426+
{
427+
self.has_target_been_checked = true;
428+
}
429+
AttributeParser::check_target(allowed_targets, attribute_args, self);
430+
}
431+
}
432+
402433
/// This is the list of all targets to which a attribute can be applied
403434
/// This is used for:
404435
/// - `rustc_dummy`, which can be applied to all targets

0 commit comments

Comments
 (0)