rust icon indicating copy to clipboard operation
rust copied to clipboard

Hir attributes

Open jdonszelmann opened this issue 1 year ago • 8 comments

This PR needs some explanation, it's somewhat large.

  • This is step one as described in https://github.com/rust-lang/compiler-team/issues/796. I've added a new hir::Attribute which is a lowered version of ast::Attribute. Right now, this has few concrete effects, however every place that after this PR parses a hir::Attribute should later get a pre-parsed attribute as described in https://github.com/rust-lang/compiler-team/issues/796 and transitively https://github.com/rust-lang/rust/issues/131229.
  • I've done my best to split up this change into smaller commits to make it reviewable:
    • https://github.com/rust-lang/rust/commit/b5fd0f643e2325b3f9c6599084896aa434ac64bf modified ast::Attribute because some parts are not necessary anymore. They used to model hir-specfic parts of attributes even though they were part of the ast
    • https://github.com/rust-lang/rust/commit/04307d487ad7632de18e7084393d6babae8c088c adds an extension trait AttributeExt which is implemented for both ast::Attribute and hir::Atribute. This makes hir::Attributes mostly compatible with code that used to parse ast::Attribute. Some day I hope I can remove this trait, once parsing happens in a central location but for now it's a useful abstraction
    • https://github.com/rust-lang/rust/commit/46e250591c1901591287f626c574134c652d0ec3 adds a new hir::Attribute.
    • https://github.com/rust-lang/rust/commit/1bfc0b57046d1a0e4ab39b64538259d74fde441f is the largest commit, but honestly the most boring. This changes over all the places in the compiler that used to refer to ast::Attribute but should really refer to hir::Attribute. This is mostly just fixing up imports.
    • https://github.com/rust-lang/rust/commit/d2dcaaa286170d5651d550333fb554fea504badc changes over code that used to hash ast::Attribute. This also removes some assertions that were necessary because the type ast::Attribute did not model the fact that certain values should not exist anymore while hashing.
    • https://github.com/rust-lang/rust/commit/ac9d9fcdde06aaba2a4147300cc935e75cee23c5 pretty printing had to slightly change because we're dealing with hir::Attribute now
    • Then, three commits edit rustdoc, clippy and rustfmt to use hir::Attribute. The one for clippy is largest, and was made in a call together with @xFrednet who signed off on it.
    • Finally, some tests needed fixing. First, the hir stats changed slightly. Mostly because Attribute didn't used to be in there. Another test also changed, but it seems for the better. I'm unsure what I did to change it but I looked at it with Fred and we agreed that the new result is actually preferable.

Finally, I may have broken intra-doc links with something. As far as I know, this is nothing fundamental, just a dumb mistake somewhere. I'm still debugging that, hence this is a draft PR but in fairness all the complicated logic is done.

r? @oli-obk

jdonszelmann avatar Oct 17 '24 00:10 jdonszelmann

Could not assign reviewer from: oli-obk. User(s) oli-obk are either the PR author, already assigned, or on vacation, and there are no other candidates. Use r? to specify someone else to assign.

rustbot avatar Oct 17 '24 00:10 rustbot

r? @fee1-dead

rustbot has assigned @fee1-dead. They will have a look at your PR within the next two weeks and either review your PR or reassign to another reviewer.

Use r? to explicitly pick a reviewer

rustbot avatar Oct 17 '24 00:10 rustbot

The job mingw-check-tidy failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)

COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/

# NOTE: intentionally uses python2 for x.py so we can test it still works.
# validate-toolstate only runs in our CI, so it's ok for it to only support python3.
ENV SCRIPT TIDY_PRINT_DIFF=1 python2.7 ../x.py test \
           --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint,cpp:fmt
# This file is autogenerated by pip-compile with Python 3.10
# by the following command:
#
#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
---
#13 2.834 Building wheels for collected packages: reuse
#13 2.835   Building wheel for reuse (pyproject.toml): started
#13 3.090   Building wheel for reuse (pyproject.toml): finished with status 'done'
#13 3.091   Created wheel for reuse: filename=reuse-4.0.3-cp310-cp310-manylinux_2_35_x86_64.whl size=132720 sha256=026f3bb0f1aa8090b861fd0a0939cb1a782396d84c8aab7875096557d637a0f6
#13 3.091   Stored in directory: /tmp/pip-ephem-wheel-cache-mynjpwmc/wheels/3d/8d/0a/e0fc6aba4494b28a967ab5eaf951c121d9c677958714e34532
#13 3.094 Installing collected packages: boolean-py, binaryornot, tomlkit, reuse, python-debian, markupsafe, license-expression, jinja2, chardet, attrs
#13 3.507 Successfully installed attrs-23.2.0 binaryornot-0.4.4 boolean-py-4.0 chardet-5.2.0 jinja2-3.1.4 license-expression-30.3.0 markupsafe-2.1.5 python-debian-0.1.49 reuse-4.0.3 tomlkit-0.13.0
#13 3.507 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#13 4.067 Collecting virtualenv
#13 4.067 Collecting virtualenv
#13 4.108   Downloading virtualenv-20.26.6-py3-none-any.whl (6.0 MB)
#13 4.185      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 6.0/6.0 MB 81.1 MB/s eta 0:00:00
#13 4.227 Collecting distlib<1,>=0.3.7
#13 4.231   Downloading distlib-0.3.9-py2.py3-none-any.whl (468 kB)
#13 4.238      ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 469.0/469.0 KB 94.2 MB/s eta 0:00:00
#13 4.273 Collecting filelock<4,>=3.12.2
#13 4.277   Downloading filelock-3.16.1-py3-none-any.whl (16 kB)
#13 4.311 Collecting platformdirs<5,>=3.9.1
#13 4.315   Downloading platformdirs-4.3.6-py3-none-any.whl (18 kB)
#13 4.396 Installing collected packages: distlib, platformdirs, filelock, virtualenv
#13 4.591 Successfully installed distlib-0.3.9 filelock-3.16.1 platformdirs-4.3.6 virtualenv-20.26.6
#13 DONE 4.7s

#14 [7/8] COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
#14 DONE 0.0s
---
DirectMap4k:      204736 kB
DirectMap2M:     8183808 kB
DirectMap1G:    10485760 kB
##[endgroup]
Executing TIDY_PRINT_DIFF=1 python2.7 ../x.py test            --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint,cpp:fmt
+ TIDY_PRINT_DIFF=1 python2.7 ../x.py test --stage 0 src/tools/tidy tidyselftest --extra-checks=py:lint,cpp:fmt
    Finished `dev` profile [unoptimized] target(s) in 0.04s
##[endgroup]
downloading https://static.rust-lang.org/dist/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz
extracting /checkout/obj/build/cache/2024-10-16/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz to /checkout/obj/build/x86_64-unknown-linux-gnu/rustfmt

rust-log-analyzer avatar Oct 17 '24 00:10 rust-log-analyzer

The job x86_64-gnu-llvm-18 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
------
 > importing cache manifest from ghcr.io/rust-lang/rust-ci-cache:c32c805632780b5c1de330e3f44561b336c2efe163bc0990acb392390157a8e1d9f855d75914a239aa40c49d77f4a837247d05d2f8d46f554b98e1f46712a3e3:
------
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Starting the server...
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--set', 'change-id=99999999', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
  Downloaded boml v0.3.1
   Compiling boml v0.3.1
   Compiling y v0.1.0 (/checkout/compiler/rustc_codegen_gcc/build_system)
    Finished `release` profile [optimized] target(s) in 3.75s
     Running `/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-codegen/x86_64-unknown-linux-gnu/release/y test --use-system-gcc --use-backend gcc --out-dir /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/cg_gcc --release --mini-tests --std-tests`
Using system GCC
[BUILD] example
[AOT] mini_core_hello_world
/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/cg_gcc/mini_core_hello_world
abc
---
---- [ui] tests/rustdoc-ui/include-str-bare-urls.rs stdout ----

error: ui test compiled successfully!
status: exit status: 0
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustdoc" "/checkout/tests/rustdoc-ui/include-str-bare-urls.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-ui/include-str-bare-urls" "-A" "internal_features" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-ui/include-str-bare-urls/auxiliary"
stderr: none


---- [ui] tests/rustdoc-ui/intra-doc/warning.rs stdout ----
---
To only update this specific test, also pass `--test-args intra-doc/warning.rs`

error: 1 errors occurred comparing output.
status: exit status: 0
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustdoc" "/checkout/tests/rustdoc-ui/intra-doc/warning.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-ui/intra-doc/warning" "-A" "internal_features" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-ui/intra-doc/warning/auxiliary"
--- stderr -------------------------------
warning: unresolved link to `Foo::baz`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:3:23
   |
   |
LL |        //! Test with [Foo::baz], [Bar::foo], ...
   |                       ^^^^^^^^ the struct `Foo` has no field or associated item named `baz`
   = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default

warning: unresolved link to `Bar::foo`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:3:35
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:3:35
   |
LL |        //! Test with [Foo::baz], [Bar::foo], ...
   |                                   ^^^^^^^^ no item named `Bar` in scope

warning: unresolved link to `Uniooon::X`
   |
   |
LL |      //! , [Uniooon::X] and [Qux::Z].
   |             ^^^^^^^^^^ no item named `Uniooon` in scope

warning: unresolved link to `Qux::Z`
   |
   |
LL |      //! , [Uniooon::X] and [Qux::Z].
   |                              ^^^^^^ no item named `Qux` in scope

warning: unresolved link to `Uniooon::X`
   |
   |
LL |       //! , [Uniooon::X] and [Qux::Z].
   |              ^^^^^^^^^^ no item named `Uniooon` in scope

warning: unresolved link to `Qux::Z`
   |
   |
LL |       //! , [Uniooon::X] and [Qux::Z].
   |                               ^^^^^^ no item named `Qux` in scope
warning: unresolved link to `Qux:Y`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:14:13
   |
   |
LL |        /// [Qux:Y]
   |             ^^^^^ no item named `Qux:Y` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `BarA`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:21:10
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:21:10
   |
LL | /// bar [BarA] bar //~ WARNING `BarA`
   |          ^^^^ no item named `BarA` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `BarB`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:27:9
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:27:9
   |
LL |  * bar [BarB] bar //~ WARNING `BarB`
   |         ^^^^ no item named `BarB` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `BarC`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:34:6
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:34:6
   |
LL | bar [BarC] bar //~ WARNING `BarC`
   |      ^^^^ no item named `BarC` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `BarD`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:45:9
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:45:9
   |
LL | #[doc = "Foo\nbar [BarD] bar\nbaz"] //~ WARNING `BarD`
   |
   = note: the link appears in this line:
           
           
           bar [BarD] bar
   = note: no item named `BarD` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `BarF`
warning: unresolved link to `BarF`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:54:4
   |
LL | f!("Foo\nbar [BarF] bar\nbaz"); //~ WARNING `BarF`
   |
   = note: the link appears in this line:
           
           
           bar [BarF] bar
   = note: no item named `BarF` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `error`
warning: unresolved link to `error`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:58:30
   |
LL |  * time to introduce a link [error]*/ //~ WARNING `error`
   |
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `error`
warning: unresolved link to `error`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:64:30
   |
LL |  * time to introduce a link [error] //~ WARNING `error`
   |
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `error`
warning: unresolved link to `error`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:68:9
   |
LL | #[doc = "single line [error]"] //~ WARNING `error`
   |
   = note: the link appears in this line:
           
           single line [error]
           single line [error]
                        ^^^^^
   = note: no item named `error` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `error`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:71:9
   |
LL | #[doc = "single line with \"escaping\" [error]"] //~ WARNING `error`
   |
   = note: the link appears in this line:
           
           
           single line with "escaping" [error]
   = note: no item named `error` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `error`
warning: unresolved link to `error`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:74:1
   |
LL | / /// Item docs. //~ WARNING `error`
LL | | #[doc="Hello there!"]
LL | | /// [error]
   |
   = note: the link appears in this line:
           
           [error]
           [error]
            ^^^^^
   = note: no item named `error` in scope
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `error1`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:80:11
   |
LL | /// docs [error1] //~ WARNING `error1`
   |
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: unresolved link to `error2`
warning: unresolved link to `error2`
##[warning]  --> /checkout/tests/rustdoc-ui/intra-doc/warning.rs:82:11
   |
LL | /// docs [error2] //~ WARNING `error2`
   |
   = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]`

warning: 19 warnings emitted
---
652 
653 error: unescaped backtick
-   --> $DIR/unescaped_backticks.rs:115:9
-    |
- LL | #[doc = concat!("\\", "`")]
-    |
-    = help: the opening backtick of an inline code may be missing
-             change: \`
-            to this: `\`
-            to this: `\`
-    = help: if you meant to use a literal backtick, escape it
-             change: \`
-            to this: \\`
- 
- error: unescaped backtick
667   --> $DIR/unescaped_backticks.rs:119:9
668    |
669 LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]

967 LL | /// | table`( | )\`body |
969 
- error: aborting due to 64 previous errors
+ error: aborting due to 63 previous errors
971 
---
To only update this specific test, also pass `--test-args unescaped_backticks.rs`

error: 1 errors occurred comparing output.
status: exit status: 1
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustdoc" "/checkout/tests/rustdoc-ui/unescaped_backticks.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "-o" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-ui/unescaped_backticks" "-A" "internal_features" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers" "-L" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/rustdoc-ui/unescaped_backticks/auxiliary"
--- stderr -------------------------------
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:187:70
   |
   |
LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
   |
note: the lint level is defined here
  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:1:9
   |
   |
LL | #![deny(rustdoc::unescaped_backticks)]
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: the closing backtick of an inline code may be missing
   |
LL | /// "runtime", phase = "optimized")]` if you don't.
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// if you want your MIR to be modified by the full MIR pipeline, or \`#![custom_mir(dialect =

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:232:13
   |
   |
LL |         //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL |         //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]`
help: if you meant to use a literal backtick, escape it
   |
   |
LL |         //! \`#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:237:13
   |
   |
LL |         /// `cfg=...
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL |         /// `cfg=...`
help: if you meant to use a literal backtick, escape it
   |
   |
LL |         /// \`cfg=...

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:241:42
   |
   |
LL |         /// `cfg=... and not `#[cfg_attr]`
   |
help: a previous inline code might be longer than expected
   |
   |
LL |         /// `cfg=...` and not `#[cfg_attr]`
help: if you meant to use a literal backtick, escape it
   |
   |
LL |         /// `cfg=... and not `#[cfg_attr]\`

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:193:93
   |
   |
LL |     /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg to
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL |     /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given `msg` to
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// Constructs a `TyKind::Error` type and registers a `span_delayed_bug` with the given \`msg to

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:202:34
   |
   |
LL |         /// in `nt_to_tokenstream`
   |                                  ^
   |
help: a previous inline code might be longer than expected
   |
LL |         /// if we parsed no predicates (e.g. `struct` Foo where {}
help: if you meant to use a literal backtick, escape it
   |
LL |         /// in `nt_to_tokenstream\`
   |                                  +
   |                                  +

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:208:62
   |
LL |     /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL |     /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index!` reserves
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// that `Option<Symbol>` only takes up 4 bytes, because \`newtype_index! reserves

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:216:52
   |
   |
LL |     /// also avoids the need to import `OpenOptions`.
   |                                                    ^
   |
help: a previous inline code might be longer than expected
   |
LL |     /// you can write `File::with_options().read(true).open("foo.txt")`. This
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// also avoids the need to import `OpenOptions\`.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:221:46
   |
   |
LL |     /// `HybridBitSet`. Has no effect if `row` does not exist.
   |
help: a previous inline code might be longer than expected
   |
   |
LL |     /// Subtracts `set` from `row`. `set` can be either `BitSet` or
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// `HybridBitSet`. Has no effect if `row\` does not exist.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:247:12
   |
   |
LL |     /// RWU`s can get very large, so it uses a more compact representation.
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL |     /// `RWU`s can get very large, so it uses a more compact representation.
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// RWU\`s can get very large, so it uses a more compact representation.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:254:15
   |
   |
LL |     /// in `U2`.
   |               ^
   |
help: the opening backtick of a previous inline code may be missing
   |
LL |     /// `'?1` is in `U3` would be canonicalized to have `?0` in `U1` and `'?1`
help: if you meant to use a literal backtick, escape it
   |
LL |     /// in `U2\`.
   |               +
   |               +

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:271:42
   |
LL |     /// because it contains `[type error]`. Yuck! (See issue #29857 for
   |
help: a previous inline code might be longer than expected
   |
   |
LL |     /// as Trait>::Foo == $0`. Here, normalizing `<MyType<$0>` as
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// because it contains `[type error]\`. Yuck! (See issue #29857 for

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:281:53
   |
   |
LL |     /// well as the second instance of `A: AutoTrait`) to suppress
   |
help: a previous inline code might be longer than expected
   |
   |
LL |     /// encountered a problem (later on) with `A:` AutoTrait. So we
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// well as the second instance of `A: AutoTrait\`) to suppress

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:291:40
   |
   |
LL |     /// `'a` with `'b` and not `'static`. But it will have to do for
   |
   = help: the opening or closing backtick of an inline code may be missing
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// `'a` with `'b` and not `'static\`. But it will have to do for

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:300:54
   |
   |
LL | /// `None`. Otherwise, it will return `Some(Dispatch)`.
   |
help: the opening backtick of a previous inline code may be missing
   |
   |
LL | /// The `Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// `None`. Otherwise, it will return `Some(Dispatch)\`.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:304:13
   |
   |
LL | /// or `None` if it isn't.
   |             ^
   |
   = help: the opening or closing backtick of an inline code may be missing
help: if you meant to use a literal backtick, escape it
   |
LL | /// or `None\` if it isn't.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:308:14
   |
   |
LL | /// `on_event` should be called.
   |              ^
   |
help: a previous inline code might be longer than expected
   |
LL | /// Called before the filtered [`Layer`]'s [`on_event`], to determine if
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// `on_event\` should be called.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:313:29
   |
   |
LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
   |
help: a previous inline code might be longer than expected
   |
LL | /// Therefore, if the `Filter` will change the value returned by this
LL | /// Therefore, if the `Filter` will change the value returned by this
   |                              +
help: if you meant to use a literal backtick, escape it
   |
LL | /// [`rebuild_interest_cache\`][rebuild] is called after the value of the max

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:323:5
   |
   |
LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
LL | |     //~^ ERROR unescaped backtick
LL | |     //~| ERROR unescaped backtick
LL | |     //~| ERROR unescaped backtick
...  |
LL | |     /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
LL | |     /// level changes.
   |
   = help: the opening backtick of a previous inline code may be missing
   = help: the opening backtick of a previous inline code may be missing
            change: The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
           to this: The `Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
   = help: if you meant to use a literal backtick, escape it
            change: `None`. Otherwise, it will return `Some(Dispatch)`.
           to this: `None`. Otherwise, it will return `Some(Dispatch)\`.
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:323:5
   |
   |
LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
LL | |     //~^ ERROR unescaped backtick
LL | |     //~| ERROR unescaped backtick
LL | |     //~| ERROR unescaped backtick
...  |
LL | |     /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
LL | |     /// level changes.
   |
   = help: the opening or closing backtick of an inline code may be missing
   = help: if you meant to use a literal backtick, escape it
            change: or `None` if it isn't.
            change: or `None` if it isn't.
           to this: or `None\` if it isn't.
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:323:5
   |
   |
LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
LL | |     //~^ ERROR unescaped backtick
LL | |     //~| ERROR unescaped backtick
LL | |     //~| ERROR unescaped backtick
...  |
LL | |     /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
LL | |     /// level changes.
   |
   = help: a previous inline code might be longer than expected
   = help: a previous inline code might be longer than expected
            change: Called before the filtered [`Layer]'s [`on_event`], to determine if
           to this: Called before the filtered [`Layer`]'s [`on_event`], to determine if
   = help: if you meant to use a literal backtick, escape it
            change: `on_event` should be called.
           to this: `on_event\` should be called.
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:323:5
   |
   |
LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
LL | |     //~^ ERROR unescaped backtick
LL | |     //~| ERROR unescaped backtick
LL | |     //~| ERROR unescaped backtick
...  |
LL | |     /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
LL | |     /// level changes.
   |
   = help: a previous inline code might be longer than expected
            change: Therefore, if the `Filter will change the value returned by this
           to this: Therefore, if the `Filter` will change the value returned by this
           to this: Therefore, if the `Filter` will change the value returned by this
   = help: if you meant to use a literal backtick, escape it
            change: [`rebuild_interest_cache`][rebuild] is called after the value of the max
           to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:349:56
   |
   |
LL |     /// instead and use [`CloneCounterObserver::counter`] to increment.
   |
   = help: the opening or closing backtick of an inline code may be missing
help: if you meant to use a literal backtick, escape it
   |
   |
LL |     /// instead and use [`CloneCounterObserver::counter\`] to increment.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:12:5
   |
---

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:26:6
   |
LL | /// [`link1]
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// [`link1`]
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// [\`link1]

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:30:11
   |
   |
LL | /// [link2`]
   |           ^
   |
help: the opening backtick of an inline code may be missing
   |
LL | /// [`link2`]
help: if you meant to use a literal backtick, escape it
   |
LL | /// [link2\`]
   |           +
   |           +

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:34:6
   |
LL | /// [`link_long](link_long)
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// [`link_long`](link_long)
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// [\`link_long](link_long)

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:38:6
   |
   |
LL | /// [`broken-link]
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// [`broken-link`]
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// [\`broken-link]

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:45:8
   |
   |
LL | /// <x:`>
   |        ^
   |
help: the opening backtick of an inline code may be missing
   |
LL | /// `<x:`>
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// <x:\`>

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:55:6
   |
---
LL | /// `foo(`
   |          +
help: if you meant to use a literal backtick, escape it
   |
LL | /// \`foo(

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:65:14
   |
   |
LL | /// `foo `bar`
   |
help: a previous inline code might be longer than expected
   |
   |
LL | /// `foo` `bar`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// `foo `bar\`

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:71:5
   |
---
LL | /// not paragraph`
   |                  +
help: if you meant to use a literal backtick, escape it
   |
LL | /// \`foo(

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:76:83
   |
   |
LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
   |
help: the opening backtick of a previous inline code may be missing
   |
   |
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:80:51
   |
   |
LL | /// or even to add a number `n` to 42 (`add(42, b)`)!
   |
help: the opening backtick of a previous inline code may be missing
   |
   |
LL | /// You could use this function to add 42 to a number `n` (`add(n, 42)`),
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// or even to add a number `n` to 42 (`add(42, b)\`)!

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:84:83
   |
   |
LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
   |
help: a previous inline code might be longer than expected
   |
   |
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:88:51
   |
   |
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
   |
help: a previous inline code might be longer than expected
   |
   |
LL | /// You could use this function to add 42 to a number `n` (`add(n, 42)`),
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:92:83
   |
   |
LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:96:50
   |
   |
LL | /// or even to add a number `n` to 42 (add(42, n)`)!
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// or even to add a number `n` to 42 (add(42, n)\`)!

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:100:74
   |
   |
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:104:51
   |
   |
LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
   |
help: a previous inline code might be longer than expected
   |
   |
LL | /// You could use this function to add 42 to a number `n` (`add(n, 42)`),
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:108:9
   |
   |
LL | #[doc = "`"]
   |
   = help: the opening or closing backtick of an inline code may be missing
   = help: if you meant to use a literal backtick, escape it
            change: `
            change: `
           to this: \`

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:119:9
   |
LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]
   |
   = help: the opening backtick of a previous inline code may be missing
   = help: the opening backtick of a previous inline code may be missing
            change: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
           to this: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
   = help: if you meant to use a literal backtick, escape it
            change: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
           to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:123:9
   |
   |
LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."]
   |
   = help: a previous inline code might be longer than expected
   = help: a previous inline code might be longer than expected
            change: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
           to this: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
   = help: if you meant to use a literal backtick, escape it
            change: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
           to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:127:9
   |
   |
LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."]
   |
   = help: the opening backtick of an inline code may be missing
   = help: the opening backtick of an inline code may be missing
            change: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
           to this: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
   = help: if you meant to use a literal backtick, escape it
            change: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
           to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:131:9
   |
   |
LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."]
   |
   = help: the closing backtick of an inline code may be missing
   = help: the closing backtick of an inline code may be missing
            change: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
           to this: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)`.
   = help: if you meant to use a literal backtick, escape it
            change: Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
           to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).
error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:136:5
   |
LL | /// `foo
---

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:140:7
   |
LL | /// # `(heading
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// # `(heading`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// # \`(heading

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:142:17
   |
   |
LL | /// ## heading2)`
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// ## `heading2)`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// ## heading2)\`

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:145:11
   |
   |
LL | /// multi `(
   |           ^
   |
help: the closing backtick of an inline code may be missing
   |
LL | /// )` heading
help: if you meant to use a literal backtick, escape it
   |
LL | /// multi \`(
   |           +
   |           +

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:151:10
   |
LL | /// para)`(graph
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// `para)`(graph
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// para)`(graph`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// para)\`(graph

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:154:10
   |
   |
LL | /// para)`(graph2
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// `para)`(graph2
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// para)`(graph2`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// para)\`(graph2

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:157:12
   |
   |
LL | /// 1. foo)`
   |            ^
   |
help: the opening backtick of an inline code may be missing
   |
LL | /// 1. `foo)`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// 1. foo)\`

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:159:8
   |
   |
LL | /// 2. `(bar
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// 2. `(bar`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// 2. \`(bar

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:161:11
   |
   |
LL | /// * baz)`
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// * `baz)`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// * baz)\`

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:163:7
   |
   |
LL | /// * `(quux
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// * `(quux`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// * \`(quux

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:166:5
   |
   |
LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// `#`![this_is_actually_an_image(and(not), an = "attribute")]
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// \`#![this_is_actually_an_image(and(not), an = "attribute")]

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:169:62
   |
   |
LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]`
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]`
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]\`

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:174:7
   |
   |
LL | /// | `table( | )head` |
   |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// | `table(` | )head` |
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// | \`table( | )head` |

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:174:22
   |
   |
LL | /// | `table( | )head` |
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// | `table( | `)head` |
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// | `table( | )head\` |

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:178:12
   |
   |
LL | /// | table`( | )`body |
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// | `table`( | )`body |
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// | table\`( | )`body |

error: unescaped backtick
##[error]  --> /checkout/tests/rustdoc-ui/unescaped_backticks.rs:178:18
   |
   |
LL | /// | table`( | )`body |
   |
help: the opening backtick of an inline code may be missing
   |
   |
LL | /// | table`( | `)`body |
help: the closing backtick of an inline code may be missing
   |
   |
LL | /// | table`( | )`body` |
help: if you meant to use a literal backtick, escape it
   |
   |
LL | /// | table`( | )\`body |

error: aborting due to 63 previous errors
------------------------------------------

rust-log-analyzer avatar Oct 17 '24 07:10 rust-log-analyzer

These commits modify the Cargo.lock file. Unintentional changes to Cargo.lock can be introduced when switching branches and rebasing PRs.

If this was unintentional then you should revert the changes before this PR is merged. Otherwise, you can ignore this comment.

Some changes occurred to MIR optimizations

cc @rust-lang/wg-mir-opt

Some changes occurred in src/tools/clippy

cc @rust-lang/clippy

Some changes occurred in coverage instrumentation.

cc @Zalathar

Some changes occurred in src/tools/rustfmt

cc @rust-lang/rustfmt

Some changes occurred in src/librustdoc/clean/types.rs

cc @camelid

Changes to the size of AST and/or HIR nodes.

cc @nnethercote

Some changes occurred in compiler/rustc_sanitizers

cc @rust-lang/project-exploit-mitigations, @rcvalle

rustbot avatar Oct 17 '24 18:10 rustbot

First, the hir stats changed slightly. Mostly because Attribute didn't used to be in there.

I see this line:

hir-stats Attribute 128 ( 1.4%) 4 32

replaced with this line lower down:

hir-stats Attribute 384 ( 4.2%) 4 96

So the size has tripled?

nnethercote avatar Oct 18 '24 00:10 nnethercote

First, the hir stats changed slightly. Mostly because Attribute didn't used to be in there.

I see this line:

hir-stats Attribute 128 ( 1.4%) 4 32

replaced with this line lower down:

hir-stats Attribute 384 ( 4.2%) 4 96

So the size has tripled?

I think you're right. This slipped through while it really shouldn't have, investigating... It seems that I forgot a layer of indirection which ast::Attribute had which is probably quite valuable. I'm choosing to make these boxes even though it's in HIR because that's what ast::Attribute also used to do in hir, and because at some point I think we can mostly remove these layers of indirection when preparsing.

jdonszelmann avatar Oct 18 '24 06:10 jdonszelmann

@nnethercote well that did it, the file even disappeared from the diff cause they're equal now :blush:

jdonszelmann avatar Oct 18 '24 07:10 jdonszelmann

:umbrella: The latest upstream changes (presumably #131892) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Oct 18 '24 23:10 bors

:umbrella: The latest upstream changes (presumably #132027) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Oct 23 '24 16:10 bors

I've done my best to split up this change into smaller commits to make it reviewable

Some meta comment - splitting is less useful unless it's done in some logical order. E.g. in the current PR https://github.com/rust-lang/rust/commit/b5fd0f643e2325b3f9c6599084896aa434ac64bf is placed first, but the compiler doesn't work after it and doesn't even build, because all the pre-requisite HIR attribute support isn't done yet. Other commits are similar, so I ended up just reviewing the whole change as one after looking at the individual commits briefly.

petrochenkov avatar Oct 26 '24 13:10 petrochenkov

I made an initial review pass and left some comments to make this change more manageable. No need to bother maintaining the current commit history when addressing them, may squash everything together if you want.

After that, could you also add an example of migrating some built-in attribute (or a group of built-in attributes, like Words) to the new scheme? (As a separate commit.) I'd like to see how it goes before starting to land the changes.

@rustbot author

petrochenkov avatar Oct 26 '24 14:10 petrochenkov

Thanks for the review! I'm actually quite far with refactoring attributes completely, also step two as highlighted in the MCP. I'll address the comments here, but also make a draft PR of that before merging so you can at least see what the new parsing will look like.

jdonszelmann avatar Oct 26 '24 14:10 jdonszelmann

With https://github.com/rust-lang/rust/pull/132192 generalizing ast::Item over attributes should no longer be necessary.

petrochenkov avatar Oct 26 '24 16:10 petrochenkov

The job mingw-check failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#16 2.958 Building wheels for collected packages: reuse
#16 2.959   Building wheel for reuse (pyproject.toml): started
#16 3.207   Building wheel for reuse (pyproject.toml): finished with status 'done'
#16 3.208   Created wheel for reuse: filename=reuse-4.0.3-cp310-cp310-manylinux_2_35_x86_64.whl size=132720 sha256=026f3bb0f1aa8090b861fd0a0939cb1a782396d84c8aab7875096557d637a0f6
#16 3.208   Stored in directory: /tmp/pip-ephem-wheel-cache-f37pxswg/wheels/3d/8d/0a/e0fc6aba4494b28a967ab5eaf951c121d9c677958714e34532
#16 3.210 Installing collected packages: boolean-py, binaryornot, tomlkit, reuse, python-debian, markupsafe, license-expression, jinja2, chardet, attrs
#16 3.620 Successfully installed attrs-23.2.0 binaryornot-0.4.4 boolean-py-4.0 chardet-5.2.0 jinja2-3.1.4 license-expression-30.3.0 markupsafe-2.1.5 python-debian-0.1.49 reuse-4.0.3 tomlkit-0.13.0
#16 3.620 WARNING: Running pip as the 'root' user can result in broken permissions and conflicting behaviour with the system package manager. It is recommended to use a virtual environment instead: https://pip.pypa.io/warnings/venv
#16 DONE 3.7s
---
    Checking rustc_mir_dataflow v0.0.0 (/checkout/compiler/rustc_mir_dataflow)
error[E0599]: no method named `item_attr` found for struct `creader::CrateMetadataRef<'a>` in the current scope
    --> compiler/rustc_metadata/src/rmeta/decoder.rs:1059:34
     |
1059 |         let attrs: Vec<_> = self.item_attr(id, sess).collect();
     |
    ::: compiler/rustc_metadata/src/creader.rs:123:1
     |
123  | pub(crate) struct CrateMetadataRef<'a> {
123  | pub(crate) struct CrateMetadataRef<'a> {
     | -------------------------------------- method `item_attr` not found for this struct
     |
help: there is a method `item_attrs` with a similar name
     |
1059 |         let attrs: Vec<_> = self.item_attrs(id, sess).collect();

For more information about this error, try `rustc --explain E0599`.
error: could not compile `rustc_metadata` (lib) due to 1 previous error
warning: build failed, waiting for other jobs to finish...

rust-log-analyzer avatar Oct 30 '24 13:10 rust-log-analyzer

The job x86_64-gnu-llvm-18 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
------
 > importing cache manifest from ghcr.io/rust-lang/rust-ci-cache:c32c805632780b5c1de330e3f44561b336c2efe163bc0990acb392390157a8e1d9f855d75914a239aa40c49d77f4a837247d05d2f8d46f554b98e1f46712a3e3:
------
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Starting the server...
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---
  Downloaded boml v0.3.1
   Compiling boml v0.3.1
   Compiling y v0.1.0 (/checkout/compiler/rustc_codegen_gcc/build_system)
    Finished `release` profile [optimized] target(s) in 3.79s
     Running `/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-codegen/x86_64-unknown-linux-gnu/release/y test --use-system-gcc --use-backend gcc --out-dir /checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/cg_gcc --release --mini-tests --std-tests`
Using system GCC
[BUILD] example
[AOT] mini_core_hello_world
/checkout/obj/build/x86_64-unknown-linux-gnu/stage1-tools/cg_gcc/mini_core_hello_world
abc
---
  --> core/src/../../stdarch/crates/core_arch/src/wasm32/simd128.rs:55:17
   |
54 |                   #[rustc_const_stable(feature = "wasm_simd_const", since = "1.56.0")]
   |                   -------------------------------------------------------------------- attribute specified here
55 |                   pub(crate) const fn v128(self) -> v128 {
...
63 | / conversions! {
63 | / conversions! {
64 | |     (as_u8x16 = simd::u8x16)
65 | |     (as_u16x8 = simd::u16x8)
66 | |     (as_u32x4 = simd::u32x4)
...  |
73 | |     (as_f64x2 = simd::f64x2)
   | |_- in this macro invocation
   |
   = note: this error originates in the macro `conversions` (in Nightly builds, run with -Z macro-backtrace for more info)


error: could not document `core`
warning: build failed, waiting for other jobs to finish...
Command has failed. Rerun with -v to see more details.
  local time: Wed Oct 30 14:42:00 UTC 2024
  network time: Wed, 30 Oct 2024 14:42:00 GMT
##[error]Process completed with exit code 1.
Post job cleanup.

rust-log-analyzer avatar Oct 30 '24 14:10 rust-log-analyzer

:umbrella: The latest upstream changes (presumably #132435) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Nov 01 '24 06:11 bors

:umbrella: The latest upstream changes (presumably #132470) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Nov 02 '24 01:11 bors

:umbrella: The latest upstream changes (presumably #132626) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Nov 05 '24 08:11 bors

Some changes occurred in src/tools/cargo

cc @ehuss

rustbot avatar Nov 05 '24 10:11 rustbot

Sorry Eric, some submodule update to cargo slipped in but nothing actually changed in Cargo

jdonszelmann avatar Nov 05 '24 10:11 jdonszelmann

:umbrella: The latest upstream changes (presumably #129884) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Nov 05 '24 19:11 bors

I rebased the PR, reordered some commits and squashed the clippy/rustdoc/rustfmt commits into the main commit. Each commit now builds on its own and does the minimal work necessary to get to a new compiling state. The middle commit is subsequently huge, but that's unavoidable for something like adding hir::Attribute

oli-obk avatar Dec 03 '24 09:12 oli-obk

The job x86_64-gnu-tools failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
   Compiling tracing-tree v0.3.1
error: unreachable pattern
    --> compiler/rustc_ast/src/ast.rs:1747:13
     |
1746 |             AttrArgs::Eq { eq_span, expr } => Some(eq_span.to(expr.span)),
     |             ------------------------------ matches all the relevant values
1747 |             AttrArgs::Eq { eq_span, expr } => Some(eq_span.to(expr.span)),
     |
     = note: `-D unreachable-patterns` implied by `-D warnings`
     = help: to override `-D warnings` add `#[allow(unreachable_patterns)]`

rust-log-analyzer avatar Dec 03 '24 09:12 rust-log-analyzer

:umbrella: The latest upstream changes (presumably #134052) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Dec 09 '24 06:12 bors

The job x86_64-gnu-llvm-18 failed! Check out the build log: (web) (plain)

Click to see the possible cause of the failure (guessed by this bot)
#17 exporting to docker image format
#17 sending tarball 28.8s done
#17 DONE 34.7s
##[endgroup]
Setting extra environment values for docker:  --env ENABLE_GCC_CODEGEN=1 --env GCC_EXEC_PREFIX=/usr/lib/gcc/
[CI_JOB_NAME=x86_64-gnu-llvm-18]
debug: `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` configured.
---
sccache: Starting the server...
##[group]Configure the build
configure: processing command line
configure: 
configure: build.configure-args := ['--build=x86_64-unknown-linux-gnu', '--llvm-root=/usr/lib/llvm-18', '--enable-llvm-link-shared', '--set', 'rust.randomize-layout=true', '--set', 'rust.thin-lto-import-instr-limit=10', '--enable-verbose-configure', '--enable-sccache', '--disable-manage-submodules', '--enable-locked-deps', '--enable-cargo-native-static', '--set', 'rust.codegen-units-std=1', '--set', 'dist.compression-profile=balanced', '--dist-compression-formats=xz', '--set', 'rust.lld=false', '--disable-dist-src', '--release-channel=nightly', '--enable-debug-assertions', '--enable-overflow-checks', '--enable-llvm-assertions', '--set', 'rust.verify-llvm-ir', '--set', 'rust.codegen-backends=llvm,cranelift,gcc', '--set', 'llvm.static-libstdcpp', '--enable-new-symbol-mangling']
configure: target.x86_64-unknown-linux-gnu.llvm-config := /usr/lib/llvm-18/bin/llvm-config
configure: llvm.link-shared     := True
configure: rust.randomize-layout := True
configure: rust.thin-lto-import-instr-limit := 10
---

19 LL - #[no_mangle]
20    |
21 
- warning: `#[unsafe(no_mangle)]` attribute may not be used in combination with `#[export_name]`
+ warning: `#[no_mangle]` attribute may not be used in combination with `#[export_name]`
24    |
25 LL | #[unsafe(no_mangle)]


-    | ^^^^^^^^^^^^^^^^^^^^ `#[unsafe(no_mangle)]` is ignored
+    | ^^^^^^^^^^^^^^^^^^^^ `#[no_mangle]` is ignored
28 note: `#[export_name]` takes precedence
29   --> $DIR/mixed_export_name_and_no_mangle.rs:13:1

30    |
30    |
31 LL | #[export_name = "baz"]
32    | ^^^^^^^^^^^^^^^^^^^^^^
- help: remove the `#[unsafe(no_mangle)]` attribute
+ help: remove the `#[no_mangle]` attribute
34    |
35 LL - #[unsafe(no_mangle)]


The actual stderr differed from the expected stderr.
To update references, rerun the tests and pass the `--bless` flag
To update references, rerun the tests and pass the `--bless` flag
To only update this specific test, also pass `--test-args attributes/mixed_export_name_and_no_mangle.rs`

error: 1 errors occurred comparing output.
status: exit status: 0
command: env -u RUSTC_LOG_COLOR RUSTC_ICE="0" RUST_BACKTRACE="short" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2/bin/rustc" "/checkout/tests/ui/attributes/mixed_export_name_and_no_mangle.rs" "-Zthreads=1" "-Zsimulate-remapped-rust-src-base=/rustc/FAKE_PREFIX" "-Ztranslate-remapped-path-to-local-path=no" "-Z" "ignore-directory-in-diagnostics-source-blocks=/cargo" "-Z" "ignore-directory-in-diagnostics-source-blocks=/checkout/vendor" "--sysroot" "/checkout/obj/build/x86_64-unknown-linux-gnu/stage2" "--target=x86_64-unknown-linux-gnu" "--check-cfg" "cfg(FALSE)" "--error-format" "json" "--json" "future-incompat" "-Ccodegen-units=1" "-Zui-testing" "-Zdeduplicate-diagnostics=no" "-Zwrite-long-types-to-disk=no" "-Cstrip=debuginfo" "--emit" "metadata" "-C" "prefer-dynamic" "--out-dir" "/checkout/obj/build/x86_64-unknown-linux-gnu/test/ui/attributes/mixed_export_name_and_no_mangle" "-A" "unused" "-A" "internal_features" "-Crpath" "-Cdebuginfo=0" "-Lnative=/checkout/obj/build/x86_64-unknown-linux-gnu/native/rust-test-helpers"
--- stderr -------------------------------
--- stderr -------------------------------
warning: `#[no_mangle]` attribute may not be used in combination with `#[export_name]`
   |
LL | #[no_mangle]
   | ^^^^^^^^^^^^ `#[no_mangle]` is ignored
   |
---
   |
LL - #[no_mangle]
   |

warning: `#[no_mangle]` attribute may not be used in combination with `#[export_name]`
   |
LL | #[unsafe(no_mangle)]
   | ^^^^^^^^^^^^^^^^^^^^ `#[no_mangle]` is ignored
   |
   |
note: `#[export_name]` takes precedence
  --> /checkout/tests/ui/attributes/mixed_export_name_and_no_mangle.rs:13:1
   |
LL | #[export_name = "baz"]
   | ^^^^^^^^^^^^^^^^^^^^^^
help: remove the `#[no_mangle]` attribute
   |
LL - #[unsafe(no_mangle)]

warning: 2 warnings emitted
------------------------------------------

rust-log-analyzer avatar Dec 10 '24 23:12 rust-log-analyzer

:umbrella: The latest upstream changes (presumably #133099) made this pull request unmergeable. Please resolve the merge conflicts.

bors avatar Dec 13 '24 23:12 bors

Alright, I promised I'd write this, so finally here we go. I'll also post this same comment here to track progress.

Already completed

  • [x] remove attribute IDs from hir statistics https://github.com/rust-lang/rust/pull/132576
  • [x] make clippy's attribute lints work on the ast instead of hir
    • [x] https://github.com/rust-lang/rust/pull/132598
    • [x] https://github.com/rust-lang/rust-clippy/pull/13657
    • [x] https://github.com/rust-lang/rust-clippy/pull/13658

This pr

Introduce hir attributes, making a very clear distinction between pre-lowering and post-lowering attributes

After hir attributes exist, I want to slowly start tackling attribute parsing. Most of that happens spread out throughout the compiler, but the one place that has a lot of it centralized is rustc_attr/src/builtin.rs. Introducing this in one go is a pain to review, so I'm trying to keep things reviewable and hopefully reduce the number of conflicts, though there will be some, and make every change on its own either neutral or a net-positive change.

Future

split up builtins.rs into files for individual attributes

ready: https://github.com/jdonszelmann/rust/pull/4

rename rustc_attr to rustc_attr_parsing, and introduce also rustc_attr_data_structures

ready: https://github.com/jdonszelmann/rust/pull/3

(I might make this ande the previous one 1 pr). This one might be a little painful, but I think clear naming is also important. I think it's nice if code that has to do with attributes mostly lives in rustc_attr_* crates, and because of circular dependencies it can't be a single one.

Introduce new logic to systematically parse attributes

Sofar these changes might be nice, but neither makes attribute parsing actually better.

A lot of these changes are already implemented. I have made this pr to my own fork for me to keep track of everything, it contains a lot of the changes I want to make, but it's currently too large to review. I'm a bit further ahead, since I wanted to make 100% sure that what I'm planning works out. So, I've already experimented with converting around 15 different kinds of attributes to it, and testing the compiler on that. I didn't want to propose something that wouldn't actually work.

Below follows an explanation of some of it, but feel free to skip that if you're not interested in that right now. When I file this, I'll of course motivate it more. In the code it's already documented pretty well.

Define an enum AttributeKind that exhaustively lists all parsed attributes.

https://github.com/jdonszelmann/rust/blob/458f1d026c6dfe7345829326793db0f26fda6b77/compiler/rustc_attr_data_structures/src/attributes.rs#L129

It contains a variant for all attributes in the compiler, but when I make a PR for this I'll of course start with only one or two.

For a bit, Attributes will be an enum. An attribute is either Parsed, or Unparsed. Unparsed attributes will basically be hir attributes like introduced in this pr (https://github.com/rust-lang/rust/pull/131808). At some point in the future, almost no attributes will be of the Unparsed type anymore, except custom tool attributes which we cannot parse.

Define "attribute groups", sets of syntactical attributes that are parsed together.

Here's an example of that. You can see the group for #[stable(..)], #[unstable(..)] and #[rustc_allowed_through_unstable_modules]

These are a group together, because they result in a single parsed AttributeKind. That's because these are either directly conflicting, or modify each other. Attribute groups have state. They work in two phases:

  1. Iterate over all relevant attributes. Which ones are relevant is defined by the group. This modifies the state of the group.
  2. When all relevant attributes have passed, each goup can report that the result of what it saw as either an error, or a valid AttributeKind.

The stability group accepts stable, unstable and rustc_allowed_through_unstable_modules, rejects stable if it already saw unstable and the other way round, and finally creates one AttributeKind containing either a stability, instability, and a boolean whether it also saw rustc_allowed_through_unstable_modules.

Define certain shortcuts for common kinds of attribute groups.

For example, an attribute that can only appear a single time, or are only a single word (no parameters), or where only either the first or the last one is accepted and the rest should warn. I've already crudely done this for attributes that can only appear a single time but I want it to match the same names as AttributeDuplicates, since that's effectively what these simplifications are. That way, these policies for when an attribute is duplicate becomes a property of how we parse it, making it impossible to do it wrong. I recently found a bug with duplicate #[inline] where it warns that the unused attribute is the last one, while actually it's the first one that's unused. That will become impossible.

Define a macro to match on attributes on nodes

You can see an example of that here


Note that the attribute parsers will usually run as part of ast lowering, but in select cases it is desired to run them early. I did consider this, and this is indeed possible using the approach described here.

Create a new attribute parser

Currently, attributes are not really parsed, I think it can more accurately be described as being decomposed. rustc_ast::attr has all kinds of methods to convert between somewhat abstract types like AttrItem, Attribute, MetaItem, MetaItemKind, etc, representing parts of attributes but mostly containing tokens. When attributes are parsed, they are broken up and often still stored as smaller instances of these types, while what we really want to do is get the information out and throw away the tokens when parsing.

I've created a new parser that is better suited to do this, making it harder to make errors. Even though it's already ready, I'll introduce this separately so we can talk about its benefits separately.

introduce rustc_attr_validation

At this point, not much has changed as to validation. Next to rustc_attr_parsing and rustc_attr_data_structures, I intend to create rustc_attr_validation. This will represent all the logic after ast lowering, for when a tcx is available and we can run queries. Some of this currently happens in rustc_passes/check_attr.rs. However, even the fact that we will be able to exhaustively match on an enum of attributes will make mistakes harder. I intend to make more changes, such as forcing new attributes to list what kinds of targets they're valid on.

Document these changes

Of course, I'll already have documentation on all the previous changes in code. However, I intend to write a post on the dev guide as well to make sure that in the future, people know how to use the infrastructure for attributes

Port all attributes to this system

At this point, with all infrastructure in place, I expect a few PRs porting all attributes to be parsed in rustc_attr_parsing. I might ask others to help here, which is now possible when things are documented in the devguide.

FUTURE also introduce some parsed attributes in the AST

This is an idea of @oli-obk . It might be good to also make a smaller enum of parsed attributes in ast::Attribute. Especially for attributes that can be discarded when lowering, or which we need or need to validate earlier on. When we validate them while parsing, we can make fewer mistakes. These can then also contain fields that aren't just tokens to support for example resolving names like with the defines attribute.


pfew, that's a lot. Finally, a summary of PRs I intend to make after this:

  • [ ] refactor: split up builtins.rs into separate files for the different attributes (this makes future conflicts easier to resolve, and later on the parsers will be split over these files anyway) (pr ready)
  • [ ] refactor: rename rustc_attr to rustc_attr_parsing. This is where the parsers will be defined. There will also be rustc_attr_datastructures containing all the structs and enums contained in attributes, and later also the AttributeKind enum (containing all the parsed attributes). This is necessary, because the datastructures cannot be defined in rustc_attr_parsing itself when rustc_hir needs to import them (cyclic dependency problem) (pr ready)
  • [ ] introduce infrastructure in rustc_attr_parsing to systematically parse attributes using rustc_ast parsing type. (implementation ready) I've implemented this, but need to make the diff more manageable. I've also used this setup to create parsers for like 10 different attributes already to see if it all works. I don't intend to ship these parsers immediately though
  • [ ] introduce a new parser with which it's harder to make mistakes, deleting rustc_ast::attr/*. implementation ready
  • [ ] introduce rustc_attr_validation (also needs to be a separate crate, cyclic deps again) where we can put all the checks that run post-ast-lowering when we have a tcx. Here we can exhaustively match on parsed attributes and make sure everything we care about is validated.
  • [ ] Document this new approach well (I've already used rustdoc a lot, but intend to also write an article for the dev guide)
  • [ ] (multiple PRs): slowly introduce the parsers I've made sofar, and port more. I've done most of the complicated ones luckily to check if my approach works. This is something others can start helping with as well since the approach should now be documented properly
  • [ ] future: introduce parsed attributes in ast::Attribute for attributes that can be discarded when lowering, or which we need or need to validate earlier on. These can contain fields that arent just tokens to support for example name resolution in them

jdonszelmann avatar Dec 14 '24 23:12 jdonszelmann

The implementation part looks correct.

My general feeling about the direction though, is that it's a lot of work to arrive to a system that is 2-3 times larger and more complex than the current one, i.e. overengineering. But at least @jdonszelmann is volunteering to do that work and doesn't suggest me to do it. And maybe the metadata reading/writing will be faster.

I won't block proceeding with this experiment if others on the compiler team want it. The potential harm is not large since built-in attributes are simple, and therefore the existing attribute processing system is simple, and even making it twice as complex is tolerable. Maybe in a few years the changes will be reverted in an equally valiant effort by a different enthusiastic person (or maybe not). Edit: I'd actually rather try this experiment and see it fail than not try it at all.


I still feel pretty strongly about not doing this

These can then also contain fields that aren't just tokens to support for example resolving names like with the defines attribute.

, if something is not on a similar level of triviality with current built-in attributes, then it shouldn't be an attribute.

petrochenkov avatar Dec 15 '24 17:12 petrochenkov

@bors delegate+

r=me,petrochenkov once CI is happy

oli-obk avatar Dec 15 '24 18:12 oli-obk