From 7eaf7386b93dbeb5029cc99538b3b25fc81928aa Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 17 Jun 2025 12:22:13 -0500 Subject: [PATCH 01/11] bootstrap.example.toml: use less contextual format prefixing each key with its section means you don't need to scroll up 4 pages to see which section a particular key is from. target specific options were kept in old format since the exact section name depends on the target, so those options must now be moved to the bottom of the file. --- bootstrap.example.toml | 383 ++++++++++++++++++++--------------------- 1 file changed, 189 insertions(+), 194 deletions(-) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 19cf360b0fb8b..38c3195deb9d7 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -44,7 +44,6 @@ # ============================================================================= # Tweaking how LLVM is compiled # ============================================================================= -[llvm] # Whether to use Rust CI built LLVM instead of locally building it. # @@ -62,50 +61,50 @@ # # Note that many of the LLVM options are not currently supported for # downloading. Currently only the "assertions" option can be toggled. -#download-ci-llvm = true +#llvm.download-ci-llvm = true # Indicates whether the LLVM build is a Release or Debug build -#optimize = true +#llvm.optimize = true # Indicates whether LLVM should be built with ThinLTO. Note that this will # only succeed if you use clang, lld, llvm-ar, and llvm-ranlib in your C/C++ # toolchain (see the `cc`, `cxx`, `linker`, `ar`, and `ranlib` options below). # More info at: https://clang.llvm.org/docs/ThinLTO.html#clang-bootstrap -#thin-lto = false +#llvm.thin-lto = false # Indicates whether an LLVM Release build should include debug info -#release-debuginfo = false +#llvm.release-debuginfo = false # Indicates whether the LLVM assertions are enabled or not # NOTE: When assertions are disabled, bugs in the integration between rustc and LLVM can lead to # unsoundness (segfaults, etc.) in the rustc process itself, not just in the generated code. -#assertions = false +#llvm.assertions = false # Indicates whether the LLVM testsuite is enabled in the build or not. Does # not execute the tests as part of the build as part of x.py build et al, # just makes it possible to do `ninja check-llvm` in the staged LLVM build # directory when doing LLVM development as part of Rust development. -#tests = false +#llvm.tests = false # Indicates whether the LLVM plugin is enabled or not -#plugins = false +#llvm.plugins = false # Whether to build Enzyme as AutoDiff backend. -#enzyme = false +#llvm.enzyme = false # Whether to build LLVM with support for it's gpu offload runtime. -#offload = false +#llvm.offload = false # When true, link libstdc++ statically into the rustc_llvm. # This is useful if you don't want to use the dynamic version of that # library provided by LLVM. -#static-libstdcpp = false +#llvm.static-libstdcpp = false # Enable LLVM to use zstd for compression. -#libzstd = false +#llvm.libzstd = false # Whether to use Ninja to build LLVM. This runs much faster than make. -#ninja = true +#llvm.ninja = true # LLVM targets to build support for. # Note: this is NOT related to Rust compilation targets. However, as Rust is @@ -113,13 +112,13 @@ # the resulting rustc being unable to compile for the disabled architectures. # # To add support for new targets, see https://rustc-dev-guide.rust-lang.org/building/new-target.html. -#targets = "AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86" +#llvm.targets = "AArch64;AMDGPU;ARM;BPF;Hexagon;LoongArch;MSP430;Mips;NVPTX;PowerPC;RISCV;Sparc;SystemZ;WebAssembly;X86" # LLVM experimental targets to build support for. These targets are specified in # the same format as above, but since these targets are experimental, they are # not built by default and the experimental Rust compilation targets that depend # on them will not work unless the user opts in to building them. -#experimental-targets = "AVR;M68k;CSKY" +#llvm.experimental-targets = "AVR;M68k;CSKY" # Cap the number of parallel linker invocations when compiling LLVM. # This can be useful when building LLVM with debug info, which significantly @@ -127,86 +126,84 @@ # each linker process. # If set to 0, linker invocations are treated like any other job and # controlled by bootstrap's -j parameter. -#link-jobs = 0 +#llvm.link-jobs = 0 # Whether to build LLVM as a dynamically linked library (as opposed to statically linked). # Under the hood, this passes `--shared` to llvm-config. # NOTE: To avoid performing LTO multiple times, we suggest setting this to `true` when `thin-lto` is enabled. -#link-shared = llvm.thin-lto +#llvm.link-shared = llvm.thin-lto # When building llvm, this configures what is being appended to the version. # To use LLVM version as is, provide an empty string. -#version-suffix = if rust.channel == "dev" { "-rust-dev" } else { "-rust-$version-$channel" } +#llvm.version-suffix = if rust.channel == "dev" { "-rust-dev" } else { "-rust-$version-$channel" } # On MSVC you can compile LLVM with clang-cl, but the test suite doesn't pass # with clang-cl, so this is special in that it only compiles LLVM with clang-cl. # Note that this takes a /path/to/clang-cl, not a boolean. -#clang-cl = cc +#llvm.clang-cl = cc # Pass extra compiler and linker flags to the LLVM CMake build. -#cflags = "" -#cxxflags = "" -#ldflags = "" +#llvm.cflags = "" +#llvm.cxxflags = "" +#llvm.ldflags = "" # Use libc++ when building LLVM instead of libstdc++. This is the default on # platforms already use libc++ as the default C++ library, but this option # allows you to use libc++ even on platforms when it's not. You need to ensure # that your host compiler ships with libc++. -#use-libcxx = false +#llvm.use-libcxx = false # The value specified here will be passed as `-DLLVM_USE_LINKER` to CMake. -#use-linker = (path) +#llvm.use-linker = (path) # Whether or not to specify `-DLLVM_TEMPORARILY_ALLOW_OLD_TOOLCHAIN=YES` -#allow-old-toolchain = false +#llvm.allow-old-toolchain = false # Whether to include the Polly optimizer. -#polly = false +#llvm.polly = false # Whether to build the clang compiler. -#clang = false +#llvm.clang = false # Whether to enable llvm compilation warnings. -#enable-warnings = false +#llvm.enable-warnings = false # Custom CMake defines to set when building LLVM. -#build-config = {} +#llvm.build-config = {} # ============================================================================= # Tweaking how GCC is compiled # ============================================================================= -[gcc] # Download GCC from CI instead of building it locally. # Note that this will attempt to download GCC even if there are local # modifications to the `src/gcc` submodule. # Currently, this is only supported for the `x86_64-unknown-linux-gnu` target. -#download-ci-gcc = false +#gcc.download-ci-gcc = false # ============================================================================= # General build configuration options # ============================================================================= -[build] # The default stage to use for the `check` subcommand -#check-stage = 0 +#build.check-stage = 0 # The default stage to use for the `doc` subcommand -#doc-stage = 0 +#build.doc-stage = 0 # The default stage to use for the `build` subcommand -#build-stage = 1 +#build.build-stage = 1 # The default stage to use for the `test` subcommand -#test-stage = 1 +#build.test-stage = 1 # The default stage to use for the `dist` subcommand -#dist-stage = 2 +#build.dist-stage = 2 # The default stage to use for the `install` subcommand -#install-stage = 2 +#build.install-stage = 2 # The default stage to use for the `bench` subcommand -#bench-stage = 2 +#build.bench-stage = 2 # A descriptive string to be appended to version output (e.g., `rustc --version`), # which is also used in places like debuginfo `DW_AT_producer`. This may be useful for @@ -217,7 +214,7 @@ # upstream Rust you need to set this to "". However, note that if you set this to "" but # are not actually compatible -- for example if you've backported patches that change # behavior -- this may lead to miscompilations or other bugs. -#description = "" +#build.description = "" # Build triple for the pre-compiled snapshot compiler. If `rustc` is set, this must match its host # triple (see `rustc --version --verbose`; cross-compiling the rust build system itself is NOT @@ -229,14 +226,14 @@ # Otherwise, `x.py` will try to infer it from the output of `uname`. # If `uname` is not found in PATH, we assume this is `x86_64-pc-windows-msvc`. # This may be changed in the future. -#build = "x86_64-unknown-linux-gnu" (as an example) +#build.build = "x86_64-unknown-linux-gnu" (as an example) # Which triples to produce a compiler toolchain for. Each of these triples will be bootstrapped from # the build triple themselves. In other words, this is the list of triples for which to build a # compiler that can RUN on that triple. # # Defaults to just the `build` triple. -#host = [build.build] (list of triples) +#build.host = [build.build] (list of triples) # Which triples to build libraries (core/alloc/std/test/proc_macro) for. Each of these triples will # be bootstrapped from the build triple themselves. In other words, this is the list of triples for @@ -245,32 +242,32 @@ # Defaults to `host`. If you set this explicitly, you likely want to add all # host triples to this list as well in order for those host toolchains to be # able to compile programs for their native target. -#target = build.host (list of triples) +#build.target = build.host (list of triples) # Use this directory to store build artifacts. Paths are relative to the current directory, not to # the root of the repository. -#build-dir = "build" +#build.build-dir = "build" # Instead of downloading the src/stage0 version of Cargo specified, use # this Cargo binary instead to build all Rust code # If you set this, you likely want to set `rustc` as well. -#cargo = "/path/to/cargo" +#build.cargo = "/path/to/cargo" # Instead of downloading the src/stage0 version of the compiler # specified, use this rustc binary instead as the stage0 snapshot compiler. # If you set this, you likely want to set `cargo` as well. -#rustc = "/path/to/rustc" +#build.rustc = "/path/to/rustc" # Instead of downloading the src/stage0 version of rustfmt specified, # use this rustfmt binary instead as the stage0 snapshot rustfmt. -#rustfmt = "/path/to/rustfmt" +#build.rustfmt = "/path/to/rustfmt" # Instead of downloading the src/stage0 version of cargo-clippy specified, # use this cargo-clippy binary instead as the stage0 snapshot cargo-clippy. # # Note that this option should be used with the same toolchain as the `rustc` option above. # Otherwise, clippy is likely to fail due to a toolchain conflict. -#cargo-clippy = "/path/to/cargo-clippy" +#build.cargo-clippy = "/path/to/cargo-clippy" # Whether to build documentation by default. If false, rustdoc and # friends will still be compiled but they will not be used to generate any @@ -278,47 +275,47 @@ # # You can still build documentation when this is disabled by explicitly passing paths, # e.g. `x doc library`. -#docs = true +#build.docs = true # Flag to specify whether CSS, JavaScript, and HTML are minified when # docs are generated. JSON is always minified, because it's enormous, # and generated in already-minified form from the beginning. -#docs-minification = true +#build.docs-minification = true # Flag to specify whether private items should be included in the library docs. -#library-docs-private-items = false +#build.library-docs-private-items = false # Indicate whether to build compiler documentation by default. # You can still build documentation when this is disabled by explicitly passing a path: `x doc compiler`. -#compiler-docs = false +#build.compiler-docs = false # Indicate whether git submodules are managed and updated automatically. -#submodules = true +#build.submodules = true # The path to (or name of) the GDB executable to use. This is only used for # executing the debuginfo test suite. -#gdb = "gdb" +#build.gdb = "gdb" # The path to (or name of) the LLDB executable to use. This is only used for # executing the debuginfo test suite. -#lldb = "lldb" +#build.lldb = "lldb" # The node.js executable to use. Note that this is only used for the emscripten # target when running tests, otherwise this can be omitted. -#nodejs = "node" +#build.nodejs = "node" # The npm executable to use. Note that this is used for rustdoc-gui tests, # otherwise this can be omitted. # # Under Windows this should be `npm.cmd` or path to it (verified on nodejs v18.06), or # error will be emitted. -#npm = "npm" +#build.npm = "npm" # Python interpreter to use for various tasks throughout the build, notably # rustdoc tests, the lldb python interpreter, and some dist bits and pieces. # # Defaults to the Python interpreter used to execute x.py. -#python = "python" +#build.python = "python" # The path to the REUSE executable to use. Note that REUSE is not required in # most cases, as our tooling relies on a cached (and shrunk) copy of the @@ -328,17 +325,17 @@ # repository to change, and the cached copy has to be regenerated. # # Defaults to the "reuse" command in the system path. -#reuse = "reuse" +#build.reuse = "reuse" # Force Cargo to check that Cargo.lock describes the precise dependency # set that all the Cargo.toml files create, instead of updating it. -#locked-deps = false +#build.locked-deps = false # Indicate whether the vendored sources are used for Rust dependencies or not. # # Vendoring requires additional setup. We recommend using the pre-generated source tarballs if you # want to use vendoring. See https://forge.rust-lang.org/infra/other-installation-methods.html#source-code. -#vendor = if "is a tarball source" && "vendor" dir exists && ".cargo/config.toml" file exists { true } else { false } +#build.vendor = if "is a tarball source" && "vendor" dir exists && ".cargo/config.toml" file exists { true } else { false } # Typically the build system will build the Rust compiler twice. The second # compiler, however, will simply use its own libraries to link against. If you @@ -346,11 +343,11 @@ # then you can set this option to true. # # This is only useful for verifying that rustc generates reproducible builds. -#full-bootstrap = false +#build.full-bootstrap = false # Set the bootstrap/download cache path. It is useful when building rust # repeatedly in a CI environment. -#bootstrap-cache-path = /path/to/shared/cache +#build.bootstrap-cache-path = /path/to/shared/cache # Enable a build of the extended Rust tool set which is not only the compiler # but also tools such as Cargo. This will also produce "combined installers" @@ -359,7 +356,7 @@ # which tools should be built if `extended = true`. # # This is disabled by default. -#extended = false +#build.extended = false # Set of tools to be included in the installation. # @@ -368,7 +365,7 @@ # If `extended = true`, they are all included. # # If any enabled tool fails to build, the installation fails. -#tools = [ +#build.tools = [ # "cargo", # "clippy", # "rustdoc", @@ -391,14 +388,14 @@ #tool.TOOL_NAME.features = [FEATURE1, FEATURE2] # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation -#verbose = 0 +#build.verbose = 0 # Build the sanitizer runtimes -#sanitizers = false +#build.sanitizers = false # Build the profiler runtime (required when compiling with options that depend # on this runtime, such as `-C profile-generate` or `-C instrument-coverage`). -#profiler = false +#build.profiler = false # Use the optimized LLVM C intrinsics for `compiler_builtins`, rather than Rust intrinsics. # Requires the LLVM submodule to be managed by bootstrap (i.e. not external) so that `compiler-rt` @@ -406,102 +403,100 @@ # # Setting this to `false` generates slower code, but removes the requirement for a C toolchain in # order to run `x check`. -#optimized-compiler-builtins = if rust.channel == "dev" { false } else { true } +#build.optimized-compiler-builtins = if rust.channel == "dev" { false } else { true } # Indicates whether the native libraries linked into Cargo will be statically # linked or not. -#cargo-native-static = false +#build.cargo-native-static = false # Run the build with low priority, by setting the process group's "nice" value # to +10 on Unix platforms, and by using a "low priority" job object on Windows. -#low-priority = false +#build.low-priority = false # Arguments passed to the `./configure` script, used during distcheck. You # probably won't fill this in but rather it's filled in by the `./configure` # script. Useful for debugging. -#configure-args = [] +#build.configure-args = [] # Indicates that a local rebuild is occurring instead of a full bootstrap, # essentially skipping stage0 as the local compiler is recompiling itself again. # Useful for modifying only the stage2 compiler without having to pass `--keep-stage 0` each time. -#local-rebuild = false +#build.local-rebuild = false # Print out how long each bootstrap step took (mostly intended for CI and # tracking over time) -#print-step-timings = false +#build.print-step-timings = false # Print out resource usage data for each bootstrap step, as defined by the Unix # struct rusage. (Note that this setting is completely unstable: the data it # captures, what platforms it supports, the format of its associated output, and # this setting's very existence, are all subject to change.) -#print-step-rusage = false +#build.print-step-rusage = false # Always patch binaries for usage with Nix toolchains. If `true` then binaries # will be patched unconditionally. If `false` or unset, binaries will be patched # only if the current distribution is NixOS. This option is useful when using # a Nix toolchain on non-NixOS distributions. -#patch-binaries-for-nix = false +#build.patch-binaries-for-nix = false # Collect information and statistics about the current build, and write it to # disk. Enabling this has no impact on the resulting build output. The # schema of the file generated by the build metrics feature is unstable, and # this is not intended to be used during local development. -#metrics = false +#build.metrics = false # Specify the location of the Android NDK. Used when targeting Android. -#android-ndk = "/path/to/android-ndk-r26d" +#build.android-ndk = "/path/to/android-ndk-r26d" # Number of parallel jobs to be used for building and testing. If set to `0` or # omitted, it will be automatically determined. This is the `-j`/`--jobs` flag # passed to cargo invocations. -#jobs = 0 +#build.jobs = 0 # What custom diff tool to use for displaying compiletest tests. -#compiletest-diff-tool = +#build.compiletest-diff-tool = # Whether to use the precompiled stage0 libtest with compiletest. -#compiletest-use-stage0-libtest = true +#build.compiletest-use-stage0-libtest = true # Indicates whether ccache is used when building certain artifacts (e.g. LLVM). # Set to `true` to use the first `ccache` in PATH, or set an absolute path to use # a specific version. -#ccache = false +#build.ccache = false # List of paths to exclude from the build and test processes. # For example, exclude = ["tests/ui", "src/tools/tidy"]. -#exclude = [] +#build.exclude = [] # ============================================================================= # General install configuration options # ============================================================================= -[install] # Where to install the generated toolchain. Must be an absolute path. -#prefix = "/usr/local" +#install.prefix = "/usr/local" # Where to install system configuration files. # If this is a relative path, it will get installed in `prefix` above -#sysconfdir = "/etc" +#install.sysconfdir = "/etc" # Where to install documentation in `prefix` above -#docdir = "share/doc/rust" +#install.docdir = "share/doc/rust" # Where to install binaries in `prefix` above -#bindir = "bin" +#install.bindir = "bin" # Where to install libraries in `prefix` above -#libdir = "lib" +#install.libdir = "lib" # Where to install man pages in `prefix` above -#mandir = "share/man" +#install.mandir = "share/man" # Where to install data in `prefix` above -#datadir = "share" +#install.datadir = "share" # ============================================================================= # Options for compiling Rust code itself # ============================================================================= -[rust] # Whether or not to optimize when compiling the compiler and standard library, # and what level of optimization to use. @@ -517,7 +512,7 @@ # 3 - All optimizations. # "s" - Optimize for binary size. # "z" - Optimize for binary size, but also turn off loop vectorization. -#optimize = true +#rust.optimize = true # Indicates that the build should be configured for debugging Rust. A # `debug`-enabled compiler and standard library will be somewhat @@ -540,7 +535,7 @@ # "maximally debuggable" environment (notably libstd) takes # hours to build. # -#debug = false +#rust.debug = false # Whether to download the stage 1 and 2 compilers from CI. This is useful if you # are working on tools, doc-comments, or library (you will be able to build the @@ -553,37 +548,37 @@ # # Set this to `true` to always download or `false` to always use the in-tree # compiler. -#download-rustc = false +#rust.download-rustc = false # Number of codegen units to use for each compiler invocation. A value of 0 # means "the number of cores on this machine", and 1+ is passed through to the # compiler. # # Uses the rustc defaults: https://doc.rust-lang.org/rustc/codegen-options/index.html#codegen-units -#codegen-units = if incremental { 256 } else { 16 } +#rust.codegen-units = if incremental { 256 } else { 16 } # Sets the number of codegen units to build the standard library with, # regardless of what the codegen-unit setting for the rest of the compiler is. # NOTE: building with anything other than 1 is known to occasionally have bugs. -#codegen-units-std = codegen-units +#rust.codegen-units-std = codegen-units # Whether or not debug assertions are enabled for the compiler and standard library. # These can help find bugs at the cost of a small runtime slowdown. # # Defaults to rust.debug value -#debug-assertions = rust.debug (boolean) +#rust.debug-assertions = rust.debug (boolean) # Whether or not debug assertions are enabled for the standard library. # Overrides the `debug-assertions` option, if defined. # # Defaults to rust.debug-assertions value -#debug-assertions-std = rust.debug-assertions (boolean) +#rust.debug-assertions-std = rust.debug-assertions (boolean) # Whether or not debug assertions are enabled for the tools built by bootstrap. # Overrides the `debug-assertions` option, if defined. # # Defaults to rust.debug-assertions value -#debug-assertions-tools = rust.debug-assertions (boolean) +#rust.debug-assertions-tools = rust.debug-assertions (boolean) # Whether or not to leave debug! and trace! calls in the rust binary. # @@ -591,22 +586,22 @@ # # If you see a message from `tracing` saying "some trace filter directives would enable traces that # are disabled statically" because `max_level_info` is enabled, set this value to `true`. -#debug-logging = rust.debug-assertions (boolean) +#rust.debug-logging = rust.debug-assertions (boolean) # Whether or not to build rustc, tools and the libraries with randomized type layout -#randomize-layout = false +#rust.randomize-layout = false # Whether or not overflow checks are enabled for the compiler and standard # library. # # Defaults to rust.debug value -#overflow-checks = rust.debug (boolean) +#rust.overflow-checks = rust.debug (boolean) # Whether or not overflow checks are enabled for the standard library. # Overrides the `overflow-checks` option, if defined. # # Defaults to rust.overflow-checks value -#overflow-checks-std = rust.overflow-checks (boolean) +#rust.overflow-checks-std = rust.overflow-checks (boolean) # Debuginfo level for most of Rust code, corresponds to the `-C debuginfo=N` option of `rustc`. # See https://doc.rust-lang.org/rustc/codegen-options/index.html#debuginfo for available options. @@ -617,20 +612,20 @@ # # Note that debuginfo-level = 2 generates several gigabytes of debuginfo # and will slow down the linking process significantly. -#debuginfo-level = if rust.debug { 1 } else { 0 } +#rust.debuginfo-level = if rust.debug { 1 } else { 0 } # Debuginfo level for the compiler. -#debuginfo-level-rustc = rust.debuginfo-level +#rust.debuginfo-level-rustc = rust.debuginfo-level # Debuginfo level for the standard library. -#debuginfo-level-std = rust.debuginfo-level +#rust.debuginfo-level-std = rust.debuginfo-level # Debuginfo level for the tools. -#debuginfo-level-tools = rust.debuginfo-level +#rust.debuginfo-level-tools = rust.debuginfo-level # Debuginfo level for the test suites run with compiletest. # FIXME(#61117): Some tests fail when this option is enabled. -#debuginfo-level-tests = 0 +#rust.debuginfo-level-tests = 0 # Should rustc and the standard library be built with split debuginfo? Default # is platform dependent. @@ -640,13 +635,13 @@ # The value specified here is only used when targeting the `build.build` triple, # and is overridden by `target..split-debuginfo` if specified. # -#split-debuginfo = see target..split-debuginfo +#rust.split-debuginfo = see target..split-debuginfo # Whether or not `panic!`s generate backtraces (RUST_BACKTRACE) -#backtrace = true +#rust.backtrace = true # Whether to always use incremental compilation when building rustc -#incremental = false +#rust.incremental = false # The default linker that will be hard-coded into the generated # compiler for targets that don't specify a default linker explicitly @@ -656,7 +651,7 @@ # setting. # # See https://doc.rust-lang.org/rustc/codegen-options/index.html#linker for more information. -#default-linker = (path) +#rust.default-linker = (path) # The "channel" for the Rust build to produce. The stable/beta channels only # allow using stable features, whereas the nightly and dev channels allow using @@ -665,7 +660,7 @@ # You can set the channel to "auto-detect" to load the channel name from `src/ci/channel`. # # If using tarball sources, default value is "auto-detect", otherwise, it's "dev". -#channel = if "is a tarball source" { "auto-detect" } else { "dev" } +#rust.channel = if "is a tarball source" { "auto-detect" } else { "dev" } # The root location of the musl installation directory. The library directory # will also need to contain libunwind.a for an unwinding implementation. Note @@ -673,65 +668,65 @@ # linked binaries. # # Defaults to /usr on musl hosts. Has no default otherwise. -#musl-root = (path) +#rust.musl-root = (path) # By default the `rustc` executable is built with `-Wl,-rpath` flags on Unix # platforms to ensure that the compiler is usable by default from the build # directory (as it links to a number of dynamic libraries). This may not be # desired in distributions, for example. -#rpath = true +#rust.rpath = true # Indicates whether symbols should be stripped using `-Cstrip=symbols`. -#strip = false +#rust.strip = false # Forces frame pointers to be used with `-Cforce-frame-pointers`. # This can be helpful for profiling at a small performance cost. -#frame-pointers = false +#rust.frame-pointers = false # Indicates whether stack protectors should be used # via the unstable option `-Zstack-protector`. # # Valid options are : `none`(default),`basic`,`strong`, or `all`. # `strong` and `basic` options may be buggy and are not recommended, see rust-lang/rust#114903. -#stack-protector = "none" +#rust.stack-protector = "none" # Prints each test name as it is executed, to help debug issues in the test harness itself. -#verbose-tests = if is_verbose { true } else { false } +#rust.verbose-tests = if is_verbose { true } else { false } # Flag indicating whether tests are compiled with optimizations (the -O flag). -#optimize-tests = true +#rust.optimize-tests = true # Flag indicating whether codegen tests will be run or not. If you get an error # saying that the FileCheck executable is missing, you may want to disable this. # Also see the target's llvm-filecheck option. -#codegen-tests = true +#rust.codegen-tests = true # Flag indicating whether git info will be retrieved from .git automatically. # Having the git information can cause a lot of rebuilds during development. -#omit-git-hash = if rust.channel == "dev" { true } else { false } +#rust.omit-git-hash = if rust.channel == "dev" { true } else { false } # Whether to create a source tarball by default when running `x dist`. # # You can still build a source tarball when this is disabled by explicitly passing `x dist rustc-src`. -#dist-src = true +#rust.dist-src = true # After building or testing an optional component (e.g. the nomicon or reference), append the # result (broken, compiling, testing) into this JSON file. -#save-toolstates = (path) +#rust.save-toolstates = (path) # This is an array of the codegen backends that will be compiled for the rustc # that's being compiled. The default is to only build the LLVM codegen backend, # and currently the only standard options supported are `"llvm"`, `"cranelift"` # and `"gcc"`. The first backend in this list will be used as default by rustc # when no explicit backend is specified. -#codegen-backends = ["llvm"] +#rust.codegen-backends = ["llvm"] # Indicates whether LLD will be compiled and made available in the sysroot for rustc to execute, and # whether to set it as rustc's default linker on `x86_64-unknown-linux-gnu`. This will also only be # when *not* building an external LLVM (so only when using `download-ci-llvm` or building LLVM from # the in-tree source): setting `llvm-config` in the `[target.x86_64-unknown-linux-gnu]` section will # make this default to false. -#lld = false in all cases, except on `x86_64-unknown-linux-gnu` as described above, where it is true +#rust.lld = false in all cases, except on `x86_64-unknown-linux-gnu` as described above, where it is true # Indicates whether LLD will be used to link Rust crates during bootstrap on # supported platforms. @@ -742,56 +737,56 @@ # On MSVC, LLD will not be used if we're cross linking. # # Explicitly setting the linker for a target will override this option when targeting MSVC. -#use-lld = false +#rust.use-lld = false # Indicates whether some LLVM tools, like llvm-objdump, will be made available in the # sysroot. -#llvm-tools = true +#rust.llvm-tools = true # Indicates whether the `self-contained` llvm-bitcode-linker, will be made available # in the sysroot. It is required for running nvptx tests. -#llvm-bitcode-linker = false +#rust.llvm-bitcode-linker = false # Whether to deny warnings in crates -#deny-warnings = true +#rust.deny-warnings = true # Print backtrace on internal compiler errors during bootstrap -#backtrace-on-ice = false +#rust.backtrace-on-ice = false # Whether to verify generated LLVM IR -#verify-llvm-ir = false +#rust.verify-llvm-ir = false # Compile the compiler with a non-default ThinLTO import limit. This import # limit controls the maximum size of functions imported by ThinLTO. Decreasing # will make code compile faster at the expense of lower runtime performance. -#thin-lto-import-instr-limit = if incremental { 10 } else { LLVM default (currently 100) } +#rust.thin-lto-import-instr-limit = if incremental { 10 } else { LLVM default (currently 100) } # Map debuginfo paths to `/rust/$sha/...`. # Useful for reproducible builds. Generally only set for releases -#remap-debuginfo = false +#rust.remap-debuginfo = false # Link the compiler and LLVM against `jemalloc` instead of the default libc allocator. # This option is only tested on Linux and OSX. It can also be configured per-target in the # [target.] section. -#jemalloc = false +#rust.jemalloc = false # Run tests in various test suites with the "nll compare mode" in addition to # running the tests in normal mode. Largely only used on CI and during local # development of NLL -#test-compare-mode = false +#rust.test-compare-mode = false # Global default for llvm-libunwind for all targets. See the target-specific # documentation for llvm-libunwind below. Note that the target-specific # option will override this if set. -#llvm-libunwind = 'no' +#rust.llvm-libunwind = 'no' # Enable Windows Control Flow Guard checks in the standard library. # This only applies from stage 1 onwards, and only for Windows targets. -#control-flow-guard = false +#rust.control-flow-guard = false # Enable Windows EHCont Guard checks in the standard library. # This only applies from stage 1 onwards, and only for Windows targets. -#ehcont-guard = false +#rust.ehcont-guard = false # Enable symbol-mangling-version v0. This can be helpful when profiling rustc, # as generics will be preserved in symbols (rather than erased into opaque T). @@ -799,16 +794,16 @@ # compiler and its tools and the legacy scheme will be used when compiling the # standard library. # If an explicit setting is given, it will be used for all parts of the codebase. -#new-symbol-mangling = true|false (see comment) +#rust.new-symbol-mangling = true|false (see comment) # Select LTO mode that will be used for compiling rustc. By default, thin local LTO # (LTO within a single crate) is used (like for any Rust crate). You can also select # "thin" or "fat" to apply Thin/Fat LTO to the `rustc_driver` dylib, or "off" to disable # LTO entirely. -#lto = "thin-local" +#rust.lto = "thin-local" # Build compiler with the optimization enabled and -Zvalidate-mir, currently only for `std` -#validate-mir-opts = 3 +#rust.validate-mir-opts = 3 # Configure `std` features used during bootstrap. # @@ -822,7 +817,57 @@ # # Since libstd also builds libcore and liballoc as dependencies and all their features are mirrored # as libstd features, this option can also be used to configure features such as optimize_for_size. -#std-features = ["panic_unwind"] +#rust.std-features = ["panic_unwind"] + +# ============================================================================= +# Distribution options +# +# These options are related to distribution, mostly for the Rust project itself. +# You probably won't need to concern yourself with any of these options +# ============================================================================= + +# This is the folder of artifacts that the build system will sign. All files in +# this directory will be signed with the default gpg key using the system `gpg` +# binary. The `asc` and `sha256` files will all be output into the standard dist +# output folder (currently `build/dist`) +# +# This folder should be populated ahead of time before the build system is +# invoked. +#dist.sign-folder = (path) + +# The remote address that all artifacts will eventually be uploaded to. The +# build system generates manifests which will point to these urls, and for the +# manifests to be correct they'll have to have the right URLs encoded. +# +# Note that this address should not contain a trailing slash as file names will +# be appended to it. +#dist.upload-addr = (URL) + +# Whether to build a plain source tarball to upload +# We disable that on Windows not to override the one already uploaded on S3 +# as the one built on Windows will contain backslashes in paths causing problems +# on linux +#dist.src-tarball = true + +# List of compression formats to use when generating dist tarballs. The list of +# formats is provided to rust-installer, which must support all of them. +# +# This list must be non-empty. +#dist.compression-formats = ["gz", "xz"] + +# How much time should be spent compressing the tarballs. The better the +# compression profile, the longer compression will take. +# +# Available options: fast, balanced, best +#dist.compression-profile = "fast" + +# Copy the linker, DLLs, and various libraries from MinGW into the Rust toolchain. +# Only applies when the host or target is pc-windows-gnu. +#dist.include-mingw-linker = true + +# Whether to vendor dependencies for the dist tarball. +#dist.vendor = if "is a tarball source" || "is a git repository" { true } else { false } + # ============================================================================= # Options for specific targets @@ -973,53 +1018,3 @@ # Link the compiler and LLVM against `jemalloc` instead of the default libc allocator. # This overrides the global `rust.jemalloc` option. See that option for more info. #jemalloc = rust.jemalloc (bool) - -# ============================================================================= -# Distribution options -# -# These options are related to distribution, mostly for the Rust project itself. -# You probably won't need to concern yourself with any of these options -# ============================================================================= -[dist] - -# This is the folder of artifacts that the build system will sign. All files in -# this directory will be signed with the default gpg key using the system `gpg` -# binary. The `asc` and `sha256` files will all be output into the standard dist -# output folder (currently `build/dist`) -# -# This folder should be populated ahead of time before the build system is -# invoked. -#sign-folder = (path) - -# The remote address that all artifacts will eventually be uploaded to. The -# build system generates manifests which will point to these urls, and for the -# manifests to be correct they'll have to have the right URLs encoded. -# -# Note that this address should not contain a trailing slash as file names will -# be appended to it. -#upload-addr = (URL) - -# Whether to build a plain source tarball to upload -# We disable that on Windows not to override the one already uploaded on S3 -# as the one built on Windows will contain backslashes in paths causing problems -# on linux -#src-tarball = true - -# List of compression formats to use when generating dist tarballs. The list of -# formats is provided to rust-installer, which must support all of them. -# -# This list must be non-empty. -#compression-formats = ["gz", "xz"] - -# How much time should be spent compressing the tarballs. The better the -# compression profile, the longer compression will take. -# -# Available options: fast, balanced, best -#compression-profile = "fast" - -# Copy the linker, DLLs, and various libraries from MinGW into the Rust toolchain. -# Only applies when the host or target is pc-windows-gnu. -#include-mingw-linker = true - -# Whether to vendor dependencies for the dist tarball. -#vendor = if "is a tarball source" || "is a git repository" { true } else { false } From 01fbeb806570a94e1520b6b74e6db70e88574627 Mon Sep 17 00:00:00 2001 From: binarycat Date: Tue, 17 Jun 2025 15:19:51 -0500 Subject: [PATCH 02/11] update configure.py to handle new bootstrap.example.toml --- bootstrap.example.toml | 2 +- src/bootstrap/configure.py | 31 ++++++++++++++++++++++++------- 2 files changed, 25 insertions(+), 8 deletions(-) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 38c3195deb9d7..fade30c0c33e0 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -385,7 +385,7 @@ # # The default value for the `features` array is `[]`. However, please note that other flags in # `bootstrap.toml` might influence the features enabled for some tools. -#tool.TOOL_NAME.features = [FEATURE1, FEATURE2] +#build.tool.TOOL_NAME.features = [FEATURE1, FEATURE2] # Verbosity level: 0 == not verbose, 1 == verbose, 2 == very verbose, 3 == print environment variables on each rustc invocation #build.verbose = 0 diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 0d4d6e0ff54c6..ce9290620cb55 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -6,6 +6,7 @@ import shlex import sys import os +import re rust_dir = os.path.dirname(os.path.abspath(__file__)) rust_dir = os.path.dirname(rust_dir) @@ -585,16 +586,31 @@ def parse_example_config(known_args, config): section_order = [None] targets = {} top_level_keys = [] + comment_lines = [] with open(rust_dir + "/bootstrap.example.toml") as example_config: example_lines = example_config.read().split("\n") for line in example_lines: - if cur_section is None: - if line.count("=") == 1: - top_level_key = line.split("=")[0] - top_level_key = top_level_key.strip(" #") - top_level_keys.append(top_level_key) - if line.startswith("["): + if line.count("=") == 1 and not line.startswith("# "): + key = line.split("=")[0] + key = key.strip(" #") + parts = key.split(".") + if len(parts) > 1: + cur_section = parts[0] + if cur_section not in sections: + sections[cur_section] = ["[" + cur_section + "]"] + section_order.append(cur_section) + elif cur_section is None: + top_level_keys.append(key) + # put the comment lines within the start of + # a new section, not outside it. + sections[cur_section] += comment_lines + comment_lines = [] + # remove just the `section.` part from the line, if present. + sections[cur_section].append( + re.sub("(#?)([a-zA-Z_-]+\\.)?(.*)", "\\1\\3", line) + ) + elif line.startswith("["): cur_section = line[1:-1] if cur_section.startswith("target"): cur_section = "target" @@ -605,8 +621,9 @@ def parse_example_config(known_args, config): sections[cur_section] = [line] section_order.append(cur_section) else: - sections[cur_section].append(line) + comment_lines.append(line) + sections[cur_section] += comment_lines # Fill out the `targets` array by giving all configured targets a copy of the # `target` section we just loaded from the example config configured_targets = [build(known_args)] From bedc0eaa9d63f4fae716e7f737b50dde2ff2b59d Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 20 Jun 2025 11:35:53 -0500 Subject: [PATCH 03/11] bootstrap.example.toml: add note explaining toml --- bootstrap.example.toml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index fade30c0c33e0..cc1ea796a0288 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -8,6 +8,14 @@ # `bootstrap.toml` in the current directory of a build for build configuration, but # a custom configuration file can also be specified with `--config` to the build # system. +# +# Note that the following are equivelent, for more details see . +# +# build.verbose = 1 +# +# [build] +# verbose = 1 + # ============================================================================= # Global Settings From a759f05a71fa9faf79087f8621865462aa166a48 Mon Sep 17 00:00:00 2001 From: binarycat Date: Fri, 20 Jun 2025 16:17:31 -0500 Subject: [PATCH 04/11] configure.py: fix edge case --- src/bootstrap/configure.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index ce9290620cb55..c077555b90699 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -591,7 +591,7 @@ def parse_example_config(known_args, config): with open(rust_dir + "/bootstrap.example.toml") as example_config: example_lines = example_config.read().split("\n") for line in example_lines: - if line.count("=") == 1 and not line.startswith("# "): + if line.count("=") >= 1 and not line.startswith("# "): key = line.split("=")[0] key = key.strip(" #") parts = key.split(".") From 993344257d8d2ba2ea808c5f22f0648b5f3a7fdf Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 20 Jun 2025 14:44:20 +0000 Subject: [PATCH 05/11] Make `PartialEq` a `const_trait` --- library/core/src/cmp.rs | 25 ++- tests/ui/consts/const_cmp_type_id.rs | 5 +- tests/ui/consts/const_cmp_type_id.stderr | 26 +-- tests/ui/consts/fn_trait_refs.stderr | 18 +- .../ui/consts/issue-73976-monomorphic.stderr | 8 +- tests/ui/consts/issue-90870.rs | 15 +- tests/ui/consts/issue-90870.stderr | 58 ++++- .../call-const-trait-method-pass.rs | 3 +- .../call-const-trait-method-pass.stderr | 20 -- .../const-traits/call-generic-in-impl.rs | 3 +- .../const-traits/call-generic-in-impl.stderr | 30 --- .../const-traits/call-generic-method-chain.rs | 3 +- .../call-generic-method-chain.stderr | 66 ------ .../call-generic-method-dup-bound.rs | 3 +- .../call-generic-method-dup-bound.stderr | 74 ------- .../const-traits/call-generic-method-fail.rs | 2 +- .../call-generic-method-fail.stderr | 6 +- .../const-traits/call-generic-method-pass.rs | 3 +- .../call-generic-method-pass.stderr | 47 ---- .../const-traits/const-impl-trait.stderr | 200 +----------------- .../const_derives/derive-const-use.stderr | 58 +---- .../const_derives/derive-const-with-params.rs | 3 +- .../derive-const-with-params.stderr | 35 --- .../ice-112822-expected-type-for-param.rs | 1 - .../ice-112822-expected-type-for-param.stderr | 11 +- 25 files changed, 117 insertions(+), 606 deletions(-) delete mode 100644 tests/ui/traits/const-traits/call-const-trait-method-pass.stderr delete mode 100644 tests/ui/traits/const-traits/call-generic-in-impl.stderr delete mode 100644 tests/ui/traits/const-traits/call-generic-method-chain.stderr delete mode 100644 tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr delete mode 100644 tests/ui/traits/const-traits/call-generic-method-pass.stderr delete mode 100644 tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 5cb1a14847702..0aa8f47462dbd 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -247,6 +247,8 @@ use crate::ops::ControlFlow; append_const_msg )] #[rustc_diagnostic_item = "PartialEq"] +#[const_trait] +#[rustc_const_unstable(feature = "const_trait_impl", issue = "67792")] pub trait PartialEq: PointeeSized { /// Tests for `self` and `other` values to be equal, and is used by `==`. #[must_use] @@ -1811,7 +1813,8 @@ mod impls { macro_rules! partial_eq_impl { ($($t:ty)*) => ($( #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq for $t { + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialEq for $t { #[inline] fn eq(&self, other: &Self) -> bool { *self == *other } #[inline] @@ -2018,9 +2021,10 @@ mod impls { // & pointers #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq<&B> for &A + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialEq<&B> for &A where - A: PartialEq, + A: ~const PartialEq, { #[inline] fn eq(&self, other: &&B) -> bool { @@ -2089,9 +2093,10 @@ mod impls { // &mut pointers #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq<&mut B> for &mut A + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialEq<&mut B> for &mut A where - A: PartialEq, + A: ~const PartialEq, { #[inline] fn eq(&self, other: &&mut B) -> bool { @@ -2158,9 +2163,10 @@ mod impls { impl Eq for &mut A where A: Eq {} #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq<&mut B> for &A + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialEq<&mut B> for &A where - A: PartialEq, + A: ~const PartialEq, { #[inline] fn eq(&self, other: &&mut B) -> bool { @@ -2173,9 +2179,10 @@ mod impls { } #[stable(feature = "rust1", since = "1.0.0")] - impl PartialEq<&B> for &mut A + #[rustc_const_unstable(feature = "const_cmp", issue = "92391")] + impl const PartialEq<&B> for &mut A where - A: PartialEq, + A: ~const PartialEq, { #[inline] fn eq(&self, other: &&B) -> bool { diff --git a/tests/ui/consts/const_cmp_type_id.rs b/tests/ui/consts/const_cmp_type_id.rs index e89b8d3778783..dca0615083a78 100644 --- a/tests/ui/consts/const_cmp_type_id.rs +++ b/tests/ui/consts/const_cmp_type_id.rs @@ -6,11 +6,10 @@ use std::any::TypeId; fn main() { const { assert!(TypeId::of::() == TypeId::of::()); - //~^ ERROR cannot call non-const operator in constants + //~^ ERROR the trait bound `TypeId: const PartialEq` is not satisfied assert!(TypeId::of::<()>() != TypeId::of::()); - //~^ ERROR cannot call non-const operator in constants + //~^ ERROR the trait bound `TypeId: const PartialEq` is not satisfied let _a = TypeId::of::() < TypeId::of::(); - //~^ ERROR cannot call non-const operator in constants // can't assert `_a` because it is not deterministic // FIXME(const_trait_impl) make it pass } diff --git a/tests/ui/consts/const_cmp_type_id.stderr b/tests/ui/consts/const_cmp_type_id.stderr index 62f8d42c0e688..a8242a200eff1 100644 --- a/tests/ui/consts/const_cmp_type_id.stderr +++ b/tests/ui/consts/const_cmp_type_id.stderr @@ -1,33 +1,15 @@ -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `TypeId: const PartialEq` is not satisfied --> $DIR/const_cmp_type_id.rs:8:17 | LL | assert!(TypeId::of::() == TypeId::of::()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `TypeId: const PartialEq` is not satisfied --> $DIR/const_cmp_type_id.rs:10:17 | LL | assert!(TypeId::of::<()>() != TypeId::of::()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constants - --> $DIR/const_cmp_type_id.rs:12:18 - | -LL | let _a = TypeId::of::() < TypeId::of::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr index d688bfbde2bc2..7dc0804988963 100644 --- a/tests/ui/consts/fn_trait_refs.stderr +++ b/tests/ui/consts/fn_trait_refs.stderr @@ -4,12 +4,6 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls` LL | #![feature(const_fn_trait_ref_impls)] | ^^^^^^^^^^^^^^^^^^^^^^^^ -error[E0635]: unknown feature `const_cmp` - --> $DIR/fn_trait_refs.rs:7:12 - | -LL | #![feature(const_cmp)] - | ^^^^^^^^^ - error: `~const` can only be applied to `#[const_trait]` traits --> $DIR/fn_trait_refs.rs:14:8 | @@ -155,21 +149,17 @@ note: `FnMut` can't be used with `~const` because it isn't annotated with `#[con --> $SRC_DIR/core/src/ops/function.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `(i32, i32, i32): const PartialEq` is not satisfied --> $DIR/fn_trait_refs.rs:71:17 | LL | assert!(test_one == (1, 1, 1)); | ^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constants +error[E0277]: the trait bound `(i32, i32): const PartialEq` is not satisfied --> $DIR/fn_trait_refs.rs:74:17 | LL | assert!(test_two == (2, 2)); | ^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants error[E0015]: cannot call non-const closure in constant functions --> $DIR/fn_trait_refs.rs:16:5 @@ -195,7 +185,7 @@ LL | f() | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error: aborting due to 22 previous errors +error: aborting due to 21 previous errors -Some errors have detailed explanations: E0015, E0635. +Some errors have detailed explanations: E0015, E0277, E0635. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/consts/issue-73976-monomorphic.stderr b/tests/ui/consts/issue-73976-monomorphic.stderr index ef754b23ff06e..e5b32e0c4adff 100644 --- a/tests/ui/consts/issue-73976-monomorphic.stderr +++ b/tests/ui/consts/issue-73976-monomorphic.stderr @@ -1,13 +1,9 @@ -error[E0015]: cannot call non-const operator in constant functions +error[E0277]: the trait bound `TypeId: ~const PartialEq` is not satisfied --> $DIR/issue-73976-monomorphic.rs:21:5 | LL | GetTypeId::::VALUE == GetTypeId::::VALUE | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: impl defined here, but it is not `const` - --> $SRC_DIR/core/src/any.rs:LL:COL - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/consts/issue-90870.rs b/tests/ui/consts/issue-90870.rs index b62769a33f8e2..f807ae75ee5e1 100644 --- a/tests/ui/consts/issue-90870.rs +++ b/tests/ui/consts/issue-90870.rs @@ -3,22 +3,31 @@ #![allow(dead_code)] const fn f(a: &u8, b: &u8) -> bool { + //~^ HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable a == b - //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~^ ERROR: cannot call conditionally-const operator in constant functions + //~| ERROR: `PartialEq` is not yet stable as a const trait //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable } const fn g(a: &&&&i64, b: &&&&i64) -> bool { a == b - //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~^ ERROR: cannot call conditionally-const operator in constant functions + //~| ERROR: `PartialEq` is not yet stable as a const trait //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable } const fn h(mut a: &[u8], mut b: &[u8]) -> bool { while let ([l, at @ ..], [r, bt @ ..]) = (a, b) { if l == r { - //~^ ERROR: cannot call non-const operator in constant functions [E0015] + //~^ ERROR: cannot call conditionally-const operator in constant functions + //~| ERROR: `PartialEq` is not yet stable as a const trait //~| HELP: consider dereferencing here + //~| HELP: add `#![feature(const_trait_impl)]` to the crate attributes to enable a = at; b = bt; } else { diff --git a/tests/ui/consts/issue-90870.stderr b/tests/ui/consts/issue-90870.stderr index ea987920d7d33..8d6f21fd82fbe 100644 --- a/tests/ui/consts/issue-90870.stderr +++ b/tests/ui/consts/issue-90870.stderr @@ -1,39 +1,81 @@ -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:6:5 +error[E0658]: cannot call conditionally-const operator in constant functions + --> $DIR/issue-90870.rs:9:5 | LL | a == b | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date help: consider dereferencing here | LL | *a == *b | + + -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:12:5 +error: `PartialEq` is not yet stable as a const trait + --> $DIR/issue-90870.rs:9:5 + | +LL | a == b + | ^^^^^^ + | +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error[E0658]: cannot call conditionally-const operator in constant functions + --> $DIR/issue-90870.rs:17:5 | LL | a == b | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date help: consider dereferencing here | LL | ****a == ****b | ++++ ++++ -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/issue-90870.rs:19:12 +error: `PartialEq` is not yet stable as a const trait + --> $DIR/issue-90870.rs:17:5 + | +LL | a == b + | ^^^^^^ + | +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error[E0658]: cannot call conditionally-const operator in constant functions + --> $DIR/issue-90870.rs:26:12 | LL | if l == r { | ^^^^^^ | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + = note: see issue #67792 for more information + = help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date help: consider dereferencing here | LL | if *l == *r { | + + -error: aborting due to 3 previous errors +error: `PartialEq` is not yet stable as a const trait + --> $DIR/issue-90870.rs:26:12 + | +LL | if l == r { + | ^^^^^^ + | +help: add `#![feature(const_trait_impl)]` to the crate attributes to enable + | +LL + #![feature(const_trait_impl)] + | + +error: aborting due to 6 previous errors -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs index 3004647ede075..d66a11490c59d 100644 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.rs +++ b/tests/ui/traits/const-traits/call-const-trait-method-pass.rs @@ -1,6 +1,5 @@ -//@ known-bug: #110395 - #![feature(const_trait_impl, const_ops)] +//@ check-pass struct Int(i32); diff --git a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr b/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr deleted file mode 100644 index 7746f103ac368..0000000000000 --- a/tests/ui/traits/const-traits/call-const-trait-method-pass.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/call-const-trait-method-pass.rs:15:12 - | -LL | impl const PartialEq for Int { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-const-trait-method-pass.rs:20:15 - | -LL | !self.eq(other) - | ^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.rs b/tests/ui/traits/const-traits/call-generic-in-impl.rs index 6149dc3d12635..b63458b39e95d 100644 --- a/tests/ui/traits/const-traits/call-generic-in-impl.rs +++ b/tests/ui/traits/const-traits/call-generic-in-impl.rs @@ -1,5 +1,4 @@ -//@ known-bug: #110395 -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(const_trait_impl)] #[const_trait] diff --git a/tests/ui/traits/const-traits/call-generic-in-impl.stderr b/tests/ui/traits/const-traits/call-generic-in-impl.stderr deleted file mode 100644 index a45dfd95b4a46..0000000000000 --- a/tests/ui/traits/const-traits/call-generic-in-impl.stderr +++ /dev/null @@ -1,30 +0,0 @@ -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-in-impl.rs:10:9 - | -LL | impl const MyPartialEq for T { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-in-impl.rs:10:9 - | -LL | impl const MyPartialEq for T { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-generic-in-impl.rs:12:9 - | -LL | PartialEq::eq(self, other) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 3 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.rs b/tests/ui/traits/const-traits/call-generic-method-chain.rs index 74beab71208af..b515c0e711da4 100644 --- a/tests/ui/traits/const-traits/call-generic-method-chain.rs +++ b/tests/ui/traits/const-traits/call-generic-method-chain.rs @@ -1,8 +1,7 @@ //! Basic test for calling methods on generic type parameters in `const fn`. -//@ known-bug: #110395 //@ compile-flags: -Znext-solver -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/call-generic-method-chain.stderr b/tests/ui/traits/const-traits/call-generic-method-chain.stderr deleted file mode 100644 index 40b4f14733f0c..0000000000000 --- a/tests/ui/traits/const-traits/call-generic-method-chain.stderr +++ /dev/null @@ -1,66 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/call-generic-method-chain.rs:11:12 - | -LL | impl const PartialEq for S { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-chain.rs:20:25 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-chain.rs:20:25 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-chain.rs:24:33 - | -LL | const fn equals_self_wrapper(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-chain.rs:24:33 - | -LL | const fn equals_self_wrapper(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-chain.rs:21:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-generic-method-chain.rs:16:15 - | -LL | !self.eq(other) - | ^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 7 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs index ec615d8484cda..fdc439845ace7 100644 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs +++ b/tests/ui/traits/const-traits/call-generic-method-dup-bound.rs @@ -1,6 +1,5 @@ //@ compile-flags: -Znext-solver -//@ known-bug: #110395 -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr b/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr deleted file mode 100644 index c74f5cf786c1e..0000000000000 --- a/tests/ui/traits/const-traits/call-generic-method-dup-bound.stderr +++ /dev/null @@ -1,74 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/call-generic-method-dup-bound.rs:9:12 - | -LL | impl const PartialEq for S { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-dup-bound.rs:20:37 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-dup-bound.rs:20:37 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-dup-bound.rs:27:30 - | -LL | const fn equals_self2(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-dup-bound.rs:27:30 - | -LL | const fn equals_self2(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-dup-bound.rs:21:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-generic-method-dup-bound.rs:14:15 - | -LL | !self.eq(other) - | ^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-dup-bound.rs:28:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 8 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.rs b/tests/ui/traits/const-traits/call-generic-method-fail.rs index 66881334a2985..3ab5cc58ce3ca 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.rs +++ b/tests/ui/traits/const-traits/call-generic-method-fail.rs @@ -3,7 +3,7 @@ pub const fn equals_self(t: &T) -> bool { *t == *t - //~^ ERROR cannot call non-const operator in constant functions + //~^ ERROR the trait bound `T: ~const PartialEq` is not satisfied } fn main() {} diff --git a/tests/ui/traits/const-traits/call-generic-method-fail.stderr b/tests/ui/traits/const-traits/call-generic-method-fail.stderr index 6bacb986fef0c..9facf80ee8761 100644 --- a/tests/ui/traits/const-traits/call-generic-method-fail.stderr +++ b/tests/ui/traits/const-traits/call-generic-method-fail.stderr @@ -1,11 +1,9 @@ -error[E0015]: cannot call non-const operator in constant functions +error[E0277]: the trait bound `T: ~const PartialEq` is not satisfied --> $DIR/call-generic-method-fail.rs:5:5 | LL | *t == *t | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.rs b/tests/ui/traits/const-traits/call-generic-method-pass.rs index af793b8da031b..bc671c897f075 100644 --- a/tests/ui/traits/const-traits/call-generic-method-pass.rs +++ b/tests/ui/traits/const-traits/call-generic-method-pass.rs @@ -1,8 +1,7 @@ //! Basic test for calling methods on generic type parameters in `const fn`. //@ compile-flags: -Znext-solver -//@ known-bug: #110395 -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/call-generic-method-pass.stderr b/tests/ui/traits/const-traits/call-generic-method-pass.stderr deleted file mode 100644 index 1a33ff5ab450f..0000000000000 --- a/tests/ui/traits/const-traits/call-generic-method-pass.stderr +++ /dev/null @@ -1,47 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/call-generic-method-pass.rs:11:12 - | -LL | impl const PartialEq for S { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-pass.rs:20:25 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/call-generic-method-pass.rs:20:25 - | -LL | const fn equals_self(t: &T) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/call-generic-method-pass.rs:21:5 - | -LL | *t == *t - | ^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const method `::eq` in constant functions - --> $DIR/call-generic-method-pass.rs:16:15 - | -LL | !self.eq(other) - | ^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 5 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const-impl-trait.stderr b/tests/ui/traits/const-traits/const-impl-trait.stderr index 6783cec3960d6..ee922f9689edd 100644 --- a/tests/ui/traits/const-traits/const-impl-trait.stderr +++ b/tests/ui/traits/const-traits/const-impl-trait.stderr @@ -1,197 +1,17 @@ -error[E0635]: unknown feature `const_cmp` - --> $DIR/const-impl-trait.rs:7:30 +error[E0277]: the trait bound `(): const PartialEq` is not satisfied + --> $DIR/const-impl-trait.rs:34:17 | -LL | #![feature(const_trait_impl, const_cmp, const_destruct)] - | ^^^^^^^^^ - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:11:23 - | -LL | const fn cmp(a: &impl ~const PartialEq) -> bool { - | ^^^^^^ can't be applied to `PartialEq` +LL | assert!(cmp(&())); + | --- ^^^ + | | + | required by a bound introduced by this call | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits +note: required by a bound in `cmp` --> $DIR/const-impl-trait.rs:11:23 | LL | const fn cmp(a: &impl ~const PartialEq) -> bool { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:16:13 - | -LL | x: impl ~const PartialEq + ~const Destruct, - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:16:13 - | -LL | x: impl ~const PartialEq + ~const Destruct, - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:17:11 - | -LL | ) -> impl ~const PartialEq + ~const Destruct { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:17:11 - | -LL | ) -> impl ~const PartialEq + ~const Destruct { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:27:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:17:11 - | -LL | ) -> impl ~const PartialEq + ~const Destruct { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:27:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:27:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy { - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: `~const` can only be applied to `#[const_trait]` traits - --> $DIR/const-impl-trait.rs:23:22 - | -LL | fn huh() -> impl ~const PartialEq + ~const Destruct + Copy; - | ^^^^^^ can't be applied to `PartialEq` - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0015]: cannot call non-const operator in constants - --> $DIR/const-impl-trait.rs:35:13 - | -LL | assert!(wrap(123) == wrap(123)); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constants - --> $DIR/const-impl-trait.rs:36:13 - | -LL | assert!(wrap(123) != wrap(456)); - | ^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constants - --> $DIR/const-impl-trait.rs:38:13 - | -LL | assert!(x == x); - | ^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/const-impl-trait.rs:12:5 - | -LL | a == a - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants + | ^^^^^^^^^^^^^^^^ required by this bound in `cmp` -error: aborting due to 21 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0015, E0635. -For more information about an error, try `rustc --explain E0015`. +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr index 8297911a3f3c7..87ac78908bbaf 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr +++ b/tests/ui/traits/const-traits/const_derives/derive-const-use.stderr @@ -1,9 +1,3 @@ -error[E0635]: unknown feature `const_cmp` - --> $DIR/derive-const-use.rs:3:30 - | -LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)] - | ^^^^^^^^^ - error[E0635]: unknown feature `const_default_impls` --> $DIR/derive-const-use.rs:3:41 | @@ -28,23 +22,13 @@ LL | #[derive_const(Default, PartialEq)] = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` = note: adding a non-const method body in the future would be a breaking change -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/derive-const-use.rs:11:12 - | -LL | impl const PartialEq for A { - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/derive-const-use.rs:15:25 +error[E0277]: the trait bound `(): ~const PartialEq` is not satisfied + --> $DIR/derive-const-use.rs:16:14 | LL | #[derive_const(Default, PartialEq)] - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change + | --------- in this derive macro expansion +LL | pub struct S((), A); + | ^^ error[E0015]: cannot call non-const associated function `::default` in constants --> $DIR/derive-const-use.rs:18:35 @@ -54,14 +38,6 @@ LL | const _: () = assert!(S((), A) == S::default()); | = note: calls in constants are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constants - --> $DIR/derive-const-use.rs:18:23 - | -LL | const _: () = assert!(S((), A) == S::default()); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constants are limited to constant functions, tuple structs and tuple variants - error[E0015]: cannot call non-const associated function `<() as Default>::default` in constant functions --> $DIR/derive-const-use.rs:16:14 | @@ -82,27 +58,7 @@ LL | pub struct S((), A); | = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/derive-const-use.rs:16:14 - | -LL | #[derive_const(Default, PartialEq)] - | --------- in this derive macro expansion -LL | pub struct S((), A); - | ^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/derive-const-use.rs:16:18 - | -LL | #[derive_const(Default, PartialEq)] - | --------- in this derive macro expansion -LL | pub struct S((), A); - | ^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 12 previous errors +error: aborting due to 7 previous errors -Some errors have detailed explanations: E0015, E0635. +Some errors have detailed explanations: E0015, E0277, E0635. For more information about an error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs index 18b224af2780f..b39f97b59382b 100644 --- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs +++ b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.rs @@ -1,5 +1,4 @@ -//@ known-bug: #110395 -// FIXME(const_trait_impl) check-pass +//@ check-pass #![feature(derive_const)] #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr b/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr deleted file mode 100644 index d1dbf62d5666a..0000000000000 --- a/tests/ui/traits/const-traits/const_derives/derive-const-with-params.stderr +++ /dev/null @@ -1,35 +0,0 @@ -error: const `impl` for trait `PartialEq` which is not marked with `#[const_trait]` - --> $DIR/derive-const-with-params.rs:7:16 - | -LL | #[derive_const(PartialEq)] - | ^^^^^^^^^ this trait is not `const` - | - = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const` - = note: adding a non-const method body in the future would be a breaking change - -error: `~const` can only be applied to `#[const_trait]` traits - | -note: `PartialEq` can't be used with `~const` because it isn't annotated with `#[const_trait]` - --> $SRC_DIR/core/src/cmp.rs:LL:COL - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/derive-const-with-params.rs:8:23 - | -LL | #[derive_const(PartialEq)] - | --------- in this derive macro expansion -LL | pub struct Reverse(T); - | ^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/derive-const-with-params.rs:11:5 - | -LL | a == b - | ^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0015`. diff --git a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs index 4cb013b932309..4312d295b113b 100644 --- a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs +++ b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.rs @@ -11,7 +11,6 @@ const fn test() -> impl ~const Fn() { [first, remainder @ ..] => { assert_eq!(first, &b'f'); //~^ ERROR cannot call non-const function - //~| ERROR cannot call non-const operator } [] => panic!(), } diff --git a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr index 8d9371bf9f692..f06bacdeb4e27 100644 --- a/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr +++ b/tests/ui/traits/const-traits/ice-112822-expected-type-for-param.stderr @@ -37,15 +37,6 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_ --> $SRC_DIR/core/src/ops/function.rs:LL:COL = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0015]: cannot call non-const operator in constant functions - --> $DIR/ice-112822-expected-type-for-param.rs:12:17 - | -LL | assert_eq!(first, &b'f'); - | ^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants - = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) - error[E0015]: cannot call non-const function `core::panicking::assert_failed::<&u8, &u8>` in constant functions --> $DIR/ice-112822-expected-type-for-param.rs:12:17 | @@ -55,7 +46,7 @@ LL | assert_eq!(first, &b'f'); = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 6 previous errors +error: aborting due to 5 previous errors Some errors have detailed explanations: E0015, E0658. For more information about an error, try `rustc --explain E0015`. From 9dd7bcb75ac9e513268eb3b20ec10212c777e4c7 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 23 Jun 2025 11:33:23 +0200 Subject: [PATCH 06/11] notify me when rdg is touched --- triagebot.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 4d13eaf1c84c8..6385528e7b6ed 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1168,7 +1168,7 @@ cc = ["@ehuss"] [mentions."src/doc/rustc-dev-guide"] message = "The rustc-dev-guide subtree was changed. If this PR *only* touches the dev guide consider submitting a PR directly to [rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide/pulls) otherwise thank you for updating the dev guide with your changes." -cc = ["@BoxyUwU", "@jieyouxu", "@kobzol"] +cc = ["@BoxyUwU", "@jieyouxu", "@kobzol", "@tshepang"] [mentions."compiler/rustc_codegen_ssa/src/codegen_attrs.rs"] cc = ["@jdonszelmann"] From 2313d4c5718957fd1ce7ae41edee253ca8975663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sun, 22 Jun 2025 22:45:28 +0200 Subject: [PATCH 07/11] test for lint on root node crash --- tests/ui/attributes/lint_on_root.rs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/ui/attributes/lint_on_root.rs diff --git a/tests/ui/attributes/lint_on_root.rs b/tests/ui/attributes/lint_on_root.rs new file mode 100644 index 0000000000000..0ede97c033c76 --- /dev/null +++ b/tests/ui/attributes/lint_on_root.rs @@ -0,0 +1,3 @@ +#![inline = ""] + +fn main() {} From 269b67d6b8529850233b60817773b75c54206962 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Sun, 22 Jun 2025 22:49:22 +0200 Subject: [PATCH 08/11] fix 142891 --- compiler/rustc_middle/src/hir/map.rs | 10 +++++++++- tests/ui/attributes/lint_on_root.rs | 4 ++++ tests/ui/attributes/lint_on_root.stderr | 12 ++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 tests/ui/attributes/lint_on_root.stderr diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 03bb97095a4bf..291707878a342 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -1254,10 +1254,18 @@ pub(crate) fn hir_crate_items(tcx: TyCtxt<'_>, _: ()) -> ModuleItems { body_owners, opaques, nested_bodies, - delayed_lint_items, + mut delayed_lint_items, .. } = collector; + // The crate could have delayed lints too, but would not be picked up by the visitor. + // The `delayed_lint_items` list is smart - it only contains items which we know from + // earlier passes is guaranteed to contain lints. It's a little harder to determine that + // for sure here, so we simply always add the crate to the list. If it has no lints, + // we'll discover that later. The cost of this should be low, there's only one crate + // after all compared to the many items we have we wouldn't want to iterate over later. + delayed_lint_items.push(CRATE_OWNER_ID); + ModuleItems { add_root: true, submodules: submodules.into_boxed_slice(), diff --git a/tests/ui/attributes/lint_on_root.rs b/tests/ui/attributes/lint_on_root.rs index 0ede97c033c76..93d47bf0d714e 100644 --- a/tests/ui/attributes/lint_on_root.rs +++ b/tests/ui/attributes/lint_on_root.rs @@ -1,3 +1,7 @@ +// NOTE: this used to panic in debug builds (by a sanity assertion) +// and not emit any lint on release builds. See https://github.com/rust-lang/rust/issues/142891. #![inline = ""] +//~^ ERROR valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` +//~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! fn main() {} diff --git a/tests/ui/attributes/lint_on_root.stderr b/tests/ui/attributes/lint_on_root.stderr new file mode 100644 index 0000000000000..aaa46e6f54ba0 --- /dev/null +++ b/tests/ui/attributes/lint_on_root.stderr @@ -0,0 +1,12 @@ +error: valid forms for the attribute are `#[inline(always|never)]` and `#[inline]` + --> $DIR/lint_on_root.rs:3:1 + | +LL | #![inline = ""] + | ^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #57571 + = note: `#[deny(ill_formed_attribute_input)]` on by default + +error: aborting due to 1 previous error + From 82cbc3a35e23a804682922d1c04ac51a00b35137 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Fri, 13 Jun 2025 01:36:52 +0200 Subject: [PATCH 09/11] rewrite #[naked] parser --- .../src/attributes.rs | 3 +++ .../src/attributes/codegen_attrs.rs | 19 ++++++++++++++++++- compiler/rustc_attr_parsing/src/context.rs | 3 ++- .../rustc_codegen_ssa/src/codegen_attrs.rs | 2 +- .../rustc_hir_analysis/src/check/check.rs | 3 ++- compiler/rustc_hir_typeck/src/expr.rs | 3 ++- compiler/rustc_hir_typeck/src/lib.rs | 5 +++-- .../rustc_hir_typeck/src/naked_functions.rs | 5 +++-- compiler/rustc_passes/src/check_attr.rs | 14 ++++++++------ compiler/rustc_passes/src/liveness.rs | 3 ++- 10 files changed, 44 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index c7487847e6f26..63db0d0c98823 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -244,6 +244,9 @@ pub enum AttributeKind { reason: Option, }, + /// Represents #[naked] + Naked(Span), + /// Represents `#[no_mangle]` NoMangle(Span), diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index ba4e2935004c7..cf31dd0ace793 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -51,12 +51,29 @@ impl SingleAttributeParser for ColdParser { if !args.no_args() { cx.expected_no_args(args.span().unwrap_or(cx.attr_span)); return None; - }; + } Some(AttributeKind::Cold(cx.attr_span)) } } +pub(crate) struct NakedParser; + +impl SingleAttributeParser for NakedParser { + const PATH: &[rustc_span::Symbol] = &[sym::naked]; + const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; + const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; + const TEMPLATE: AttributeTemplate = template!(Word); + + fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { + if !args.no_args() { + cx.expected_no_args(args.span().unwrap_or(cx.attr_span)); + return None; + } + Some(AttributeKind::Naked(cx.attr_span)) + } +} + pub(crate) struct NoMangleParser; impl SingleAttributeParser for NoMangleParser { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 171995dc9cbd1..bf289c6aae80c 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -15,7 +15,7 @@ use rustc_session::Session; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym}; use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser}; -use crate::attributes::codegen_attrs::{ColdParser, NoMangleParser, OptimizeParser}; +use crate::attributes::codegen_attrs::{ColdParser, NakedParser, NoMangleParser, OptimizeParser}; use crate::attributes::confusables::ConfusablesParser; use crate::attributes::deprecation::DeprecationParser; use crate::attributes::inline::{InlineParser, RustcForceInlineParser}; @@ -114,6 +114,7 @@ attribute_parsers!( Single, Single, Single, + Single, Single, Single, Single, diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index b006fdbb6586f..fbcfcaa706cae 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -121,6 +121,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { .max(); } AttributeKind::Cold(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, + AttributeKind::Naked(_) => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, AttributeKind::Align { align, .. } => codegen_fn_attrs.alignment = Some(*align), AttributeKind::NoMangle(attr_span) => { if tcx.opt_item_name(did.to_def_id()).is_some() { @@ -165,7 +166,6 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs { sym::rustc_allocator_zeroed => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::ALLOCATOR_ZEROED } - sym::naked => codegen_fn_attrs.flags |= CodegenFnAttrFlags::NAKED, sym::rustc_std_internal_symbol => { codegen_fn_attrs.flags |= CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL } diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 752cc2eff9734..3a2dfa8e98575 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -4,6 +4,7 @@ use std::ops::ControlFlow; use rustc_abi::FieldIdx; use rustc_attr_data_structures::AttributeKind; use rustc_attr_data_structures::ReprAttr::ReprPacked; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{EmissionGuarantee, MultiSpan}; @@ -104,7 +105,7 @@ pub fn check_abi_fn_ptr(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: Ex pub fn check_custom_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, fn_sig: FnSig<'_>, fn_sig_span: Span) { if fn_sig.abi == ExternAbi::Custom { // Function definitions that use `extern "custom"` must be naked functions. - if !tcx.has_attr(def_id, sym::naked) { + if !find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Naked(_)) { tcx.dcx().emit_err(crate::errors::AbiCustomClothedFunction { span: fn_sig_span, naked_span: tcx.def_span(def_id).shrink_to_lo(), diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index bd3ca8317eb49..672f3bc67cef8 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -7,6 +7,7 @@ use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_ast::util::parser::ExprPrecedence; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stack::ensure_sufficient_stack; use rustc_data_structures::unord::UnordMap; @@ -3779,7 +3780,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { fn check_expr_asm(&self, asm: &'tcx hir::InlineAsm<'tcx>, span: Span) -> Ty<'tcx> { if let rustc_ast::AsmMacro::NakedAsm = asm.asm_macro { - if !self.tcx.has_attr(self.body_id, sym::naked) { + if !find_attr!(self.tcx.get_all_attrs(self.body_id), AttributeKind::Naked(..)) { self.tcx.dcx().emit_err(NakedAsmOutsideNakedFn { span }); } } diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 043a687914b70..1cc618e2aeeca 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -42,6 +42,7 @@ mod writeback; pub use coercion::can_coerce; use fn_ctxt::FnCtxt; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, pluralize, struct_span_code_err}; @@ -55,8 +56,8 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_middle::{bug, span_bug}; use rustc_session::config; +use rustc_span::Span; use rustc_span::def_id::LocalDefId; -use rustc_span::{Span, sym}; use tracing::{debug, instrument}; use typeck_root_ctxt::TypeckRootCtxt; @@ -173,7 +174,7 @@ fn typeck_with_inspect<'tcx>( .map(|(idx, ty)| fcx.normalize(arg_span(idx), ty)), ); - if tcx.has_attr(def_id, sym::naked) { + if find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Naked(..)) { naked_functions::typeck_naked_fn(tcx, def_id, body); } diff --git a/compiler/rustc_hir_typeck/src/naked_functions.rs b/compiler/rustc_hir_typeck/src/naked_functions.rs index 2518d6478e655..d055fa68fc34a 100644 --- a/compiler/rustc_hir_typeck/src/naked_functions.rs +++ b/compiler/rustc_hir_typeck/src/naked_functions.rs @@ -1,12 +1,13 @@ //! Checks validity of naked functions. +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::Visitor; use rustc_hir::{ExprKind, HirIdSet, StmtKind}; use rustc_middle::span_bug; use rustc_middle::ty::TyCtxt; -use rustc_span::{Span, sym}; +use rustc_span::Span; use crate::errors::{ NakedFunctionsAsmBlock, NakedFunctionsMustNakedAsm, NoPatterns, ParamsNotAllowed, @@ -20,7 +21,7 @@ pub(crate) fn typeck_naked_fn<'tcx>( def_id: LocalDefId, body: &'tcx hir::Body<'tcx>, ) { - debug_assert!(tcx.has_attr(def_id, sym::naked)); + debug_assert!(find_attr!(tcx.get_all_attrs(def_id), AttributeKind::Naked(..))); check_no_patterns(tcx, body.params); check_no_parameters_use(tcx, body); check_asm(tcx, def_id, body); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index ad1a2a0427376..1990b46adbb79 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -160,6 +160,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { Attribute::Parsed(AttributeKind::Align { align, span: repr_span }) => { self.check_align(span, target, *align, *repr_span) } + Attribute::Parsed(AttributeKind::Naked(attr_span)) => { + self.check_naked(hir_id, *attr_span, span, target, attrs) + } Attribute::Parsed( AttributeKind::BodyStability { .. } | AttributeKind::ConstStabilityIndirect @@ -217,7 +220,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { [sym::rustc_std_internal_symbol, ..] => { self.check_rustc_std_internal_symbol(attr, span, target) } - [sym::naked, ..] => self.check_naked(hir_id, attr, span, target, attrs), [sym::rustc_no_implicit_autorefs, ..] => { self.check_applied_to_fn_or_method(hir_id, attr.span(), span, target) } @@ -623,7 +625,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { fn check_naked( &self, hir_id: HirId, - attr: &Attribute, + attr_span: Span, span: Span, target: Target, attrs: &[Attribute], @@ -659,7 +661,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::link_section, sym::linkage, sym::no_mangle, - sym::naked, sym::instruction_set, sym::repr, sym::align, @@ -703,13 +704,14 @@ impl<'tcx> CheckAttrVisitor<'tcx> { | AttributeKind::NoMangle(..) | AttributeKind::Cold(..) | AttributeKind::MustUse { .. }, + | AttributeKind::Naked(..), ) => { continue; } Attribute::Parsed(AttributeKind::Inline(.., span)) => { self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { span: *span, - naked_span: attr.span(), + naked_span: attr_span, attr: sym::inline.to_string(), }); @@ -746,7 +748,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { span: other_attr.span(), - naked_span: attr.span(), + naked_span: attr_span, attr: other_attr_name, }); @@ -756,7 +758,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { - attr_span: attr.span(), + attr_span, defn_span: span, on_crate: hir_id == CRATE_HIR_ID, }); diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs index 763d9fda80494..125730377ef87 100644 --- a/compiler/rustc_passes/src/liveness.rs +++ b/compiler/rustc_passes/src/liveness.rs @@ -85,6 +85,7 @@ use std::io; use std::io::prelude::*; use std::rc::Rc; +use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; use rustc_hir::def::*; @@ -145,7 +146,7 @@ fn check_liveness(tcx: TyCtxt<'_>, def_id: LocalDefId) { } // Don't run unused pass for #[naked] - if tcx.has_attr(def_id.to_def_id(), sym::naked) { + if find_attr!(tcx.get_all_attrs(def_id.to_def_id()), AttributeKind::Naked(..)) { return; } From 73bcf4c117681b95fe591e1d468ac0bf84b8d792 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Thu, 19 Jun 2025 08:26:18 +0200 Subject: [PATCH 10/11] make warnings methods on cx so it's easier to emit them elsewhere too --- .../rustc_attr_parsing/src/attributes/mod.rs | 10 ++----- compiler/rustc_attr_parsing/src/context.rs | 26 +++++++++++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 3162c1fc72799..bfdd61384e5c8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -189,14 +189,8 @@ impl OnDuplicate { unused: Span, ) { match self { - OnDuplicate::Warn => cx.emit_lint( - AttributeLintKind::UnusedDuplicate { this: unused, other: used, warning: false }, - unused, - ), - OnDuplicate::WarnButFutureError => cx.emit_lint( - AttributeLintKind::UnusedDuplicate { this: unused, other: used, warning: true }, - unused, - ), + OnDuplicate::Warn => cx.warn_unused_duplicate(used, unused), + OnDuplicate::WarnButFutureError => cx.warn_unused_duplicate_future_error(used, unused), OnDuplicate::Error => { cx.emit_err(UnusedMultiple { this: used, diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index bf289c6aae80c..570151eae9d5d 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -201,6 +201,32 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { (self.emit_lint)(AttributeLint { id, span, kind: lint }); } + pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) { + self.emit_lint( + AttributeLintKind::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: false, + }, + unused_span, + ) + } + + pub(crate) fn warn_unused_duplicate_future_error( + &mut self, + used_span: Span, + unused_span: Span, + ) { + self.emit_lint( + AttributeLintKind::UnusedDuplicate { + this: unused_span, + other: used_span, + warning: true, + }, + unused_span, + ) + } + pub(crate) fn unknown_key( &self, span: Span, From 5c0a6252058e01fc17527039333c70f17290b5ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Fri, 13 Jun 2025 02:28:33 +0200 Subject: [PATCH 11/11] move naked checks out of check_attr.rs --- .../src/attributes.rs | 2 +- compiler/rustc_attr_parsing/messages.ftl | 4 + .../src/attributes/codegen_attrs.rs | 120 +++++++++++++++-- .../src/attributes/inline.rs | 6 +- .../rustc_attr_parsing/src/attributes/mod.rs | 1 - compiler/rustc_attr_parsing/src/context.rs | 71 +++++++--- compiler/rustc_attr_parsing/src/parser.rs | 8 ++ .../src/session_diagnostics.rs | 11 ++ .../rustc_hir_analysis/src/check/check.rs | 1 - compiler/rustc_passes/messages.ftl | 5 - compiler/rustc_passes/src/check_attr.rs | 121 +----------------- compiler/rustc_passes/src/errors.rs | 11 -- tests/ui/asm/naked-functions-inline.stderr | 14 +- tests/ui/asm/naked-invalid-attr.stderr | 18 +-- ...gate-naked_functions_target_feature.stderr | 4 +- .../error-with-naked.stderr | 8 +- 16 files changed, 211 insertions(+), 194 deletions(-) diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs index 63db0d0c98823..9227b81f12fac 100644 --- a/compiler/rustc_attr_data_structures/src/attributes.rs +++ b/compiler/rustc_attr_data_structures/src/attributes.rs @@ -244,7 +244,7 @@ pub enum AttributeKind { reason: Option, }, - /// Represents #[naked] + /// Represents `#[naked]` Naked(Span), /// Represents `#[no_mangle]` diff --git a/compiler/rustc_attr_parsing/messages.ftl b/compiler/rustc_attr_parsing/messages.ftl index 0891afc003e14..2bb27ede86055 100644 --- a/compiler/rustc_attr_parsing/messages.ftl +++ b/compiler/rustc_attr_parsing/messages.ftl @@ -89,6 +89,10 @@ attr_parsing_missing_since = attr_parsing_multiple_stability_levels = multiple stability levels +attr_parsing_naked_functions_incompatible_attribute = + attribute incompatible with `#[unsafe(naked)]` + .label = the `{$attr}` attribute is incompatible with `#[unsafe(naked)]` + .naked_attribute = function marked with `#[unsafe(naked)]` here attr_parsing_non_ident_feature = 'feature' is not an identifier diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index cf31dd0ace793..24c40c301fe08 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -1,10 +1,12 @@ use rustc_attr_data_structures::{AttributeKind, OptimizeAttr}; use rustc_feature::{AttributeTemplate, template}; -use rustc_span::sym; +use rustc_session::parse::feature_err; +use rustc_span::{Span, sym}; -use super::{AttributeOrder, OnDuplicate, SingleAttributeParser}; -use crate::context::{AcceptContext, Stage}; +use super::{AcceptMapping, AttributeOrder, AttributeParser, OnDuplicate, SingleAttributeParser}; +use crate::context::{AcceptContext, FinalizeContext, Stage}; use crate::parser::ArgParser; +use crate::session_diagnostics::NakedFunctionIncompatibleAttribute; pub(crate) struct OptimizeParser; @@ -57,20 +59,110 @@ impl SingleAttributeParser for ColdParser { } } -pub(crate) struct NakedParser; +#[derive(Default)] +pub(crate) struct NakedParser { + span: Option, +} -impl SingleAttributeParser for NakedParser { - const PATH: &[rustc_span::Symbol] = &[sym::naked]; - const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepLast; - const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const TEMPLATE: AttributeTemplate = template!(Word); +impl AttributeParser for NakedParser { + const ATTRIBUTES: AcceptMapping = + &[(&[sym::naked], template!(Word), |this, cx, args| { + if !args.no_args() { + cx.expected_no_args(args.span().unwrap_or(cx.attr_span)); + return; + } - fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option { - if !args.no_args() { - cx.expected_no_args(args.span().unwrap_or(cx.attr_span)); - return None; + if let Some(earlier) = this.span { + let span = cx.attr_span; + cx.warn_unused_duplicate(earlier, span); + } else { + this.span = Some(cx.attr_span); + } + })]; + + fn finalize(self, cx: &FinalizeContext<'_, '_, S>) -> Option { + // FIXME(jdonszelmann): upgrade this list to *parsed* attributes + // once all of these have parsed forms. That'd make the check much nicer... + // + // many attributes don't make sense in combination with #[naked]. + // Notable attributes that are incompatible with `#[naked]` are: + // + // * `#[inline]` + // * `#[track_caller]` + // * `#[test]`, `#[ignore]`, `#[should_panic]` + // + // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains + // accurate. + const ALLOW_LIST: &[rustc_span::Symbol] = &[ + // conditional compilation + sym::cfg_trace, + sym::cfg_attr_trace, + // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`) + sym::test, + sym::ignore, + sym::should_panic, + sym::bench, + // diagnostics + sym::allow, + sym::warn, + sym::deny, + sym::forbid, + sym::deprecated, + sym::must_use, + // abi, linking and FFI + sym::cold, + sym::export_name, + sym::link_section, + sym::linkage, + sym::no_mangle, + sym::instruction_set, + sym::repr, + sym::rustc_std_internal_symbol, + sym::align, + // obviously compatible with self + sym::naked, + // documentation + sym::doc, + ]; + + let span = self.span?; + + // only if we found a naked attribute do we do the somewhat expensive check + 'outer: for other_attr in cx.all_attrs { + for allowed_attr in ALLOW_LIST { + if other_attr.segments().next().is_some_and(|i| cx.tools.contains(&i.name)) { + // effectively skips the error message being emitted below + // if it's a tool attribute + continue 'outer; + } + if other_attr.word_is(*allowed_attr) { + // effectively skips the error message being emitted below + // if its an allowed attribute + continue 'outer; + } + + if other_attr.word_is(sym::target_feature) { + if !cx.features().naked_functions_target_feature() { + feature_err( + &cx.sess(), + sym::naked_functions_target_feature, + other_attr.span(), + "`#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions", + ).emit(); + } + + continue 'outer; + } + } + + cx.emit_err(NakedFunctionIncompatibleAttribute { + span: other_attr.span(), + naked_span: span, + attr: other_attr.get_attribute_path().to_string(), + }); } - Some(AttributeKind::Naked(cx.attr_span)) + + Some(AttributeKind::Naked(span)) } } diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index 25efc3ae49b9d..11844f4cd950f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -45,10 +45,8 @@ impl SingleAttributeParser for InlineParser { ArgParser::NameValue(_) => { let suggestions = >::TEMPLATE.suggestions(false, "inline"); - cx.emit_lint( - AttributeLintKind::IllFormedAttributeInput { suggestions }, - cx.attr_span, - ); + let span = cx.attr_span; + cx.emit_lint(AttributeLintKind::IllFormedAttributeInput { suggestions }, span); return None; } } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index bfdd61384e5c8..738d8735b6924 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -17,7 +17,6 @@ use std::marker::PhantomData; use rustc_attr_data_structures::AttributeKind; -use rustc_attr_data_structures::lints::AttributeLintKind; use rustc_feature::AttributeTemplate; use rustc_span::{Span, Symbol}; use thin_vec::ThinVec; diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 570151eae9d5d..457e073c488b0 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -28,7 +28,7 @@ use crate::attributes::stability::{ }; use crate::attributes::transparency::TransparencyParser; use crate::attributes::{AttributeParser as _, Combine, Single}; -use crate::parser::{ArgParser, MetaItemParser}; +use crate::parser::{ArgParser, MetaItemParser, PathParser}; use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem}; macro_rules! group_type { @@ -97,6 +97,7 @@ attribute_parsers!( BodyStabilityParser, ConfusablesParser, ConstStabilityParser, + NakedParser, StabilityParser, // tidy-alphabetical-end @@ -114,7 +115,6 @@ attribute_parsers!( Single, Single, Single, - Single, Single, Single, Single, @@ -175,7 +175,7 @@ pub struct Late; /// /// Gives [`AttributeParser`]s enough information to create errors, for example. pub(crate) struct AcceptContext<'f, 'sess, S: Stage> { - pub(crate) finalize_cx: FinalizeContext<'f, 'sess, S>, + pub(crate) shared: SharedContext<'f, 'sess, S>, /// The span of the attribute currently being parsed pub(crate) attr_span: Span, @@ -188,7 +188,7 @@ pub(crate) struct AcceptContext<'f, 'sess, S: Stage> { pub(crate) attr_path: AttrPath, } -impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { +impl<'f, 'sess: 'f, S: Stage> SharedContext<'f, 'sess, S> { pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed { S::emit_err(&self.sess, diag) } @@ -226,7 +226,9 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { unused_span, ) } +} +impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { pub(crate) fn unknown_key( &self, span: Span, @@ -359,16 +361,16 @@ impl<'f, 'sess: 'f, S: Stage> AcceptContext<'f, 'sess, S> { } impl<'f, 'sess, S: Stage> Deref for AcceptContext<'f, 'sess, S> { - type Target = FinalizeContext<'f, 'sess, S>; + type Target = SharedContext<'f, 'sess, S>; fn deref(&self) -> &Self::Target { - &self.finalize_cx + &self.shared } } impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.finalize_cx + &mut self.shared } } @@ -376,7 +378,7 @@ impl<'f, 'sess, S: Stage> DerefMut for AcceptContext<'f, 'sess, S> { /// /// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create /// errors, for example. -pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> { +pub(crate) struct SharedContext<'p, 'sess, S: Stage> { /// The parse context, gives access to the session and the /// diagnostics context. pub(crate) cx: &'p mut AttributeParser<'sess, S>, @@ -385,10 +387,40 @@ pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> { /// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to pub(crate) target_id: S::Id, - pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint), + emit_lint: &'p mut dyn FnMut(AttributeLint), +} + +/// Context given to every attribute parser during finalization. +/// +/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create +/// errors, for example. +pub(crate) struct FinalizeContext<'p, 'sess, S: Stage> { + pub(crate) shared: SharedContext<'p, 'sess, S>, + + /// A list of all attribute on this syntax node. + /// + /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize) + /// + /// Usually, you should use normal attribute parsing logic instead, + /// especially when making a *denylist* of other attributes. + pub(crate) all_attrs: &'p [PathParser<'p>], } impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> { + type Target = SharedContext<'p, 'sess, S>; + + fn deref(&self) -> &Self::Target { + &self.shared + } +} + +impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.shared + } +} + +impl<'p, 'sess: 'p, S: Stage> Deref for SharedContext<'p, 'sess, S> { type Target = AttributeParser<'sess, S>; fn deref(&self) -> &Self::Target { @@ -396,7 +428,7 @@ impl<'p, 'sess: 'p, S: Stage> Deref for FinalizeContext<'p, 'sess, S> { } } -impl<'p, 'sess: 'p, S: Stage> DerefMut for FinalizeContext<'p, 'sess, S> { +impl<'p, 'sess: 'p, S: Stage> DerefMut for SharedContext<'p, 'sess, S> { fn deref_mut(&mut self) -> &mut Self::Target { self.cx } @@ -411,8 +443,7 @@ pub enum OmitDoc { /// Context created once, for example as part of the ast lowering /// context, through which all attributes can be lowered. pub struct AttributeParser<'sess, S: Stage = Late> { - #[expect(dead_code)] // FIXME(jdonszelmann): needed later to verify we parsed all attributes - tools: Vec, + pub(crate) tools: Vec, features: Option<&'sess Features>, sess: &'sess Session, stage: PhantomData, @@ -500,6 +531,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { mut emit_lint: impl FnMut(AttributeLint), ) -> Vec { let mut attributes = Vec::new(); + let mut attr_paths = Vec::new(); for attr in attrs { // If we're only looking for a single attribute, skip all the ones we don't care about. @@ -543,6 +575,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { // })) // } ast::AttrKind::Normal(n) => { + attr_paths.push(PathParser::Ast(&n.item.path)); + let parser = MetaItemParser::from_attr(n, self.dcx()); let path = parser.path(); let args = parser.args(); @@ -551,7 +585,7 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { if let Some(accepts) = S::parsers().0.get(parts.as_slice()) { for (template, accept) in accepts { let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext { - finalize_cx: FinalizeContext { + shared: SharedContext { cx: self, target_span, target_id, @@ -595,10 +629,13 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> { let mut parsed_attributes = Vec::new(); for f in &S::parsers().1 { if let Some(attr) = f(&mut FinalizeContext { - cx: self, - target_span, - target_id, - emit_lint: &mut emit_lint, + shared: SharedContext { + cx: self, + target_span, + target_id, + emit_lint: &mut emit_lint, + }, + all_attrs: &attr_paths, }) { parsed_attributes.push(Attribute::Parsed(attr)); } diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 1edbe3a9d27aa..e02dc098127cf 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -87,6 +87,14 @@ impl<'a> PathParser<'a> { pub fn word_is(&self, sym: Symbol) -> bool { self.word().map(|i| i.name == sym).unwrap_or(false) } + + /// Checks whether the first segments match the givens. + /// + /// Unlike [`segments_is`](Self::segments_is), + /// `self` may contain more segments than the number matched against. + pub fn starts_with(&self, segments: &[Symbol]) -> bool { + segments.len() < self.len() && self.segments().zip(segments).all(|(a, b)| a.name == *b) + } } impl Display for PathParser<'_> { diff --git a/compiler/rustc_attr_parsing/src/session_diagnostics.rs b/compiler/rustc_attr_parsing/src/session_diagnostics.rs index 2a020770e5d3c..808e452799d3c 100644 --- a/compiler/rustc_attr_parsing/src/session_diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/session_diagnostics.rs @@ -482,6 +482,17 @@ pub(crate) struct UnrecognizedReprHint { pub span: Span, } +#[derive(Diagnostic)] +#[diag(attr_parsing_naked_functions_incompatible_attribute, code = E0736)] +pub(crate) struct NakedFunctionIncompatibleAttribute { + #[primary_span] + #[label] + pub span: Span, + #[label(attr_parsing_naked_attribute)] + pub naked_span: Span, + pub attr: String, +} + pub(crate) enum AttributeParseErrorReason { ExpectedNoArgs, ExpectedStringLiteral { byte_string: Option }, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 3a2dfa8e98575..60b691e0f751b 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -2,7 +2,6 @@ use std::cell::LazyCell; use std::ops::ControlFlow; use rustc_abi::FieldIdx; -use rustc_attr_data_structures::AttributeKind; use rustc_attr_data_structures::ReprAttr::ReprPacked; use rustc_attr_data_structures::{AttributeKind, find_attr}; use rustc_data_structures::unord::{UnordMap, UnordSet}; diff --git a/compiler/rustc_passes/messages.ftl b/compiler/rustc_passes/messages.ftl index c1a2b3b29733f..29526817257b1 100644 --- a/compiler/rustc_passes/messages.ftl +++ b/compiler/rustc_passes/messages.ftl @@ -491,11 +491,6 @@ passes_must_not_suspend = passes_must_use_no_effect = `#[must_use]` has no effect when applied to {$article} {$target} -passes_naked_functions_incompatible_attribute = - attribute incompatible with `#[unsafe(naked)]` - .label = the `{$attr}` attribute is incompatible with `#[unsafe(naked)]` - .naked_attribute = function marked with `#[unsafe(naked)]` here - passes_no_link = attribute should be applied to an `extern crate` item .label = not an `extern crate` item diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 1990b46adbb79..c2a58b4cd7d53 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{ UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES, UNUSED_ATTRIBUTES, }; use rustc_session::parse::feature_err; -use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, kw, sym}; +use rustc_span::{BytePos, DUMMY_SP, Span, Symbol, edition, sym}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::infer::{TyCtxtInferExt, ValuePairs}; use rustc_trait_selection::traits::ObligationCtxt; @@ -161,7 +161,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_align(span, target, *align, *repr_span) } Attribute::Parsed(AttributeKind::Naked(attr_span)) => { - self.check_naked(hir_id, *attr_span, span, target, attrs) + self.check_naked(hir_id, *attr_span, span, target) } Attribute::Parsed( AttributeKind::BodyStability { .. } @@ -622,53 +622,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Checks if `#[naked]` is applied to a function definition. - fn check_naked( - &self, - hir_id: HirId, - attr_span: Span, - span: Span, - target: Target, - attrs: &[Attribute], - ) { - // many attributes don't make sense in combination with #[naked]. - // Notable attributes that are incompatible with `#[naked]` are: - // - // * `#[inline]` - // * `#[track_caller]` - // * `#[test]`, `#[ignore]`, `#[should_panic]` - // - // NOTE: when making changes to this list, check that `error_codes/E0736.md` remains - // accurate. - const ALLOW_LIST: &[rustc_span::Symbol] = &[ - // conditional compilation - sym::cfg_trace, - sym::cfg_attr_trace, - // testing (allowed here so better errors can be generated in `rustc_builtin_macros::test`) - sym::test, - sym::ignore, - sym::should_panic, - sym::bench, - // diagnostics - sym::allow, - sym::warn, - sym::deny, - sym::forbid, - // FIXME(jdonszelmann): not used, because already a new-style attr (ugh) - sym::deprecated, - sym::must_use, - // abi, linking and FFI - sym::export_name, - sym::link_section, - sym::linkage, - sym::no_mangle, - sym::instruction_set, - sym::repr, - sym::align, - sym::rustc_std_internal_symbol, - // documentation - sym::doc, - ]; - + fn check_naked(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) { match target { Target::Fn | Target::Method(MethodKind::Trait { body: true } | MethodKind::Inherent) => { @@ -686,75 +640,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { ) .emit(); } - - for other_attr in attrs { - // this covers "sugared doc comments" of the form `/// ...` - // it does not cover `#[doc = "..."]`, which is handled below - if other_attr.is_doc_comment() { - continue; - } - - // FIXME(jdonszelmann): once naked uses new-style parsing, - // this check can be part of the parser and be removed here - match other_attr { - Attribute::Parsed( - AttributeKind::Deprecation { .. } - | AttributeKind::Repr { .. } - | AttributeKind::Align { .. } - | AttributeKind::NoMangle(..) - | AttributeKind::Cold(..) - | AttributeKind::MustUse { .. }, - | AttributeKind::Naked(..), - ) => { - continue; - } - Attribute::Parsed(AttributeKind::Inline(.., span)) => { - self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { - span: *span, - naked_span: attr_span, - attr: sym::inline.to_string(), - }); - - return; - } - // FIXME(jdonszelmann): make exhaustive - _ => {} - } - - if other_attr.has_name(sym::target_feature) { - if !self.tcx.features().naked_functions_target_feature() { - feature_err( - &self.tcx.sess, - sym::naked_functions_target_feature, - other_attr.span(), - "`#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions", - ).emit(); - - return; - } else { - continue; - } - } - - if !other_attr.has_any_name(ALLOW_LIST) - && !matches!(other_attr.path().as_slice(), [sym::rustfmt, ..]) - { - let path = other_attr.path(); - let path: Vec<_> = path - .iter() - .map(|s| if *s == kw::PathRoot { "" } else { s.as_str() }) - .collect(); - let other_attr_name = path.join("::"); - - self.dcx().emit_err(errors::NakedFunctionIncompatibleAttribute { - span: other_attr.span(), - naked_span: attr_span, - attr: other_attr_name, - }); - - return; - } - } } _ => { self.dcx().emit_err(errors::AttrShouldBeAppliedToFn { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 587d9170f067c..94c8ae77ed767 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -1070,17 +1070,6 @@ pub(crate) struct FeaturePreviouslyDeclared<'a> { pub prev_declared: &'a str, } -#[derive(Diagnostic)] -#[diag(passes_naked_functions_incompatible_attribute, code = E0736)] -pub(crate) struct NakedFunctionIncompatibleAttribute { - #[primary_span] - #[label] - pub span: Span, - #[label(passes_naked_attribute)] - pub naked_span: Span, - pub attr: String, -} - #[derive(Diagnostic)] #[diag(passes_attr_only_in_functions)] pub(crate) struct AttrOnlyInFunctions { diff --git a/tests/ui/asm/naked-functions-inline.stderr b/tests/ui/asm/naked-functions-inline.stderr index 07d5f3bc49a94..91140a301edc9 100644 --- a/tests/ui/asm/naked-functions-inline.stderr +++ b/tests/ui/asm/naked-functions-inline.stderr @@ -1,26 +1,26 @@ error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-functions-inline.rs:12:1 + --> $DIR/naked-functions-inline.rs:12:3 | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here LL | #[inline] - | ^^^^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-functions-inline.rs:19:1 + --> $DIR/naked-functions-inline.rs:19:3 | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-functions-inline.rs:26:1 + --> $DIR/naked-functions-inline.rs:26:3 | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here LL | #[inline(never)] - | ^^^^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` error[E0736]: attribute incompatible with `#[unsafe(naked)]` --> $DIR/naked-functions-inline.rs:33:19 @@ -28,7 +28,7 @@ error[E0736]: attribute incompatible with `#[unsafe(naked)]` LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here LL | #[cfg_attr(all(), inline(never))] - | ^^^^^^^^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^ the `inline` attribute is incompatible with `#[unsafe(naked)]` error: aborting due to 4 previous errors diff --git a/tests/ui/asm/naked-invalid-attr.stderr b/tests/ui/asm/naked-invalid-attr.stderr index 6661084861eee..915b54b3fc236 100644 --- a/tests/ui/asm/naked-invalid-attr.stderr +++ b/tests/ui/asm/naked-invalid-attr.stderr @@ -4,6 +4,15 @@ error[E0433]: failed to resolve: use of unresolved module or unlinked crate `a` LL | #[::a] | ^ use of unresolved module or unlinked crate `a` +error[E0736]: attribute incompatible with `#[unsafe(naked)]` + --> $DIR/naked-invalid-attr.rs:56:3 + | +LL | #[::a] + | ^^^ the `{{root}}::a` attribute is incompatible with `#[unsafe(naked)]` +... +LL | #[unsafe(naked)] + | ---------------- function marked with `#[unsafe(naked)]` here + error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:13:1 | @@ -33,15 +42,6 @@ LL | #[unsafe(naked)] LL | || {}; | ----- not a function definition -error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/naked-invalid-attr.rs:56:1 - | -LL | #[::a] - | ^^^^^^ the `::a` attribute is incompatible with `#[unsafe(naked)]` -... -LL | #[unsafe(naked)] - | ---------------- function marked with `#[unsafe(naked)]` here - error: attribute should be applied to a function definition --> $DIR/naked-invalid-attr.rs:22:5 | diff --git a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr index 8e601a14753bb..e57ec9cc59b2d 100644 --- a/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr +++ b/tests/ui/feature-gates/feature-gate-naked_functions_target_feature.stderr @@ -1,8 +1,8 @@ error[E0658]: `#[target_feature(/* ... */)]` is currently unstable on `#[naked]` functions - --> $DIR/feature-gate-naked_functions_target_feature.rs:7:1 + --> $DIR/feature-gate-naked_functions_target_feature.rs:7:3 | LL | #[target_feature(enable = "avx2")] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^ | = note: see issue #138568 for more information = help: add `#![feature(naked_functions_target_feature)]` to the crate attributes to enable diff --git a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr index d3cafbc635086..3036080613882 100644 --- a/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr +++ b/tests/ui/rfcs/rfc-2091-track-caller/error-with-naked.stderr @@ -1,17 +1,17 @@ error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/error-with-naked.rs:5:1 + --> $DIR/error-with-naked.rs:5:3 | LL | #[track_caller] - | ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[unsafe(naked)]` LL | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here error[E0736]: attribute incompatible with `#[unsafe(naked)]` - --> $DIR/error-with-naked.rs:17:5 + --> $DIR/error-with-naked.rs:17:7 | LL | #[track_caller] - | ^^^^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[unsafe(naked)]` + | ^^^^^^^^^^^^ the `track_caller` attribute is incompatible with `#[unsafe(naked)]` LL | LL | #[unsafe(naked)] | ---------------- function marked with `#[unsafe(naked)]` here