Skip to content

Commit 3e2dbcd

Browse files
committed
Auto merge of #149646 - matthiaskrgr:rollup-jbfeow8, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - #147224 (Emscripten: Turn wasm-eh on by default) - #149405 (Recover on misspelled item keyword) - #149443 (Tidying up UI tests [6/N]) - #149524 (Move attribute safety checking to attribute parsing) - #149593 (powf, powi: point out SNaN non-determinism) - #149605 (Use branch name instead of HEAD when unshallowing) - #149612 (Apply the `bors` environment also to the `outcome` job) - #149623 (Don't require a normal tool build of clippy/rustfmt when running their test steps) - #149627 (Point to the item that is incorrectly annotated with `#[diagnostic::on_const]`) r? `@ghost` `@rustbot` modify labels: rollup
2 parents b33119f + 69f8a5c commit 3e2dbcd

File tree

86 files changed

+645
-447
lines changed

Some content is hidden

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

86 files changed

+645
-447
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,7 @@ jobs:
313313
needs: [ calculate_matrix, job ]
314314
# !cancelled() executes the job regardless of whether the previous jobs passed or failed
315315
if: ${{ !cancelled() && contains(fromJSON('["auto", "try"]'), needs.calculate_matrix.outputs.run_type) }}
316+
environment: ${{ ((github.repository == 'rust-lang/rust' && (github.ref == 'refs/heads/try' || github.ref == 'refs/heads/try-perf' || github.ref == 'refs/heads/automation/bors/try' || github.ref == 'refs/heads/auto')) && 'bors') || '' }}
316317
steps:
317318
- name: checkout the source code
318319
uses: actions/checkout@v5

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1075,7 +1075,7 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
10751075

10761076
impl<'a> Visitor<'a> for AstValidator<'a> {
10771077
fn visit_attribute(&mut self, attr: &Attribute) {
1078-
validate_attr::check_attr(&self.sess.psess, attr, self.lint_node_id);
1078+
validate_attr::check_attr(&self.sess.psess, attr);
10791079
}
10801080

10811081
fn visit_ty(&mut self, ty: &'a Ty) {

compiler/rustc_attr_parsing/src/attributes/cfg.rs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
use std::convert::identity;
2+
13
use rustc_ast::token::Delimiter;
24
use rustc_ast::tokenstream::DelimSpan;
35
use rustc_ast::{AttrItem, Attribute, CRATE_NODE_ID, LitKind, NodeId, ast, token};
@@ -353,7 +355,7 @@ pub fn parse_cfg_attr(
353355
span,
354356
attr_span: cfg_attr.span,
355357
template: CFG_ATTR_TEMPLATE,
356-
path: AttrPath::from_ast(&cfg_attr.get_normal_item().path),
358+
path: AttrPath::from_ast(&cfg_attr.get_normal_item().path, identity),
357359
description: ParsedDescription::Attribute,
358360
reason,
359361
suggestions: CFG_ATTR_TEMPLATE
@@ -398,6 +400,7 @@ fn parse_cfg_attr_internal<'a>(
398400
.into_boxed_slice(),
399401
span: attribute.span,
400402
},
403+
Some(attribute.get_normal_item().unsafety),
401404
ParsedDescription::Attribute,
402405
pred_span,
403406
CRATE_NODE_ID,

compiler/rustc_attr_parsing/src/attributes/cfg_select.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ pub fn parse_cfg_select(
6363
segments: vec![Ident::from_str("cfg_select")].into_boxed_slice(),
6464
span: cfg_span,
6565
},
66+
None,
6667
ParsedDescription::Macro,
6768
cfg_span,
6869
lint_node_id,

compiler/rustc_attr_parsing/src/interface.rs

Lines changed: 28 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
use std::borrow::Cow;
22

33
use rustc_ast as ast;
4-
use rustc_ast::{AttrStyle, NodeId};
4+
use rustc_ast::{AttrStyle, NodeId, Safety};
55
use rustc_errors::DiagCtxtHandle;
66
use rustc_feature::{AttributeTemplate, Features};
77
use rustc_hir::attrs::AttributeKind;
@@ -146,6 +146,7 @@ impl<'sess> AttributeParser<'sess, Early> {
146146
normal_attr.item.span(),
147147
attr.style,
148148
path.get_attribute_path(),
149+
Some(normal_attr.item.unsafety),
149150
ParsedDescription::Attribute,
150151
target_span,
151152
target_node_id,
@@ -165,6 +166,7 @@ impl<'sess> AttributeParser<'sess, Early> {
165166
inner_span: Span,
166167
attr_style: AttrStyle,
167168
attr_path: AttrPath,
169+
attr_safety: Option<Safety>,
168170
parsed_description: ParsedDescription,
169171
target_span: Span,
170172
target_node_id: NodeId,
@@ -181,14 +183,24 @@ impl<'sess> AttributeParser<'sess, Early> {
181183
sess,
182184
stage: Early { emit_errors },
183185
};
186+
let mut emit_lint = |lint| {
187+
crate::lints::emit_attribute_lint(&lint, sess);
188+
};
189+
if let Some(safety) = attr_safety {
190+
parser.check_attribute_safety(
191+
&attr_path,
192+
inner_span,
193+
safety,
194+
&mut emit_lint,
195+
target_node_id,
196+
)
197+
}
184198
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
185199
shared: SharedContext {
186200
cx: &mut parser,
187201
target_span,
188202
target_id: target_node_id,
189-
emit_lint: &mut |lint| {
190-
crate::lints::emit_attribute_lint(&lint, sess);
191-
},
203+
emit_lint: &mut emit_lint,
192204
},
193205
attr_span,
194206
inner_span,
@@ -288,6 +300,15 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
288300
// }
289301
ast::AttrKind::Normal(n) => {
290302
attr_paths.push(PathParser(Cow::Borrowed(&n.item.path)));
303+
let attr_path = AttrPath::from_ast(&n.item.path, lower_span);
304+
305+
self.check_attribute_safety(
306+
&attr_path,
307+
lower_span(n.item.span()),
308+
n.item.unsafety,
309+
&mut emit_lint,
310+
target_id,
311+
);
291312

292313
let parts =
293314
n.item.path.segments.iter().map(|seg| seg.ident.name).collect::<Vec<_>>();
@@ -301,7 +322,6 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
301322
) else {
302323
continue;
303324
};
304-
let path = parser.path();
305325
let args = parser.args();
306326
for accept in accepts {
307327
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
@@ -312,11 +332,11 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
312332
emit_lint: &mut emit_lint,
313333
},
314334
attr_span: lower_span(attr.span),
315-
inner_span: lower_span(attr.get_normal_item().span()),
335+
inner_span: lower_span(n.item.span()),
316336
attr_style: attr.style,
317337
parsed_description: ParsedDescription::Attribute,
318338
template: &accept.template,
319-
attr_path: path.get_attribute_path(),
339+
attr_path: attr_path.clone(),
320340
};
321341

322342
(accept.accept_fn)(&mut cx, args);
@@ -341,7 +361,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
341361
// );
342362

343363
attributes.push(Attribute::Unparsed(Box::new(AttrItem {
344-
path: AttrPath::from_ast(&n.item.path),
364+
path: attr_path.clone(),
345365
args: self.lower_attr_args(&n.item.args, lower_span),
346366
id: HashIgnoredAttrId { attr_id: attr.id },
347367
style: attr.style,

compiler/rustc_attr_parsing/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ mod interface;
9898
pub mod parser;
9999

100100
mod lints;
101+
mod safety;
101102
mod session_diagnostics;
102103
mod target_checking;
103104
pub mod validate_attr;

compiler/rustc_attr_parsing/src/lints.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,5 +98,17 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emi
9898
},
9999
)
100100
}
101+
&AttributeLintKind::UnsafeAttrOutsideUnsafe {
102+
attribute_name_span,
103+
sugg_spans: (left, right),
104+
} => lint_emitter.emit_node_span_lint(
105+
rustc_session::lint::builtin::UNSAFE_ATTR_OUTSIDE_UNSAFE,
106+
*id,
107+
*span,
108+
session_diagnostics::UnsafeAttrOutsideUnsafeLint {
109+
span: attribute_name_span,
110+
suggestion: session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion { left, right },
111+
},
112+
),
101113
}
102114
}
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
use rustc_ast::Safety;
2+
use rustc_feature::{AttributeSafety, BUILTIN_ATTRIBUTE_MAP};
3+
use rustc_hir::AttrPath;
4+
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
5+
use rustc_span::{Span, sym};
6+
7+
use crate::context::Stage;
8+
use crate::{AttributeParser, ShouldEmit};
9+
10+
impl<'sess, S: Stage> AttributeParser<'sess, S> {
11+
pub fn check_attribute_safety(
12+
&mut self,
13+
attr_path: &AttrPath,
14+
attr_span: Span,
15+
attr_safety: Safety,
16+
emit_lint: &mut impl FnMut(AttributeLint<S::Id>),
17+
target_id: S::Id,
18+
) {
19+
if matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
20+
return;
21+
}
22+
23+
let name = (attr_path.segments.len() == 1).then_some(attr_path.segments[0].name);
24+
if let Some(name) = name
25+
&& [sym::cfg_trace, sym::cfg_attr_trace].contains(&name)
26+
{
27+
return;
28+
}
29+
30+
// FIXME: We should retrieve this information from the attribute parsers instead of from `BUILTIN_ATTRIBUTE_MAP`
31+
let builtin_attr_info = name.and_then(|name| BUILTIN_ATTRIBUTE_MAP.get(&name));
32+
let builtin_attr_safety = builtin_attr_info.map(|x| x.safety);
33+
34+
match (builtin_attr_safety, attr_safety) {
35+
// - Unsafe builtin attribute
36+
// - User wrote `#[unsafe(..)]`, which is permitted on any edition
37+
(Some(AttributeSafety::Unsafe { .. }), Safety::Unsafe(..)) => {
38+
// OK
39+
}
40+
41+
// - Unsafe builtin attribute
42+
// - User did not write `#[unsafe(..)]`
43+
(Some(AttributeSafety::Unsafe { unsafe_since }), Safety::Default) => {
44+
let path_span = attr_path.span;
45+
46+
// If the `attr_item`'s span is not from a macro, then just suggest
47+
// wrapping it in `unsafe(...)`. Otherwise, we suggest putting the
48+
// `unsafe(`, `)` right after and right before the opening and closing
49+
// square bracket respectively.
50+
let diag_span = attr_span;
51+
52+
// Attributes can be safe in earlier editions, and become unsafe in later ones.
53+
//
54+
// Use the span of the attribute's name to determine the edition: the span of the
55+
// attribute as a whole may be inaccurate if it was emitted by a macro.
56+
//
57+
// See https://github.com/rust-lang/rust/issues/142182.
58+
let emit_error = match unsafe_since {
59+
None => true,
60+
Some(unsafe_since) => path_span.edition() >= unsafe_since,
61+
};
62+
63+
if emit_error {
64+
self.stage.emit_err(
65+
self.sess,
66+
crate::session_diagnostics::UnsafeAttrOutsideUnsafe {
67+
span: path_span,
68+
suggestion:
69+
crate::session_diagnostics::UnsafeAttrOutsideUnsafeSuggestion {
70+
left: diag_span.shrink_to_lo(),
71+
right: diag_span.shrink_to_hi(),
72+
},
73+
},
74+
);
75+
} else {
76+
emit_lint(AttributeLint {
77+
id: target_id,
78+
span: path_span,
79+
kind: AttributeLintKind::UnsafeAttrOutsideUnsafe {
80+
attribute_name_span: path_span,
81+
sugg_spans: (diag_span.shrink_to_lo(), diag_span.shrink_to_hi()),
82+
},
83+
})
84+
}
85+
}
86+
87+
// - Normal builtin attribute
88+
// - Writing `#[unsafe(..)]` is not permitted on normal builtin attributes
89+
(None | Some(AttributeSafety::Normal), Safety::Unsafe(unsafe_span)) => {
90+
self.stage.emit_err(
91+
self.sess,
92+
crate::session_diagnostics::InvalidAttrUnsafe {
93+
span: unsafe_span,
94+
name: attr_path.clone(),
95+
},
96+
);
97+
}
98+
99+
// - Normal builtin attribute
100+
// - No explicit `#[unsafe(..)]` written.
101+
(None | Some(AttributeSafety::Normal), Safety::Default) => {
102+
// OK
103+
}
104+
105+
(
106+
Some(AttributeSafety::Unsafe { .. } | AttributeSafety::Normal) | None,
107+
Safety::Safe(..),
108+
) => {
109+
self.sess.dcx().span_delayed_bug(
110+
attr_span,
111+
"`check_attribute_safety` does not expect `Safety::Safe` on attributes",
112+
);
113+
}
114+
}
115+
}
116+
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use std::num::IntErrorKind;
22

3-
use rustc_ast::{self as ast, Path};
3+
use rustc_ast::{self as ast};
44
use rustc_errors::codes::*;
55
use rustc_errors::{
66
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
@@ -790,7 +790,7 @@ pub(crate) struct InvalidAttrUnsafe {
790790
#[primary_span]
791791
#[label]
792792
pub span: Span,
793-
pub name: Path,
793+
pub name: AttrPath,
794794
}
795795

796796
#[derive(Diagnostic)]
@@ -803,6 +803,15 @@ pub(crate) struct UnsafeAttrOutsideUnsafe {
803803
pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
804804
}
805805

806+
#[derive(LintDiagnostic)]
807+
#[diag(attr_parsing_unsafe_attr_outside_unsafe)]
808+
pub(crate) struct UnsafeAttrOutsideUnsafeLint {
809+
#[label]
810+
pub span: Span,
811+
#[subdiagnostic]
812+
pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
813+
}
814+
806815
#[derive(Subdiagnostic)]
807816
#[multipart_suggestion(
808817
attr_parsing_unsafe_attr_outside_unsafe_suggestion,

0 commit comments

Comments
 (0)