Skip to content

Commit 1a56b22

Browse files
Move attribute validation from rustc_parse to rustc_attr_parsing
Signed-off-by: Jonathan Brouwer <[email protected]>
1 parent e4ea1c8 commit 1a56b22

File tree

18 files changed

+382
-390
lines changed

18 files changed

+382
-390
lines changed

Cargo.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3275,7 +3275,6 @@ dependencies = [
32753275
"rustc_feature",
32763276
"rustc_fluent_macro",
32773277
"rustc_macros",
3278-
"rustc_parse",
32793278
"rustc_session",
32803279
"rustc_span",
32813280
"rustc_target",
@@ -3321,6 +3320,7 @@ dependencies = [
33213320
"rustc_hir",
33223321
"rustc_lexer",
33233322
"rustc_macros",
3323+
"rustc_parse",
33243324
"rustc_session",
33253325
"rustc_span",
33263326
"thin-vec",

compiler/rustc_ast_passes/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ rustc_errors = { path = "../rustc_errors" }
1515
rustc_feature = { path = "../rustc_feature" }
1616
rustc_fluent_macro = { path = "../rustc_fluent_macro" }
1717
rustc_macros = { path = "../rustc_macros" }
18-
rustc_parse = { path = "../rustc_parse" }
1918
rustc_session = { path = "../rustc_session" }
2019
rustc_span = { path = "../rustc_span" }
2120
rustc_target = { path = "../rustc_target" }

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@ use rustc_ast_pretty::pprust::{self, State};
2929
use rustc_data_structures::fx::FxIndexMap;
3030
use rustc_errors::DiagCtxtHandle;
3131
use rustc_feature::Features;
32-
use rustc_parse::validate_attr;
3332
use rustc_session::Session;
3433
use rustc_session::lint::builtin::{
3534
DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, MISSING_UNSAFE_ON_EXTERN,
@@ -928,10 +927,6 @@ fn validate_generic_param_order(dcx: DiagCtxtHandle<'_>, generics: &[GenericPara
928927
}
929928

930929
impl<'a> Visitor<'a> for AstValidator<'a> {
931-
fn visit_attribute(&mut self, attr: &Attribute) {
932-
validate_attr::check_attr(&self.sess.psess, attr, self.lint_node_id);
933-
}
934-
935930
fn visit_ty(&mut self, ty: &'a Ty) {
936931
self.visit_ty_common(ty);
937932
self.walk_ty(ty)

compiler/rustc_attr_data_structures/src/lints.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ pub enum AttributeLintKind {
1313
UnusedDuplicate { this: Span, other: Span, warning: bool },
1414
IllFormedAttributeInput { suggestions: Vec<String> },
1515
EmptyAttribute { first_span: Span },
16+
UnsafeAttrOutsideUnsafe { attribute_name_span: Span, sugg_spans: (Span, Span) },
1617
}

compiler/rustc_attr_parsing/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ rustc_fluent_macro = { path = "../rustc_fluent_macro" }
1515
rustc_hir = { path = "../rustc_hir" }
1616
rustc_lexer = { path = "../rustc_lexer" }
1717
rustc_macros = { path = "../rustc_macros" }
18+
rustc_parse = { path = "../rustc_parse" }
1819
rustc_session = { path = "../rustc_session" }
1920
rustc_span = { path = "../rustc_span" }
2021
thin-vec = "0.2.12"

compiler/rustc_attr_parsing/messages.ftl

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,3 +161,12 @@ attr_parsing_unused_multiple =
161161
162162
-attr_parsing_previously_accepted =
163163
this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
164+
165+
attr_parsing_unsafe_attr_outside_unsafe = unsafe attribute used without unsafe
166+
.label = usage of unsafe attribute
167+
attr_parsing_unsafe_attr_outside_unsafe_suggestion = wrap the attribute in `unsafe(...)`
168+
169+
attr_parsing_invalid_attr_unsafe = `{$name}` is not an unsafe attribute
170+
.label = this is not an unsafe attribute
171+
.suggestion = remove the `unsafe(...)`
172+
.note = extraneous unsafe is not allowed in attributes

compiler/rustc_attr_parsing/src/context.rs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -705,6 +705,22 @@ impl<'sess> AttributeParser<'sess, Early> {
705705
};
706706
parse_fn(&mut cx, args)
707707
}
708+
709+
/// Returns whether the attribute is valid
710+
pub fn validate_attribute_early(
711+
sess: &'sess Session,
712+
attr: &ast::Attribute,
713+
target_node_id: NodeId,
714+
) -> bool {
715+
let parser = Self {
716+
features: None,
717+
tools: Vec::new(),
718+
parse_only: None,
719+
sess,
720+
stage: Early { emit_errors: ShouldEmit::ErrorsAndLints },
721+
};
722+
parser.validate_attribute(attr, target_node_id, &mut |_| {}, true)
723+
}
708724
}
709725

710726
impl<'sess, S: Stage> AttributeParser<'sess, S> {
@@ -798,12 +814,14 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
798814
ast::AttrKind::Normal(n) => {
799815
attr_paths.push(PathParser::Ast(&n.item.path));
800816

817+
// Parse attribute using new infra
801818
let parser = MetaItemParser::from_attr(n, self.dcx());
802819
let path = parser.path();
803820
let args = parser.args();
804821
let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
805822

806823
if let Some(accepts) = S::parsers().0.get(parts.as_slice()) {
824+
self.validate_attribute(attr, target_id, &mut emit_lint, true);
807825
for (template, accept) in accepts {
808826
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
809827
shared: SharedContext {
@@ -834,7 +852,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
834852
// // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
835853
// "attribute {path} wasn't parsed and isn't a know tool attribute",
836854
// );
837-
855+
self.validate_attribute(attr, target_id, &mut emit_lint, false);
838856
attributes.push(Attribute::Unparsed(Box::new(AttrItem {
839857
path: AttrPath::from_ast(&n.item.path),
840858
args: self.lower_attr_args(&n.item.args, lower_span),

compiler/rustc_attr_parsing/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ pub(crate) mod context;
8989
mod lints;
9090
pub mod parser;
9191
mod session_diagnostics;
92+
mod validate_attr;
9293

9394
pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr};
9495
pub use attributes::cfg_old::*;
@@ -97,5 +98,8 @@ pub use attributes::util::{
9798
};
9899
pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit};
99100
pub use lints::emit_attribute_lint;
101+
pub use validate_attr::{
102+
check_attribute_safety, check_builtin_meta_item, emit_fatal_malformed_builtin_attribute,
103+
};
100104

101105
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

compiler/rustc_attr_parsing/src/lints.rs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use rustc_errors::{DiagArgValue, LintEmitter};
33
use rustc_hir::HirId;
44

55
use crate::session_diagnostics;
6+
use crate::session_diagnostics::{UnsafeAttrOutsideUnsafeLint, UnsafeAttrOutsideUnsafeSuggestion};
67

78
pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emitter: L) {
89
let AttributeLint { id, span, kind } = lint;
@@ -34,5 +35,19 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
3435
*first_span,
3536
session_diagnostics::EmptyAttributeList { attr_span: *first_span },
3637
),
38+
&AttributeLintKind::UnsafeAttrOutsideUnsafe { attribute_name_span, sugg_spans } => {
39+
lint_emitter.emit_node_span_lint(
40+
rustc_session::lint::builtin::UNSAFE_ATTR_OUTSIDE_UNSAFE,
41+
*id,
42+
*span,
43+
UnsafeAttrOutsideUnsafeLint {
44+
span: attribute_name_span,
45+
suggestion: UnsafeAttrOutsideUnsafeSuggestion {
46+
left: sugg_spans.0.shrink_to_lo(),
47+
right: sugg_spans.1.shrink_to_hi(),
48+
},
49+
},
50+
)
51+
}
3752
}
3853
}

compiler/rustc_attr_parsing/src/session_diagnostics.rs

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

33
use rustc_ast as ast;
4+
use rustc_ast::Path;
45
use rustc_errors::codes::*;
56
use rustc_errors::{
67
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
@@ -701,3 +702,44 @@ impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AttributeParseError {
701702
diag
702703
}
703704
}
705+
706+
#[derive(Diagnostic)]
707+
#[diag(attr_parsing_unsafe_attr_outside_unsafe)]
708+
pub(crate) struct UnsafeAttrOutsideUnsafe {
709+
#[primary_span]
710+
#[label]
711+
pub span: Span,
712+
#[subdiagnostic]
713+
pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
714+
}
715+
716+
#[derive(Subdiagnostic)]
717+
#[multipart_suggestion(
718+
attr_parsing_unsafe_attr_outside_unsafe_suggestion,
719+
applicability = "machine-applicable"
720+
)]
721+
pub(crate) struct UnsafeAttrOutsideUnsafeSuggestion {
722+
#[suggestion_part(code = "unsafe(")]
723+
pub left: Span,
724+
#[suggestion_part(code = ")")]
725+
pub right: Span,
726+
}
727+
728+
#[derive(Diagnostic)]
729+
#[diag(attr_parsing_invalid_attr_unsafe)]
730+
#[note]
731+
pub(crate) struct InvalidAttrUnsafe {
732+
#[primary_span]
733+
#[label]
734+
pub span: Span,
735+
pub name: Path,
736+
}
737+
738+
#[derive(LintDiagnostic)]
739+
#[diag(attr_parsing_unsafe_attr_outside_unsafe)]
740+
pub(crate) struct UnsafeAttrOutsideUnsafeLint {
741+
#[label]
742+
pub span: Span,
743+
#[subdiagnostic]
744+
pub suggestion: UnsafeAttrOutsideUnsafeSuggestion,
745+
}

0 commit comments

Comments
 (0)