Skip to content

Port #[path] to the new attribute parsing infrastructure #143344

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 2 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions compiler/rustc_attr_data_structures/src/attributes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -284,6 +284,9 @@ pub enum AttributeKind {
/// Represents `#[optimize(size|speed)]`
Optimize(OptimizeAttr, Span),

/// Represents `#[path]`
Path(Symbol, Span),

/// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
PubTransparent(Span),

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ impl AttributeKind {
Naked(..) => No,
NoMangle(..) => No,
Optimize(..) => No,
Path(..) => No,
PubTransparent(..) => Yes,
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_attr_parsing/src/attributes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ pub(crate) mod link_attrs;
pub(crate) mod lint_helpers;
pub(crate) mod loop_match;
pub(crate) mod must_use;
pub(crate) mod path;
pub(crate) mod repr;
pub(crate) mod rustc_internal;
pub(crate) mod semantics;
Expand Down
29 changes: 29 additions & 0 deletions compiler/rustc_attr_parsing/src/attributes/path.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use rustc_attr_data_structures::AttributeKind;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Symbol, sym};

use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;

pub(crate) struct PathParser;

impl<S: Stage> SingleAttributeParser<S> for PathParser {
const PATH: &[Symbol] = &[sym::path];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "file");

fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
let Some(nv) = args.name_value() else {
cx.expected_name_value(cx.attr_span, None);
return None;
};
let Some(path) = nv.value_as_str() else {
cx.expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
return None;
};

Some(AttributeKind::Path(path, cx.attr_span))
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_attr_parsing/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ use crate::attributes::link_attrs::{LinkNameParser, LinkSectionParser};
use crate::attributes::lint_helpers::{AsPtrParser, PubTransparentParser};
use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
use crate::attributes::must_use::MustUseParser;
use crate::attributes::path::PathParser as PathAttributeParser;
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed because this file contains an unrelated thing called PathParser already

use crate::attributes::repr::{AlignParser, ReprParser};
use crate::attributes::rustc_internal::{
RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
Expand Down Expand Up @@ -133,6 +134,7 @@ attribute_parsers!(
Single<MustUseParser>,
Single<NoMangleParser>,
Single<OptimizeParser>,
Single<PathAttributeParser>,
Single<PubTransparentParser>,
Single<RustcForceInlineParser>,
Single<RustcLayoutScalarValidRangeEnd>,
Expand Down
60 changes: 30 additions & 30 deletions compiler/rustc_parse/src/validate_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,36 @@ pub fn check_builtin_meta_item(
deny_unsafety: bool,
) {
if !is_attr_template_compatible(&template, &meta.kind) {
// attrs with new parsers are locally validated so excluded here
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This move is in a separate commit.
It is needed because

pub fn emit_fatal_malformed_builtin_attribute(
also calls emit_malformed_attribute and is not using the new parser (yet?), so should still emit the lint even for parsed attributes

if matches!(
name,
sym::inline
| sym::may_dangle
| sym::rustc_as_ptr
| sym::rustc_pub_transparent
| sym::rustc_const_stable_indirect
| sym::rustc_force_inline
| sym::rustc_confusables
| sym::rustc_skip_during_method_dispatch
| sym::repr
| sym::align
| sym::deprecated
| sym::optimize
| sym::cold
| sym::naked
| sym::no_mangle
| sym::must_use
| sym::track_caller
| sym::link_name
| sym::export_name
| sym::rustc_macro_transparency
| sym::link_section
| sym::rustc_layout_scalar_valid_range_start
| sym::rustc_layout_scalar_valid_range_end
| sym::path
) {
return;
}
emit_malformed_attribute(psess, style, meta.span, name, template);
}

Expand All @@ -282,36 +312,6 @@ fn emit_malformed_attribute(
name: Symbol,
template: AttributeTemplate,
) {
// attrs with new parsers are locally validated so excluded here
if matches!(
name,
sym::inline
| sym::may_dangle
| sym::rustc_as_ptr
| sym::rustc_pub_transparent
| sym::rustc_const_stable_indirect
| sym::rustc_force_inline
| sym::rustc_confusables
| sym::rustc_skip_during_method_dispatch
| sym::repr
| sym::align
| sym::deprecated
| sym::optimize
| sym::cold
| sym::naked
| sym::no_mangle
| sym::must_use
| sym::track_caller
| sym::link_name
| sym::export_name
| sym::rustc_macro_transparency
| sym::link_section
| sym::rustc_layout_scalar_valid_range_start
| sym::rustc_layout_scalar_valid_range_end
) {
return;
}

// Some of previously accepted forms were used in practice,
// report them as warnings for now.
let should_warn =
Expand Down
38 changes: 31 additions & 7 deletions compiler/rustc_passes/src/check_attr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
Attribute::Parsed(AttributeKind::Naked(attr_span)) => {
self.check_naked(hir_id, *attr_span, span, target)
}
Attribute::Parsed(AttributeKind::Path(_, attr_span)) => {
self.check_generic_attr(hir_id, sym::path, *attr_span, target, Target::Mod)
}
Attribute::Parsed(AttributeKind::TrackCaller(attr_span)) => {
self.check_track_caller(hir_id, *attr_span, attrs, span, target)
}
Expand Down Expand Up @@ -294,16 +297,15 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::macro_use, ..] | [sym::macro_escape, ..] => {
self.check_macro_use(hir_id, attr, target)
}
[sym::path, ..] => self.check_generic_attr(hir_id, attr, target, Target::Mod),
[sym::macro_export, ..] => self.check_macro_export(hir_id, attr, target),
[sym::ignore, ..] | [sym::should_panic, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Fn)
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn)
}
[sym::automatically_derived, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Impl)
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Impl)
}
[sym::no_implicit_prelude, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Mod)
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Mod)
}
[sym::proc_macro, ..] => {
self.check_proc_macro(hir_id, target, ProcMacroKind::FunctionLike)
Expand All @@ -312,7 +314,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
self.check_proc_macro(hir_id, target, ProcMacroKind::Attribute);
}
[sym::proc_macro_derive, ..] => {
self.check_generic_attr(hir_id, attr, target, Target::Fn);
self.check_generic_attr_unparsed(hir_id, attr, target, Target::Fn);
self.check_proc_macro(hir_id, target, ProcMacroKind::Derive)
}
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
Expand Down Expand Up @@ -621,7 +623,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

fn check_generic_attr(
fn check_generic_attr_unparsed(
&self,
hir_id: HirId,
attr: &Attribute,
Expand All @@ -644,6 +646,27 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}

fn check_generic_attr(
&self,
hir_id: HirId,
attr_name: Symbol,
attr_span: Span,
target: Target,
allowed_target: Target,
) {
if target != allowed_target {
self.tcx.emit_node_span_lint(
UNUSED_ATTRIBUTES,
hir_id,
attr_span,
errors::OnlyHasEffectOn {
attr_name: attr_name.to_string(),
target_name: allowed_target.name().replace(' ', "_"),
},
);
}
}

/// Checks if `#[naked]` is applied to a function definition.
fn check_naked(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
match target {
Expand Down Expand Up @@ -2804,7 +2827,6 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
// resolution for the attribute macro error.
const ATTRS_TO_CHECK: &[Symbol] = &[
sym::macro_export,
sym::path,
sym::automatically_derived,
sym::rustc_main,
sym::derive,
Expand All @@ -2822,6 +2844,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
(attr.span(), *a)
} else if let Attribute::Parsed(AttributeKind::Repr(r)) = attr {
(r.first().unwrap().1, sym::repr)
} else if let Attribute::Parsed(AttributeKind::Path(.., span)) = attr {
(*span, sym::path)
} else {
continue;
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -121,21 +121,6 @@ LL - #![rustc_main]
LL + #[rustc_main]
|

error: `path` attribute cannot be used at crate level
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1
|
LL | #![path = "3800"]
| ^^^^^^^^^^^^^^^^^
...
LL | mod inline {
| ------ the inner attribute doesn't annotate this module
|
help: perhaps you meant to use an outer attribute
|
LL - #![path = "3800"]
LL + #[path = "3800"]
|

error: `automatically_derived` attribute cannot be used at crate level
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:23:1
|
Expand Down Expand Up @@ -166,6 +151,21 @@ LL - #![repr()]
LL + #[repr()]
|

error: `path` attribute cannot be used at crate level
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:21:1
|
LL | #![path = "3800"]
| ^^^^^^^^^^^^^^^^^
...
LL | mod inline {
| ------ the inner attribute doesn't annotate this module
|
help: perhaps you meant to use an outer attribute
|
LL - #![path = "3800"]
LL + #[path = "3800"]
|

error[E0518]: attribute should be applied to function or closure
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:42:17
|
Expand Down
26 changes: 13 additions & 13 deletions tests/ui/lint/unused/unused-attr-duplicate.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,6 @@ note: attribute also specified here
LL | #[macro_use]
| ^^^^^^^^^^^^

error: unused attribute
--> $DIR/unused-attr-duplicate.rs:47:1
|
LL | #[path = "bar.rs"]
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:46:1
|
LL | #[path = "auxiliary/lint_unused_extern_crate.rs"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

error: unused attribute
--> $DIR/unused-attr-duplicate.rs:53:1
|
Expand Down Expand Up @@ -189,6 +176,19 @@ note: attribute also specified here
LL | #[macro_export]
| ^^^^^^^^^^^^^^^

error: unused attribute
--> $DIR/unused-attr-duplicate.rs:47:1
|
LL | #[path = "bar.rs"]
| ^^^^^^^^^^^^^^^^^^ help: remove this attribute
|
note: attribute also specified here
--> $DIR/unused-attr-duplicate.rs:46:1
|
LL | #[path = "auxiliary/lint_unused_extern_crate.rs"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!

error: unused attribute
--> $DIR/unused-attr-duplicate.rs:60:1
|
Expand Down
12 changes: 6 additions & 6 deletions tests/ui/lint/unused/unused-attr-macro-rules.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,17 @@ note: the lint level is defined here
LL | #![deny(unused_attributes)]
| ^^^^^^^^^^^^^^^^^

error: `#[path]` only has an effect on modules
--> $DIR/unused-attr-macro-rules.rs:8:1
|
LL | #[path="foo"]
| ^^^^^^^^^^^^^

error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
--> $DIR/unused-attr-macro-rules.rs:9:1
|
LL | #[recursion_limit="1"]
| ^^^^^^^^^^^^^^^^^^^^^^

error: `#[path]` only has an effect on modules
--> $DIR/unused-attr-macro-rules.rs:8:1
|
LL | #[path="foo"]
| ^^^^^^^^^^^^^

error: aborting due to 3 previous errors

1 change: 1 addition & 0 deletions tests/ui/resolve/path-attr-in-const-block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,6 @@ fn main() {
const {
#![path = foo!()]
//~^ ERROR: cannot find macro `foo` in this scope
//~| ERROR malformed `path` attribute input
}
}
12 changes: 11 additions & 1 deletion tests/ui/resolve/path-attr-in-const-block.stderr
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,15 @@ error: cannot find macro `foo` in this scope
LL | #![path = foo!()]
| ^^^

error: aborting due to 1 previous error
error[E0539]: malformed `path` attribute input
--> $DIR/path-attr-in-const-block.rs:6:9
|
LL | #![path = foo!()]
| ^^^^^^^^^^------^
| | |
| | expected a string literal here
| help: must be of the form: `#[path = "file"]`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0539`.
Loading