about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_attr_data_structures/src/attributes.rs3
-rw-r--r--compiler/rustc_attr_data_structures/src/encode_cross_crate.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/mod.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/path.rs29
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs2
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs72
-rw-r--r--compiler/rustc_passes/src/check_attr.rs6
-rw-r--r--tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr30
-rw-r--r--tests/ui/lint/unused/unused-attr-duplicate.stderr26
-rw-r--r--tests/ui/lint/unused/unused-attr-macro-rules.stderr12
-rw-r--r--tests/ui/resolve/path-attr-in-const-block.rs1
-rw-r--r--tests/ui/resolve/path-attr-in-const-block.stderr12
12 files changed, 123 insertions, 72 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs
index ba62be676d4..84fb4f363d4 100644
--- a/compiler/rustc_attr_data_structures/src/attributes.rs
+++ b/compiler/rustc_attr_data_structures/src/attributes.rs
@@ -298,6 +298,9 @@ pub enum AttributeKind {
     /// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
     PassByValue(Span),
 
+    /// Represents `#[path]`
+    Path(Symbol, Span),
+
     /// Represents `#[rustc_pub_transparent]` (used by the `repr_transparent_external_private_fields` lint).
     PubTransparent(Span),
 
diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
index b109ebbf47b..a6ae49d2808 100644
--- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
+++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
@@ -40,6 +40,7 @@ impl AttributeKind {
             NonExhaustive(..) => Yes,
             Optimize(..) => No,
             PassByValue(..) => Yes,
+            Path(..) => No,
             PubTransparent(..) => Yes,
             Repr { .. } => No,
             RustcLayoutScalarValidRangeEnd(..) => Yes,
diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs
index 55fbb825466..ba7572434df 100644
--- a/compiler/rustc_attr_parsing/src/attributes/mod.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs
@@ -37,6 +37,7 @@ pub(crate) mod loop_match;
 pub(crate) mod must_use;
 pub(crate) mod no_implicit_prelude;
 pub(crate) mod non_exhaustive;
+pub(crate) mod path;
 pub(crate) mod repr;
 pub(crate) mod rustc_internal;
 pub(crate) mod semantics;
diff --git a/compiler/rustc_attr_parsing/src/attributes/path.rs b/compiler/rustc_attr_parsing/src/attributes/path.rs
new file mode 100644
index 00000000000..0dfbc9a9aa8
--- /dev/null
+++ b/compiler/rustc_attr_parsing/src/attributes/path.rs
@@ -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))
+    }
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index bcd7b024a9e..939f4a6fde7 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -28,6 +28,7 @@ use crate::attributes::loop_match::{ConstContinueParser, LoopMatchParser};
 use crate::attributes::must_use::MustUseParser;
 use crate::attributes::no_implicit_prelude::NoImplicitPreludeParser;
 use crate::attributes::non_exhaustive::NonExhaustiveParser;
+use crate::attributes::path::PathParser as PathAttributeParser;
 use crate::attributes::repr::{AlignParser, ReprParser};
 use crate::attributes::rustc_internal::{
     RustcLayoutScalarValidRangeEnd, RustcLayoutScalarValidRangeStart,
@@ -133,6 +134,7 @@ attribute_parsers!(
         Single<LinkSectionParser>,
         Single<MustUseParser>,
         Single<OptimizeParser>,
+        Single<PathAttributeParser>,
         Single<RustcForceInlineParser>,
         Single<RustcLayoutScalarValidRangeEnd>,
         Single<RustcLayoutScalarValidRangeStart>,
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 8fdc06ee463..67b68e77d2b 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -267,6 +267,42 @@ 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
+        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::rustc_pass_by_value
+                | sym::repr
+                | sym::align
+                | sym::deprecated
+                | sym::optimize
+                | sym::cold
+                | sym::target_feature
+                | sym::rustc_allow_const_fn_unstable
+                | sym::naked
+                | sym::no_mangle
+                | sym::non_exhaustive
+                | sym::path
+                | sym::ignore
+                | 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::no_implicit_prelude
+        ) {
+            return;
+        }
         emit_malformed_attribute(psess, style, meta.span, name, template);
     }
 
@@ -282,42 +318,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::rustc_pass_by_value
-            | sym::repr
-            | sym::align
-            | sym::deprecated
-            | sym::optimize
-            | sym::cold
-            | sym::target_feature
-            | sym::rustc_allow_const_fn_unstable
-            | sym::naked
-            | sym::no_mangle
-            | sym::non_exhaustive
-            | sym::ignore
-            | 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::no_implicit_prelude
-    ) {
-        return;
-    }
-
     // Some of previously accepted forms were used in practice,
     // report them as warnings for now.
     let should_warn = |name| matches!(name, sym::doc | sym::link | sym::test | sym::bench);
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index b8f1ec7ca93..fe9f80beaed 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -191,6 +191,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         target,
                         Target::Mod,
                     ),
+                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)
                 }
@@ -2797,7 +2800,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,
@@ -2819,6 +2821,8 @@ fn check_invalid_crate_level_attr(tcx: TyCtxt<'_>, attrs: &[Attribute]) {
         }) = attr
         {
             (*first_attr_span, sym::repr)
+        } else if let Attribute::Parsed(AttributeKind::Path(.., span)) = attr {
+            (*span, sym::path)
         } else {
             continue;
         };
diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
index 1620bf72922..49c666f498f 100644
--- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
+++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs-error.stderr
@@ -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
    |
@@ -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
    |
diff --git a/tests/ui/lint/unused/unused-attr-duplicate.stderr b/tests/ui/lint/unused/unused-attr-duplicate.stderr
index 275eb056305..2310c12c80b 100644
--- a/tests/ui/lint/unused/unused-attr-duplicate.stderr
+++ b/tests/ui/lint/unused/unused-attr-duplicate.stderr
@@ -28,19 +28,6 @@ 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:55:1
    |
 LL | #[should_panic(expected = "values don't match")]
@@ -154,6 +141,19 @@ 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:53:1
    |
 LL | #[ignore = "some text"]
diff --git a/tests/ui/lint/unused/unused-attr-macro-rules.stderr b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
index e3ca90d9acd..4698e381425 100644
--- a/tests/ui/lint/unused/unused-attr-macro-rules.stderr
+++ b/tests/ui/lint/unused/unused-attr-macro-rules.stderr
@@ -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
 
diff --git a/tests/ui/resolve/path-attr-in-const-block.rs b/tests/ui/resolve/path-attr-in-const-block.rs
index 076511d26d6..69be65bda3f 100644
--- a/tests/ui/resolve/path-attr-in-const-block.rs
+++ b/tests/ui/resolve/path-attr-in-const-block.rs
@@ -5,5 +5,6 @@ fn main() {
     const {
         #![path = foo!()]
         //~^ ERROR: cannot find macro `foo` in this scope
+        //~| ERROR malformed `path` attribute input
     }
 }
diff --git a/tests/ui/resolve/path-attr-in-const-block.stderr b/tests/ui/resolve/path-attr-in-const-block.stderr
index 8f9e58157c8..0b5942a287d 100644
--- a/tests/ui/resolve/path-attr-in-const-block.stderr
+++ b/tests/ui/resolve/path-attr-in-const-block.stderr
@@ -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`.