From b89deb41bfe08cc0b463d93f8690494ad6f160c4 Mon Sep 17 00:00:00 2001 From: Guillaume Date: Wed, 4 Mar 2026 00:24:56 +0100 Subject: [PATCH 01/17] Fix LegacyKeyValueFormat report from docker build: arm --- src/ci/docker/host-x86_64/arm-android/Dockerfile | 4 ++-- src/ci/docker/host-x86_64/armhf-gnu/Dockerfile | 4 ++-- .../docker/host-x86_64/dist-arm-linux-gnueabi/Dockerfile | 7 +++---- src/ci/docker/host-x86_64/dist-arm-linux-musl/Dockerfile | 7 +++---- src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile | 4 ++-- src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile | 4 ++-- src/ci/docker/host-x86_64/dist-ohos-armv7/Dockerfile | 7 +++---- 7 files changed, 17 insertions(+), 20 deletions(-) diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile index bc311be05808d..21f038bffe592 100644 --- a/src/ci/docker/host-x86_64/arm-android/Dockerfile +++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile @@ -32,9 +32,9 @@ ENV PATH=$PATH:/android/ndk/toolchains/llvm/prebuilt/linux-x86_64/bin ENV TARGETS=arm-linux-androideabi -ENV RUST_CONFIGURE_ARGS --android-ndk=/android/ndk/ +ENV RUST_CONFIGURE_ARGS="--android-ndk=/android/ndk/" -ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target $TARGETS +ENV SCRIPT="python3 ../x.py --stage 2 test --host= --target $TARGETS" COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh diff --git a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile index 015caafc5bd66..9a3545dbad8d1 100644 --- a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile +++ b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile @@ -82,7 +82,7 @@ RUN sh /scripts/sccache.sh COPY static/gitconfig /etc/gitconfig -ENV RUST_CONFIGURE_ARGS --qemu-armhf-rootfs=/tmp/rootfs -ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target arm-unknown-linux-gnueabihf +ENV RUST_CONFIGURE_ARGS="--qemu-armhf-rootfs=/tmp/rootfs" +ENV SCRIPT="python3 ../x.py --stage 2 test --host= --target arm-unknown-linux-gnueabihf" ENV NO_CHANGE_USER=1 diff --git a/src/ci/docker/host-x86_64/dist-arm-linux-gnueabi/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux-gnueabi/Dockerfile index 996dacd712478..f0d54b0d33d60 100644 --- a/src/ci/docker/host-x86_64/dist-arm-linux-gnueabi/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-arm-linux-gnueabi/Dockerfile @@ -27,9 +27,8 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \ ENV HOSTS=arm-unknown-linux-gnueabi -ENV RUST_CONFIGURE_ARGS \ - --enable-full-tools \ +ENV RUST_CONFIGURE_ARGS="--enable-full-tools \ --disable-docs \ --enable-sanitizers \ - --enable-profiler -ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS + --enable-profiler" +ENV SCRIPT="python3 ../x.py dist --host $HOSTS --target $HOSTS" diff --git a/src/ci/docker/host-x86_64/dist-arm-linux-musl/Dockerfile b/src/ci/docker/host-x86_64/dist-arm-linux-musl/Dockerfile index dc35285dbab99..99667d68ab7ad 100644 --- a/src/ci/docker/host-x86_64/dist-arm-linux-musl/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-arm-linux-musl/Dockerfile @@ -18,11 +18,10 @@ RUN sh /scripts/sccache.sh ENV HOSTS=aarch64-unknown-linux-musl -ENV RUST_CONFIGURE_ARGS \ - --enable-full-tools \ +ENV RUST_CONFIGURE_ARGS="--enable-full-tools \ --disable-docs \ --musl-root-aarch64=/usr/local/aarch64-linux-musl \ --enable-sanitizers \ --enable-profiler \ - --set target.aarch64-unknown-linux-musl.crt-static=false -ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS + --set target.aarch64-unknown-linux-musl.crt-static=false" +ENV SCRIPT="python3 ../x.py dist --host $HOSTS --target $HOSTS" diff --git a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile index 475542b335683..08b0c2ad04531 100644 --- a/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-armhf-linux/Dockerfile @@ -25,5 +25,5 @@ ENV CC_arm_unknown_linux_gnueabihf=arm-unknown-linux-gnueabihf-gcc \ ENV HOSTS=arm-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --enable-full-tools --enable-profiler --disable-docs -ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS +ENV RUST_CONFIGURE_ARGS="--enable-full-tools --enable-profiler --disable-docs" +ENV SCRIPT="python3 ../x.py dist --host $HOSTS --target $HOSTS" diff --git a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile index e718437aaaa39..c86bdbbc41b47 100644 --- a/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-armv7-linux/Dockerfile @@ -25,5 +25,5 @@ ENV CC_armv7_unknown_linux_gnueabihf=armv7-unknown-linux-gnueabihf-gcc \ ENV HOSTS=armv7-unknown-linux-gnueabihf -ENV RUST_CONFIGURE_ARGS --enable-full-tools --enable-profiler --disable-docs -ENV SCRIPT python3 ../x.py dist --host $HOSTS --target $HOSTS +ENV RUST_CONFIGURE_ARGS="--enable-full-tools --enable-profiler --disable-docs" +ENV SCRIPT="python3 ../x.py dist --host $HOSTS --target $HOSTS" diff --git a/src/ci/docker/host-x86_64/dist-ohos-armv7/Dockerfile b/src/ci/docker/host-x86_64/dist-ohos-armv7/Dockerfile index 2a23d8aec2376..9425f043b127b 100644 --- a/src/ci/docker/host-x86_64/dist-ohos-armv7/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-ohos-armv7/Dockerfile @@ -40,14 +40,13 @@ ENV \ AR_armv7_unknown_linux_ohos=/opt/ohos-sdk/native/llvm/bin/llvm-ar \ CXX_armv7_unknown_linux_ohos=/usr/local/bin/armv7-unknown-linux-ohos-clang++.sh -ENV RUST_CONFIGURE_ARGS \ - --enable-profiler \ +ENV RUST_CONFIGURE_ARGS="--enable-profiler \ --disable-docs \ --tools=cargo,clippy,rustdocs,rustfmt,rust-analyzer,rust-analyzer-proc-macro-srv,analysis,src,wasm-component-ld \ --enable-extended \ - --enable-sanitizers + --enable-sanitizers" -ENV SCRIPT python3 ../x.py dist --host=$TARGETS --target $TARGETS +ENV SCRIPT="python3 ../x.py dist --host=$TARGETS --target $TARGETS" COPY scripts/sccache.sh /scripts/ RUN sh /scripts/sccache.sh From eef3c4db7bfd3a3d943f9414ed2cd8464c5e6312 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 14 Nov 2025 00:24:27 +0100 Subject: [PATCH 02/17] move never type tests to subdirectories and add some comments --- .../ui/never_type/{ => basic}/adjust_never.rs | 0 .../ui/never_type/{ => basic}/auto-traits.rs | 0 .../call-fn-never-arg-wrong-type.rs | 0 .../call-fn-never-arg-wrong-type.stderr | 0 .../{ => basic}/call-fn-never-arg.rs | 0 tests/ui/never_type/{ => basic}/cast-never.rs | 0 .../never_type/{ => basic}/impl-for-never.rs | 0 .../{ => basic}/impl-for-never.run.stdout | 0 .../{ => basic}/never-assign-wrong-type.rs | 0 .../never-assign-wrong-type.stderr | 0 .../{ => basic}/never-associated-type.rs | 0 .../ui/never_type/{ => basic}/never-result.rs | 0 .../never_type/{ => basic}/never-type-arg.rs | 0 .../never-type-in-nested-fn-decl.rs | 0 .../{ => basic}/never-type-rvalues.rs | 0 .../never_type/{ => basic}/never_coercions.rs | 0 .../{ => basic}/never_transmute_never.rs | 0 .../{ => basic}/return-never-coerce.rs | 0 .../never_type/diverging-tuple-parts-39485.rs | 16 ------------ tests/ui/never_type/expr-empty-ret.rs | 14 ----------- .../defaulted-never-note.e2021.stderr | 0 .../defaulted-never-note.e2024.stderr | 0 .../defaulted-never-note.rs | 0 .../dependency-on-fallback-to-unit.rs | 0 .../dependency-on-fallback-to-unit.stderr | 0 ...fallback-unconstrained-return.e2021.stderr | 0 ...fallback-unconstrained-return.e2024.stderr | 0 ...lback-unconstrained-return.fallback.stderr | 0 ...ack-unconstrained-return.nofallback.stderr | 0 ...diverging-fallback-unconstrained-return.rs | 0 .../dont-suggest-turbofish-from-expansion.rs | 0 ...nt-suggest-turbofish-from-expansion.stderr | 0 .../fallback-closure-ret.e2021.stderr | 0 .../fallback-closure-ret.e2024.stderr | 0 .../fallback-closure-ret.fallback.stderr | 0 .../fallback-closure-ret.nofallback.stderr | 0 .../fallback-closure-ret.rs | 0 .../fallback-closure-wrap.e2024.stderr | 0 .../fallback-closure-wrap.fallback.stderr | 0 .../fallback-closure-wrap.rs | 0 .../from_infer_breaking_with_unit_fallback.rs | 2 +- ...er_breaking_with_unit_fallback.unit.stderr | 0 ...lint-breaking-2024-assign-underscore.fixed | 0 .../lint-breaking-2024-assign-underscore.rs | 0 ...int-breaking-2024-assign-underscore.stderr | 0 ...-fallback-flowing-into-unsafe.e2015.stderr | 0 ...-fallback-flowing-into-unsafe.e2024.stderr | 0 ...never-type-fallback-flowing-into-unsafe.rs | 0 .../question_mark_from_never.rs | 2 +- ...try-block-never-type-fallback.e2021.stderr | 0 .../try-block-never-type-fallback.rs | 0 tests/ui/never_type/issue-10176.rs | 9 ------- tests/ui/never_type/issue-10176.stderr | 14 ----------- tests/ui/never_type/issue-2149.rs | 15 ----------- tests/ui/never_type/issue-2149.stderr | 25 ------------------- .../never-pattern-as-closure-param-141592.rs | 0 ...ver-pattern-as-closure-param-141592.stderr | 0 .../unused_trait_in_never_pattern_body.rs | 0 .../unused_trait_in_never_pattern_body.stderr | 0 .../regress/divergent-block-with-tail.rs | 20 +++++++++++++++ .../divergent-block-with-tail.stderr} | 0 .../{ => regress}/eq-never-types.rs | 0 .../field-access-never-type-13847.rs | 0 .../field-access-never-type-13847.stderr | 0 .../never_type/{ => regress}/issue-13352.rs | 0 .../{ => regress}/issue-13352.stderr | 0 .../never_type/{ => regress}/issue-44402.rs | 0 .../never_type/{ => regress}/issue-51506.rs | 0 .../{ => regress}/issue-51506.stderr | 0 .../never_type/{ => regress}/issue-52443.rs | 0 .../{ => regress}/issue-52443.stderr | 0 .../never_type/{ => regress}/issue-5500-1.rs | 0 .../never_type/{ => regress}/issue-96335.rs | 0 .../{ => regress}/issue-96335.stderr | 0 .../never_type/{ => regress}/never-deref.rs | 0 .../{ => regress}/never-deref.stderr | 0 .../{ => regress}/never-in-range-pat.rs | 0 .../{ => regress}/never-in-range-pat.stderr | 0 .../never-type-fallback-option.rs | 0 .../never-type-method-call-15207.rs | 0 .../never-type-method-call-15207.stderr | 0 .../{ => regress}/span-bug-issue-121445.rs | 0 .../span-bug-issue-121445.stderr | 0 .../{ => regress}/suggestion-ice-132517.rs | 0 .../suggestion-ice-132517.stderr | 0 .../return-without-semicolon-in-match.rs | 13 ++++++++++ .../never-assign-dead-code.rs | 0 .../never-assign-dead-code.stderr | 0 88 files changed, 35 insertions(+), 95 deletions(-) rename tests/ui/never_type/{ => basic}/adjust_never.rs (100%) rename tests/ui/never_type/{ => basic}/auto-traits.rs (100%) rename tests/ui/never_type/{ => basic}/call-fn-never-arg-wrong-type.rs (100%) rename tests/ui/never_type/{ => basic}/call-fn-never-arg-wrong-type.stderr (100%) rename tests/ui/never_type/{ => basic}/call-fn-never-arg.rs (100%) rename tests/ui/never_type/{ => basic}/cast-never.rs (100%) rename tests/ui/never_type/{ => basic}/impl-for-never.rs (100%) rename tests/ui/never_type/{ => basic}/impl-for-never.run.stdout (100%) rename tests/ui/never_type/{ => basic}/never-assign-wrong-type.rs (100%) rename tests/ui/never_type/{ => basic}/never-assign-wrong-type.stderr (100%) rename tests/ui/never_type/{ => basic}/never-associated-type.rs (100%) rename tests/ui/never_type/{ => basic}/never-result.rs (100%) rename tests/ui/never_type/{ => basic}/never-type-arg.rs (100%) rename tests/ui/never_type/{ => basic}/never-type-in-nested-fn-decl.rs (100%) rename tests/ui/never_type/{ => basic}/never-type-rvalues.rs (100%) rename tests/ui/never_type/{ => basic}/never_coercions.rs (100%) rename tests/ui/never_type/{ => basic}/never_transmute_never.rs (100%) rename tests/ui/never_type/{ => basic}/return-never-coerce.rs (100%) delete mode 100644 tests/ui/never_type/diverging-tuple-parts-39485.rs delete mode 100644 tests/ui/never_type/expr-empty-ret.rs rename tests/ui/never_type/{ => fallback_change}/defaulted-never-note.e2021.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/defaulted-never-note.e2024.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/defaulted-never-note.rs (100%) rename tests/ui/never_type/{ => fallback_change}/dependency-on-fallback-to-unit.rs (100%) rename tests/ui/never_type/{ => fallback_change}/dependency-on-fallback-to-unit.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/diverging-fallback-unconstrained-return.e2021.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/diverging-fallback-unconstrained-return.e2024.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/diverging-fallback-unconstrained-return.fallback.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/diverging-fallback-unconstrained-return.nofallback.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/diverging-fallback-unconstrained-return.rs (100%) rename tests/ui/never_type/{ => fallback_change}/dont-suggest-turbofish-from-expansion.rs (100%) rename tests/ui/never_type/{ => fallback_change}/dont-suggest-turbofish-from-expansion.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/fallback-closure-ret.e2021.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/fallback-closure-ret.e2024.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/fallback-closure-ret.fallback.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/fallback-closure-ret.nofallback.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/fallback-closure-ret.rs (100%) rename tests/ui/never_type/{ => fallback_change}/fallback-closure-wrap.e2024.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/fallback-closure-wrap.fallback.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/fallback-closure-wrap.rs (100%) rename tests/ui/never_type/{ => fallback_change}/from_infer_breaking_with_unit_fallback.rs (90%) rename tests/ui/never_type/{ => fallback_change}/from_infer_breaking_with_unit_fallback.unit.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/lint-breaking-2024-assign-underscore.fixed (100%) rename tests/ui/never_type/{ => fallback_change}/lint-breaking-2024-assign-underscore.rs (100%) rename tests/ui/never_type/{ => fallback_change}/lint-breaking-2024-assign-underscore.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/lint-never-type-fallback-flowing-into-unsafe.rs (100%) rename tests/ui/never_type/{ => fallback_change}/question_mark_from_never.rs (93%) rename tests/ui/never_type/{ => fallback_change}/try-block-never-type-fallback.e2021.stderr (100%) rename tests/ui/never_type/{ => fallback_change}/try-block-never-type-fallback.rs (100%) delete mode 100644 tests/ui/never_type/issue-10176.rs delete mode 100644 tests/ui/never_type/issue-10176.stderr delete mode 100644 tests/ui/never_type/issue-2149.rs delete mode 100644 tests/ui/never_type/issue-2149.stderr rename tests/ui/never_type/{ => never_pattern}/never-pattern-as-closure-param-141592.rs (100%) rename tests/ui/never_type/{ => never_pattern}/never-pattern-as-closure-param-141592.stderr (100%) rename tests/ui/never_type/{ => never_pattern}/unused_trait_in_never_pattern_body.rs (100%) rename tests/ui/never_type/{ => never_pattern}/unused_trait_in_never_pattern_body.stderr (100%) create mode 100644 tests/ui/never_type/regress/divergent-block-with-tail.rs rename tests/ui/never_type/{diverging-tuple-parts-39485.stderr => regress/divergent-block-with-tail.stderr} (100%) rename tests/ui/never_type/{ => regress}/eq-never-types.rs (100%) rename tests/ui/never_type/{ => regress}/field-access-never-type-13847.rs (100%) rename tests/ui/never_type/{ => regress}/field-access-never-type-13847.stderr (100%) rename tests/ui/never_type/{ => regress}/issue-13352.rs (100%) rename tests/ui/never_type/{ => regress}/issue-13352.stderr (100%) rename tests/ui/never_type/{ => regress}/issue-44402.rs (100%) rename tests/ui/never_type/{ => regress}/issue-51506.rs (100%) rename tests/ui/never_type/{ => regress}/issue-51506.stderr (100%) rename tests/ui/never_type/{ => regress}/issue-52443.rs (100%) rename tests/ui/never_type/{ => regress}/issue-52443.stderr (100%) rename tests/ui/never_type/{ => regress}/issue-5500-1.rs (100%) rename tests/ui/never_type/{ => regress}/issue-96335.rs (100%) rename tests/ui/never_type/{ => regress}/issue-96335.stderr (100%) rename tests/ui/never_type/{ => regress}/never-deref.rs (100%) rename tests/ui/never_type/{ => regress}/never-deref.stderr (100%) rename tests/ui/never_type/{ => regress}/never-in-range-pat.rs (100%) rename tests/ui/never_type/{ => regress}/never-in-range-pat.stderr (100%) rename tests/ui/never_type/{ => regress}/never-type-fallback-option.rs (100%) rename tests/ui/never_type/{ => regress}/never-type-method-call-15207.rs (100%) rename tests/ui/never_type/{ => regress}/never-type-method-call-15207.stderr (100%) rename tests/ui/never_type/{ => regress}/span-bug-issue-121445.rs (100%) rename tests/ui/never_type/{ => regress}/span-bug-issue-121445.stderr (100%) rename tests/ui/never_type/{ => regress}/suggestion-ice-132517.rs (100%) rename tests/ui/never_type/{ => regress}/suggestion-ice-132517.stderr (100%) create mode 100644 tests/ui/parser/return-without-semicolon-in-match.rs rename tests/ui/{never_type => reachable}/never-assign-dead-code.rs (100%) rename tests/ui/{never_type => reachable}/never-assign-dead-code.stderr (100%) diff --git a/tests/ui/never_type/adjust_never.rs b/tests/ui/never_type/basic/adjust_never.rs similarity index 100% rename from tests/ui/never_type/adjust_never.rs rename to tests/ui/never_type/basic/adjust_never.rs diff --git a/tests/ui/never_type/auto-traits.rs b/tests/ui/never_type/basic/auto-traits.rs similarity index 100% rename from tests/ui/never_type/auto-traits.rs rename to tests/ui/never_type/basic/auto-traits.rs diff --git a/tests/ui/never_type/call-fn-never-arg-wrong-type.rs b/tests/ui/never_type/basic/call-fn-never-arg-wrong-type.rs similarity index 100% rename from tests/ui/never_type/call-fn-never-arg-wrong-type.rs rename to tests/ui/never_type/basic/call-fn-never-arg-wrong-type.rs diff --git a/tests/ui/never_type/call-fn-never-arg-wrong-type.stderr b/tests/ui/never_type/basic/call-fn-never-arg-wrong-type.stderr similarity index 100% rename from tests/ui/never_type/call-fn-never-arg-wrong-type.stderr rename to tests/ui/never_type/basic/call-fn-never-arg-wrong-type.stderr diff --git a/tests/ui/never_type/call-fn-never-arg.rs b/tests/ui/never_type/basic/call-fn-never-arg.rs similarity index 100% rename from tests/ui/never_type/call-fn-never-arg.rs rename to tests/ui/never_type/basic/call-fn-never-arg.rs diff --git a/tests/ui/never_type/cast-never.rs b/tests/ui/never_type/basic/cast-never.rs similarity index 100% rename from tests/ui/never_type/cast-never.rs rename to tests/ui/never_type/basic/cast-never.rs diff --git a/tests/ui/never_type/impl-for-never.rs b/tests/ui/never_type/basic/impl-for-never.rs similarity index 100% rename from tests/ui/never_type/impl-for-never.rs rename to tests/ui/never_type/basic/impl-for-never.rs diff --git a/tests/ui/never_type/impl-for-never.run.stdout b/tests/ui/never_type/basic/impl-for-never.run.stdout similarity index 100% rename from tests/ui/never_type/impl-for-never.run.stdout rename to tests/ui/never_type/basic/impl-for-never.run.stdout diff --git a/tests/ui/never_type/never-assign-wrong-type.rs b/tests/ui/never_type/basic/never-assign-wrong-type.rs similarity index 100% rename from tests/ui/never_type/never-assign-wrong-type.rs rename to tests/ui/never_type/basic/never-assign-wrong-type.rs diff --git a/tests/ui/never_type/never-assign-wrong-type.stderr b/tests/ui/never_type/basic/never-assign-wrong-type.stderr similarity index 100% rename from tests/ui/never_type/never-assign-wrong-type.stderr rename to tests/ui/never_type/basic/never-assign-wrong-type.stderr diff --git a/tests/ui/never_type/never-associated-type.rs b/tests/ui/never_type/basic/never-associated-type.rs similarity index 100% rename from tests/ui/never_type/never-associated-type.rs rename to tests/ui/never_type/basic/never-associated-type.rs diff --git a/tests/ui/never_type/never-result.rs b/tests/ui/never_type/basic/never-result.rs similarity index 100% rename from tests/ui/never_type/never-result.rs rename to tests/ui/never_type/basic/never-result.rs diff --git a/tests/ui/never_type/never-type-arg.rs b/tests/ui/never_type/basic/never-type-arg.rs similarity index 100% rename from tests/ui/never_type/never-type-arg.rs rename to tests/ui/never_type/basic/never-type-arg.rs diff --git a/tests/ui/never_type/never-type-in-nested-fn-decl.rs b/tests/ui/never_type/basic/never-type-in-nested-fn-decl.rs similarity index 100% rename from tests/ui/never_type/never-type-in-nested-fn-decl.rs rename to tests/ui/never_type/basic/never-type-in-nested-fn-decl.rs diff --git a/tests/ui/never_type/never-type-rvalues.rs b/tests/ui/never_type/basic/never-type-rvalues.rs similarity index 100% rename from tests/ui/never_type/never-type-rvalues.rs rename to tests/ui/never_type/basic/never-type-rvalues.rs diff --git a/tests/ui/never_type/never_coercions.rs b/tests/ui/never_type/basic/never_coercions.rs similarity index 100% rename from tests/ui/never_type/never_coercions.rs rename to tests/ui/never_type/basic/never_coercions.rs diff --git a/tests/ui/never_type/never_transmute_never.rs b/tests/ui/never_type/basic/never_transmute_never.rs similarity index 100% rename from tests/ui/never_type/never_transmute_never.rs rename to tests/ui/never_type/basic/never_transmute_never.rs diff --git a/tests/ui/never_type/return-never-coerce.rs b/tests/ui/never_type/basic/return-never-coerce.rs similarity index 100% rename from tests/ui/never_type/return-never-coerce.rs rename to tests/ui/never_type/basic/return-never-coerce.rs diff --git a/tests/ui/never_type/diverging-tuple-parts-39485.rs b/tests/ui/never_type/diverging-tuple-parts-39485.rs deleted file mode 100644 index f8304a692de65..0000000000000 --- a/tests/ui/never_type/diverging-tuple-parts-39485.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ edition:2015..2021 -// After #39485, this test used to pass, but that change was reverted -// due to numerous inference failures like #39808, so it now fails -// again. #39485 made it so that diverging types never propagate -// upward; but we now do propagate such types upward in many more -// cases. - -fn g() { - &panic!() //~ ERROR mismatched types -} - -fn f() -> isize { - (return 1, return 2) //~ ERROR mismatched types -} - -fn main() {} diff --git a/tests/ui/never_type/expr-empty-ret.rs b/tests/ui/never_type/expr-empty-ret.rs deleted file mode 100644 index e6af5bd3153f7..0000000000000 --- a/tests/ui/never_type/expr-empty-ret.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ run-pass - -#![allow(dead_code)] -// Issue #521 - - -fn f() { - let _x = match true { - true => { 10 } - false => { return } - }; -} - -pub fn main() { } diff --git a/tests/ui/never_type/defaulted-never-note.e2021.stderr b/tests/ui/never_type/fallback_change/defaulted-never-note.e2021.stderr similarity index 100% rename from tests/ui/never_type/defaulted-never-note.e2021.stderr rename to tests/ui/never_type/fallback_change/defaulted-never-note.e2021.stderr diff --git a/tests/ui/never_type/defaulted-never-note.e2024.stderr b/tests/ui/never_type/fallback_change/defaulted-never-note.e2024.stderr similarity index 100% rename from tests/ui/never_type/defaulted-never-note.e2024.stderr rename to tests/ui/never_type/fallback_change/defaulted-never-note.e2024.stderr diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/fallback_change/defaulted-never-note.rs similarity index 100% rename from tests/ui/never_type/defaulted-never-note.rs rename to tests/ui/never_type/fallback_change/defaulted-never-note.rs diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.rs b/tests/ui/never_type/fallback_change/dependency-on-fallback-to-unit.rs similarity index 100% rename from tests/ui/never_type/dependency-on-fallback-to-unit.rs rename to tests/ui/never_type/fallback_change/dependency-on-fallback-to-unit.rs diff --git a/tests/ui/never_type/dependency-on-fallback-to-unit.stderr b/tests/ui/never_type/fallback_change/dependency-on-fallback-to-unit.stderr similarity index 100% rename from tests/ui/never_type/dependency-on-fallback-to-unit.stderr rename to tests/ui/never_type/fallback_change/dependency-on-fallback-to-unit.stderr diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.e2021.stderr b/tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.e2021.stderr similarity index 100% rename from tests/ui/never_type/diverging-fallback-unconstrained-return.e2021.stderr rename to tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.e2021.stderr diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.e2024.stderr b/tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.e2024.stderr similarity index 100% rename from tests/ui/never_type/diverging-fallback-unconstrained-return.e2024.stderr rename to tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.e2024.stderr diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.fallback.stderr b/tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.fallback.stderr similarity index 100% rename from tests/ui/never_type/diverging-fallback-unconstrained-return.fallback.stderr rename to tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.fallback.stderr diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr b/tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.nofallback.stderr similarity index 100% rename from tests/ui/never_type/diverging-fallback-unconstrained-return.nofallback.stderr rename to tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.nofallback.stderr diff --git a/tests/ui/never_type/diverging-fallback-unconstrained-return.rs b/tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.rs similarity index 100% rename from tests/ui/never_type/diverging-fallback-unconstrained-return.rs rename to tests/ui/never_type/fallback_change/diverging-fallback-unconstrained-return.rs diff --git a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs b/tests/ui/never_type/fallback_change/dont-suggest-turbofish-from-expansion.rs similarity index 100% rename from tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs rename to tests/ui/never_type/fallback_change/dont-suggest-turbofish-from-expansion.rs diff --git a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr b/tests/ui/never_type/fallback_change/dont-suggest-turbofish-from-expansion.stderr similarity index 100% rename from tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr rename to tests/ui/never_type/fallback_change/dont-suggest-turbofish-from-expansion.stderr diff --git a/tests/ui/never_type/fallback-closure-ret.e2021.stderr b/tests/ui/never_type/fallback_change/fallback-closure-ret.e2021.stderr similarity index 100% rename from tests/ui/never_type/fallback-closure-ret.e2021.stderr rename to tests/ui/never_type/fallback_change/fallback-closure-ret.e2021.stderr diff --git a/tests/ui/never_type/fallback-closure-ret.e2024.stderr b/tests/ui/never_type/fallback_change/fallback-closure-ret.e2024.stderr similarity index 100% rename from tests/ui/never_type/fallback-closure-ret.e2024.stderr rename to tests/ui/never_type/fallback_change/fallback-closure-ret.e2024.stderr diff --git a/tests/ui/never_type/fallback-closure-ret.fallback.stderr b/tests/ui/never_type/fallback_change/fallback-closure-ret.fallback.stderr similarity index 100% rename from tests/ui/never_type/fallback-closure-ret.fallback.stderr rename to tests/ui/never_type/fallback_change/fallback-closure-ret.fallback.stderr diff --git a/tests/ui/never_type/fallback-closure-ret.nofallback.stderr b/tests/ui/never_type/fallback_change/fallback-closure-ret.nofallback.stderr similarity index 100% rename from tests/ui/never_type/fallback-closure-ret.nofallback.stderr rename to tests/ui/never_type/fallback_change/fallback-closure-ret.nofallback.stderr diff --git a/tests/ui/never_type/fallback-closure-ret.rs b/tests/ui/never_type/fallback_change/fallback-closure-ret.rs similarity index 100% rename from tests/ui/never_type/fallback-closure-ret.rs rename to tests/ui/never_type/fallback_change/fallback-closure-ret.rs diff --git a/tests/ui/never_type/fallback-closure-wrap.e2024.stderr b/tests/ui/never_type/fallback_change/fallback-closure-wrap.e2024.stderr similarity index 100% rename from tests/ui/never_type/fallback-closure-wrap.e2024.stderr rename to tests/ui/never_type/fallback_change/fallback-closure-wrap.e2024.stderr diff --git a/tests/ui/never_type/fallback-closure-wrap.fallback.stderr b/tests/ui/never_type/fallback_change/fallback-closure-wrap.fallback.stderr similarity index 100% rename from tests/ui/never_type/fallback-closure-wrap.fallback.stderr rename to tests/ui/never_type/fallback_change/fallback-closure-wrap.fallback.stderr diff --git a/tests/ui/never_type/fallback-closure-wrap.rs b/tests/ui/never_type/fallback_change/fallback-closure-wrap.rs similarity index 100% rename from tests/ui/never_type/fallback-closure-wrap.rs rename to tests/ui/never_type/fallback_change/fallback-closure-wrap.rs diff --git a/tests/ui/never_type/from_infer_breaking_with_unit_fallback.rs b/tests/ui/never_type/fallback_change/from_infer_breaking_with_unit_fallback.rs similarity index 90% rename from tests/ui/never_type/from_infer_breaking_with_unit_fallback.rs rename to tests/ui/never_type/fallback_change/from_infer_breaking_with_unit_fallback.rs index 19a1f9d0e1318..970c642514b23 100644 --- a/tests/ui/never_type/from_infer_breaking_with_unit_fallback.rs +++ b/tests/ui/never_type/fallback_change/from_infer_breaking_with_unit_fallback.rs @@ -2,7 +2,7 @@ // // This is a *minimization* of the issue. // Note that the original version with the `?` does not fail anymore even with fallback to unit, -// see `tests/ui/never_type/question_mark_from_never.rs`. +// see `tests/ui/never_type/fallback_change/question_mark_from_never.rs`. // //@ revisions: unit never //@[never] check-pass diff --git a/tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr b/tests/ui/never_type/fallback_change/from_infer_breaking_with_unit_fallback.unit.stderr similarity index 100% rename from tests/ui/never_type/from_infer_breaking_with_unit_fallback.unit.stderr rename to tests/ui/never_type/fallback_change/from_infer_breaking_with_unit_fallback.unit.stderr diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed b/tests/ui/never_type/fallback_change/lint-breaking-2024-assign-underscore.fixed similarity index 100% rename from tests/ui/never_type/lint-breaking-2024-assign-underscore.fixed rename to tests/ui/never_type/fallback_change/lint-breaking-2024-assign-underscore.fixed diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.rs b/tests/ui/never_type/fallback_change/lint-breaking-2024-assign-underscore.rs similarity index 100% rename from tests/ui/never_type/lint-breaking-2024-assign-underscore.rs rename to tests/ui/never_type/fallback_change/lint-breaking-2024-assign-underscore.rs diff --git a/tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr b/tests/ui/never_type/fallback_change/lint-breaking-2024-assign-underscore.stderr similarity index 100% rename from tests/ui/never_type/lint-breaking-2024-assign-underscore.stderr rename to tests/ui/never_type/fallback_change/lint-breaking-2024-assign-underscore.stderr diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr b/tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr similarity index 100% rename from tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr rename to tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr b/tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr similarity index 100% rename from tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr rename to tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs b/tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.rs similarity index 100% rename from tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.rs rename to tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.rs diff --git a/tests/ui/never_type/question_mark_from_never.rs b/tests/ui/never_type/fallback_change/question_mark_from_never.rs similarity index 93% rename from tests/ui/never_type/question_mark_from_never.rs rename to tests/ui/never_type/fallback_change/question_mark_from_never.rs index 8d73313667abe..8f5862a2a0ea2 100644 --- a/tests/ui/never_type/question_mark_from_never.rs +++ b/tests/ui/never_type/fallback_change/question_mark_from_never.rs @@ -1,6 +1,6 @@ // Regression test for . // -// See also: `tests/ui/never_type/from_infer_breaking_with_unit_fallback.rs`. +// See also: `tests/ui/never_type/fallback_change/from_infer_breaking_with_unit_fallback.rs`. // //@ revisions: unit never //@ check-pass diff --git a/tests/ui/never_type/try-block-never-type-fallback.e2021.stderr b/tests/ui/never_type/fallback_change/try-block-never-type-fallback.e2021.stderr similarity index 100% rename from tests/ui/never_type/try-block-never-type-fallback.e2021.stderr rename to tests/ui/never_type/fallback_change/try-block-never-type-fallback.e2021.stderr diff --git a/tests/ui/never_type/try-block-never-type-fallback.rs b/tests/ui/never_type/fallback_change/try-block-never-type-fallback.rs similarity index 100% rename from tests/ui/never_type/try-block-never-type-fallback.rs rename to tests/ui/never_type/fallback_change/try-block-never-type-fallback.rs diff --git a/tests/ui/never_type/issue-10176.rs b/tests/ui/never_type/issue-10176.rs deleted file mode 100644 index 41e012d023f9c..0000000000000 --- a/tests/ui/never_type/issue-10176.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn f() -> isize { //~ NOTE expected `isize` because of return type - (return 1, return 2) -//~^ ERROR mismatched types -//~| NOTE expected type `isize` -//~| NOTE found tuple `(!, !)` -//~| NOTE expected `isize`, found `(!, !)` -} - -fn main() {} diff --git a/tests/ui/never_type/issue-10176.stderr b/tests/ui/never_type/issue-10176.stderr deleted file mode 100644 index cd6473e0682aa..0000000000000 --- a/tests/ui/never_type/issue-10176.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0308]: mismatched types - --> $DIR/issue-10176.rs:2:5 - | -LL | fn f() -> isize { - | ----- expected `isize` because of return type -LL | (return 1, return 2) - | ^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `(!, !)` - | - = note: expected type `isize` - found tuple `(!, !)` - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/never_type/issue-2149.rs b/tests/ui/never_type/issue-2149.rs deleted file mode 100644 index d6426d2cfabfd..0000000000000 --- a/tests/ui/never_type/issue-2149.rs +++ /dev/null @@ -1,15 +0,0 @@ -trait VecMonad { - fn bind(&self, f: F) where F: FnMut(A) -> Vec; -} - -impl VecMonad for Vec { - fn bind(&self, mut f: F) where F: FnMut(A) -> Vec { - let mut r = panic!(); - for elt in self { r = r + f(*elt); } - //~^ ERROR E0277 - } -} -fn main() { - ["hi"].bind(|x| [x] ); - //~^ ERROR no method named `bind` found -} diff --git a/tests/ui/never_type/issue-2149.stderr b/tests/ui/never_type/issue-2149.stderr deleted file mode 100644 index 58fe2edb1e41c..0000000000000 --- a/tests/ui/never_type/issue-2149.stderr +++ /dev/null @@ -1,25 +0,0 @@ -error[E0277]: cannot add `Vec` to `()` - --> $DIR/issue-2149.rs:8:33 - | -LL | for elt in self { r = r + f(*elt); } - | ^ no implementation for `() + Vec` - | - = help: the trait `Add>` is not implemented for `()` - -error[E0599]: no method named `bind` found for array `[&str; 1]` in the current scope - --> $DIR/issue-2149.rs:13:12 - | -LL | ["hi"].bind(|x| [x] ); - | ^^^^ method not found in `[&str; 1]` - | - = help: items from traits can only be used if the trait is implemented and in scope -note: `VecMonad` defines an item `bind`, perhaps you need to implement it - --> $DIR/issue-2149.rs:1:1 - | -LL | trait VecMonad { - | ^^^^^^^^^^^^^^^^^ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0277, E0599. -For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/never-pattern-as-closure-param-141592.rs b/tests/ui/never_type/never_pattern/never-pattern-as-closure-param-141592.rs similarity index 100% rename from tests/ui/never_type/never-pattern-as-closure-param-141592.rs rename to tests/ui/never_type/never_pattern/never-pattern-as-closure-param-141592.rs diff --git a/tests/ui/never_type/never-pattern-as-closure-param-141592.stderr b/tests/ui/never_type/never_pattern/never-pattern-as-closure-param-141592.stderr similarity index 100% rename from tests/ui/never_type/never-pattern-as-closure-param-141592.stderr rename to tests/ui/never_type/never_pattern/never-pattern-as-closure-param-141592.stderr diff --git a/tests/ui/never_type/unused_trait_in_never_pattern_body.rs b/tests/ui/never_type/never_pattern/unused_trait_in_never_pattern_body.rs similarity index 100% rename from tests/ui/never_type/unused_trait_in_never_pattern_body.rs rename to tests/ui/never_type/never_pattern/unused_trait_in_never_pattern_body.rs diff --git a/tests/ui/never_type/unused_trait_in_never_pattern_body.stderr b/tests/ui/never_type/never_pattern/unused_trait_in_never_pattern_body.stderr similarity index 100% rename from tests/ui/never_type/unused_trait_in_never_pattern_body.stderr rename to tests/ui/never_type/never_pattern/unused_trait_in_never_pattern_body.stderr diff --git a/tests/ui/never_type/regress/divergent-block-with-tail.rs b/tests/ui/never_type/regress/divergent-block-with-tail.rs new file mode 100644 index 0000000000000..ac34d6b4ad256 --- /dev/null +++ b/tests/ui/never_type/regress/divergent-block-with-tail.rs @@ -0,0 +1,20 @@ +// Rust briefly used to allow blocks with divergent statements to type check as `!`, even if they +// had a tail expression. This led to a number of regressions (because type information no longer +// flowed from the tail expression) and was quickly reverted.i +// +// See , +// , +// . +// +//@ edition:2015..2021 + +fn g() { + &panic!() //~ ERROR mismatched types +} + +// This used to ICE, see +fn f() -> isize { + (return 1, return 2) //~ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/never_type/diverging-tuple-parts-39485.stderr b/tests/ui/never_type/regress/divergent-block-with-tail.stderr similarity index 100% rename from tests/ui/never_type/diverging-tuple-parts-39485.stderr rename to tests/ui/never_type/regress/divergent-block-with-tail.stderr diff --git a/tests/ui/never_type/eq-never-types.rs b/tests/ui/never_type/regress/eq-never-types.rs similarity index 100% rename from tests/ui/never_type/eq-never-types.rs rename to tests/ui/never_type/regress/eq-never-types.rs diff --git a/tests/ui/never_type/field-access-never-type-13847.rs b/tests/ui/never_type/regress/field-access-never-type-13847.rs similarity index 100% rename from tests/ui/never_type/field-access-never-type-13847.rs rename to tests/ui/never_type/regress/field-access-never-type-13847.rs diff --git a/tests/ui/never_type/field-access-never-type-13847.stderr b/tests/ui/never_type/regress/field-access-never-type-13847.stderr similarity index 100% rename from tests/ui/never_type/field-access-never-type-13847.stderr rename to tests/ui/never_type/regress/field-access-never-type-13847.stderr diff --git a/tests/ui/never_type/issue-13352.rs b/tests/ui/never_type/regress/issue-13352.rs similarity index 100% rename from tests/ui/never_type/issue-13352.rs rename to tests/ui/never_type/regress/issue-13352.rs diff --git a/tests/ui/never_type/issue-13352.stderr b/tests/ui/never_type/regress/issue-13352.stderr similarity index 100% rename from tests/ui/never_type/issue-13352.stderr rename to tests/ui/never_type/regress/issue-13352.stderr diff --git a/tests/ui/never_type/issue-44402.rs b/tests/ui/never_type/regress/issue-44402.rs similarity index 100% rename from tests/ui/never_type/issue-44402.rs rename to tests/ui/never_type/regress/issue-44402.rs diff --git a/tests/ui/never_type/issue-51506.rs b/tests/ui/never_type/regress/issue-51506.rs similarity index 100% rename from tests/ui/never_type/issue-51506.rs rename to tests/ui/never_type/regress/issue-51506.rs diff --git a/tests/ui/never_type/issue-51506.stderr b/tests/ui/never_type/regress/issue-51506.stderr similarity index 100% rename from tests/ui/never_type/issue-51506.stderr rename to tests/ui/never_type/regress/issue-51506.stderr diff --git a/tests/ui/never_type/issue-52443.rs b/tests/ui/never_type/regress/issue-52443.rs similarity index 100% rename from tests/ui/never_type/issue-52443.rs rename to tests/ui/never_type/regress/issue-52443.rs diff --git a/tests/ui/never_type/issue-52443.stderr b/tests/ui/never_type/regress/issue-52443.stderr similarity index 100% rename from tests/ui/never_type/issue-52443.stderr rename to tests/ui/never_type/regress/issue-52443.stderr diff --git a/tests/ui/never_type/issue-5500-1.rs b/tests/ui/never_type/regress/issue-5500-1.rs similarity index 100% rename from tests/ui/never_type/issue-5500-1.rs rename to tests/ui/never_type/regress/issue-5500-1.rs diff --git a/tests/ui/never_type/issue-96335.rs b/tests/ui/never_type/regress/issue-96335.rs similarity index 100% rename from tests/ui/never_type/issue-96335.rs rename to tests/ui/never_type/regress/issue-96335.rs diff --git a/tests/ui/never_type/issue-96335.stderr b/tests/ui/never_type/regress/issue-96335.stderr similarity index 100% rename from tests/ui/never_type/issue-96335.stderr rename to tests/ui/never_type/regress/issue-96335.stderr diff --git a/tests/ui/never_type/never-deref.rs b/tests/ui/never_type/regress/never-deref.rs similarity index 100% rename from tests/ui/never_type/never-deref.rs rename to tests/ui/never_type/regress/never-deref.rs diff --git a/tests/ui/never_type/never-deref.stderr b/tests/ui/never_type/regress/never-deref.stderr similarity index 100% rename from tests/ui/never_type/never-deref.stderr rename to tests/ui/never_type/regress/never-deref.stderr diff --git a/tests/ui/never_type/never-in-range-pat.rs b/tests/ui/never_type/regress/never-in-range-pat.rs similarity index 100% rename from tests/ui/never_type/never-in-range-pat.rs rename to tests/ui/never_type/regress/never-in-range-pat.rs diff --git a/tests/ui/never_type/never-in-range-pat.stderr b/tests/ui/never_type/regress/never-in-range-pat.stderr similarity index 100% rename from tests/ui/never_type/never-in-range-pat.stderr rename to tests/ui/never_type/regress/never-in-range-pat.stderr diff --git a/tests/ui/never_type/never-type-fallback-option.rs b/tests/ui/never_type/regress/never-type-fallback-option.rs similarity index 100% rename from tests/ui/never_type/never-type-fallback-option.rs rename to tests/ui/never_type/regress/never-type-fallback-option.rs diff --git a/tests/ui/never_type/never-type-method-call-15207.rs b/tests/ui/never_type/regress/never-type-method-call-15207.rs similarity index 100% rename from tests/ui/never_type/never-type-method-call-15207.rs rename to tests/ui/never_type/regress/never-type-method-call-15207.rs diff --git a/tests/ui/never_type/never-type-method-call-15207.stderr b/tests/ui/never_type/regress/never-type-method-call-15207.stderr similarity index 100% rename from tests/ui/never_type/never-type-method-call-15207.stderr rename to tests/ui/never_type/regress/never-type-method-call-15207.stderr diff --git a/tests/ui/never_type/span-bug-issue-121445.rs b/tests/ui/never_type/regress/span-bug-issue-121445.rs similarity index 100% rename from tests/ui/never_type/span-bug-issue-121445.rs rename to tests/ui/never_type/regress/span-bug-issue-121445.rs diff --git a/tests/ui/never_type/span-bug-issue-121445.stderr b/tests/ui/never_type/regress/span-bug-issue-121445.stderr similarity index 100% rename from tests/ui/never_type/span-bug-issue-121445.stderr rename to tests/ui/never_type/regress/span-bug-issue-121445.stderr diff --git a/tests/ui/never_type/suggestion-ice-132517.rs b/tests/ui/never_type/regress/suggestion-ice-132517.rs similarity index 100% rename from tests/ui/never_type/suggestion-ice-132517.rs rename to tests/ui/never_type/regress/suggestion-ice-132517.rs diff --git a/tests/ui/never_type/suggestion-ice-132517.stderr b/tests/ui/never_type/regress/suggestion-ice-132517.stderr similarity index 100% rename from tests/ui/never_type/suggestion-ice-132517.stderr rename to tests/ui/never_type/regress/suggestion-ice-132517.stderr diff --git a/tests/ui/parser/return-without-semicolon-in-match.rs b/tests/ui/parser/return-without-semicolon-in-match.rs new file mode 100644 index 0000000000000..a8d13254f101f --- /dev/null +++ b/tests/ui/parser/return-without-semicolon-in-match.rs @@ -0,0 +1,13 @@ +// Tests that `return` without a semicolon parses correctly in a match arm. +// See +// +//@ run-pass + +fn f() { + let _x = match true { + true => { 10 } + false => { return } + }; +} + +fn main() {} diff --git a/tests/ui/never_type/never-assign-dead-code.rs b/tests/ui/reachable/never-assign-dead-code.rs similarity index 100% rename from tests/ui/never_type/never-assign-dead-code.rs rename to tests/ui/reachable/never-assign-dead-code.rs diff --git a/tests/ui/never_type/never-assign-dead-code.stderr b/tests/ui/reachable/never-assign-dead-code.stderr similarity index 100% rename from tests/ui/never_type/never-assign-dead-code.stderr rename to tests/ui/reachable/never-assign-dead-code.stderr From a995d489313164836708ab4a839cfc4738ad9dfb Mon Sep 17 00:00:00 2001 From: Jynn Nelson Date: Fri, 12 Dec 2025 14:41:11 -0500 Subject: [PATCH 03/17] Split `is_msvc_link_exe` into a function --- compiler/rustc_codegen_ssa/src/back/link.rs | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 11bee7f865f6c..c56bfff541f53 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -672,6 +672,14 @@ struct LinkerOutput { inner: String, } +fn is_msvc_link_exe(sess: &Session) -> bool { + let (linker_path, flavor) = linker_and_flavor(sess); + sess.target.is_like_msvc + && flavor == LinkerFlavor::Msvc(Lld::No) + // Match exactly "link.exe" + && linker_path.to_str() == Some("link.exe") +} + /// Create a dynamic library or executable. /// /// This will invoke the system linker/cc to create the resulting file. This links to all upstream @@ -860,11 +868,6 @@ fn link_natively( match prog { Ok(prog) => { - let is_msvc_link_exe = sess.target.is_like_msvc - && flavor == LinkerFlavor::Msvc(Lld::No) - // Match exactly "link.exe" - && linker_path.to_str() == Some("link.exe"); - if !prog.status.success() { let mut output = prog.stderr.clone(); output.extend_from_slice(&prog.stdout); @@ -884,7 +887,7 @@ fn link_natively( if let Some(code) = prog.status.code() { // All Microsoft `link.exe` linking ror codes are // four digit numbers in the range 1000 to 9999 inclusive - if is_msvc_link_exe && (code < 1000 || code > 9999) { + if is_msvc_link_exe(sess) && (code < 1000 || code > 9999) { let is_vs_installed = find_msvc_tools::find_vs_version().is_ok(); let has_linker = find_msvc_tools::find_tool(sess.target.arch.desc(), "link.exe") @@ -923,7 +926,7 @@ fn link_natively( // Hide some progress messages from link.exe that we don't care about. // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 - if is_msvc_link_exe { + if is_msvc_link_exe(sess) { if let Ok(str) = str::from_utf8(&prog.stdout) { let mut output = String::with_capacity(str.len()); for line in stdout.lines() { From bbc45c16c49573a4d0553ff4fa6e5be720da4df4 Mon Sep 17 00:00:00 2001 From: Jynn Nelson Date: Fri, 12 Dec 2025 14:54:07 -0500 Subject: [PATCH 04/17] Split `report_linker_output` into its own function --- compiler/rustc_codegen_ssa/src/back/link.rs | 93 ++++++++++++--------- 1 file changed, 53 insertions(+), 40 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c56bfff541f53..f361ede04616d 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -62,6 +62,9 @@ use crate::base::needs_allocator_shim_for_linking; use crate::{ CompiledModule, CompiledModules, CrateInfo, NativeLib, errors, looks_like_rust_object_file, }; +use crate::{ + CodegenLintLevels, CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file +}; pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { if let Err(e) = fs::remove_file(path) { @@ -680,6 +683,55 @@ fn is_msvc_link_exe(sess: &Session) -> bool { && linker_path.to_str() == Some("link.exe") } +fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8], stderr: &[u8]) { + let escaped_stderr = escape_string(&stderr); + let mut escaped_stdout = escape_string(&stdout); + info!("linker stderr:\n{}", &escaped_stderr); + info!("linker stdout:\n{}", &escaped_stdout); + + // Hide some progress messages from link.exe that we don't care about. + // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 + if is_msvc_link_exe(sess) { + if let Ok(str) = str::from_utf8(&stdout) { + let mut output = String::with_capacity(str.len()); + for line in str.lines() { + if line.starts_with(" Creating library") + || line.starts_with("Generating code") + || line.starts_with("Finished generating code") + { + continue; + } else { + output += line; + output += "\r\n" + } + } + escaped_stdout = escape_string(output.trim().as_bytes()) + } + } + + let lint_msg = |msg| { + diag_lint_level( + sess, + LINKER_MESSAGES, + levels.linker_messages, + None, + LinkerOutput { inner: msg }, + ); + }; + + if !escaped_stderr.is_empty() { + // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present. + let stderr = escaped_stderr + .strip_prefix("warning: ") + .unwrap_or(&escaped_stderr) + .replace(": warning: ", ": "); + lint_msg(format!("linker stderr: {stderr}")); + } + if !escaped_stdout.is_empty() { + lint_msg(format!("linker stdout: {}", escaped_stdout)) + } +} + /// Create a dynamic library or executable. /// /// This will invoke the system linker/cc to create the resulting file. This links to all upstream @@ -919,46 +971,7 @@ fn link_natively( sess.dcx().abort_if_errors(); } - let stderr = escape_string(&prog.stderr); - let mut stdout = escape_string(&prog.stdout); - info!("linker stderr:\n{}", &stderr); - info!("linker stdout:\n{}", &stdout); - - // Hide some progress messages from link.exe that we don't care about. - // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 - if is_msvc_link_exe(sess) { - if let Ok(str) = str::from_utf8(&prog.stdout) { - let mut output = String::with_capacity(str.len()); - for line in stdout.lines() { - if line.starts_with(" Creating library") - || line.starts_with("Generating code") - || line.starts_with("Finished generating code") - { - continue; - } - output += line; - output += "\r\n" - } - stdout = escape_string(output.trim().as_bytes()) - } - } - - let level = crate_info.lint_levels.linker_messages; - let lint = |msg| { - diag_lint_level(sess, LINKER_MESSAGES, level, None, LinkerOutput { inner: msg }); - }; - - if !prog.stderr.is_empty() { - // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present. - let stderr = stderr - .strip_prefix("warning: ") - .unwrap_or(&stderr) - .replace(": warning: ", ": "); - lint(format!("linker stderr: {stderr}")); - } - if !stdout.is_empty() { - lint(format!("linker stdout: {}", stdout)) - } + report_linker_output(sess, crate_info.lint_levels, &prog.stdout, &prog.stderr); } Err(e) => { let linker_not_found = e.kind() == io::ErrorKind::NotFound; From 20404bf4a65c3c41391790ace10310a02fec8a05 Mon Sep 17 00:00:00 2001 From: Jynn Nelson Date: Fri, 12 Dec 2025 17:17:24 -0500 Subject: [PATCH 05/17] Split out linker-info from linker-messages - Hide common linker output behind `linker-info` - Add tests - Account for different capitalization on windows-gnu when removing "warning" prefix - Add some more comments - Add macOS deployment-target test - Ignore linker warnings from trying to statically link glibc I don't know what's going on in `nofile-limit.rs` but I want no part of it. - Use a fake linker so tests are platform-independent --- compiler/rustc_codegen_ssa/src/back/link.rs | 130 ++++++++++++++---- compiler/rustc_codegen_ssa/src/lib.rs | 7 +- compiler/rustc_lint_defs/src/builtin.rs | 35 +++++ compiler/rustc_passes/src/check_attr.rs | 4 +- compiler/rustc_passes/src/errors.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + tests/run-make/linker-warning/fake-linker.sh | 17 --- .../macos-deployment-target-warning/foo.c | 1 + .../macos-deployment-target-warning/main.rs | 8 ++ .../macos-deployment-target-warning/rmake.rs | 29 ++++ .../warnings.txt | 11 ++ .../fake-linker.rs | 8 ++ .../windows-gnu-corrupt-drective/main.rs | 6 + .../windows-gnu-corrupt-drective/rmake.rs | 14 ++ tests/ui/linking/macos-ignoring-duplicate.rs | 6 + .../linking/macos-ignoring-duplicate.stderr | 11 ++ tests/ui/linking/macos-search-path.rs | 6 + tests/ui/linking/macos-search-path.stderr | 11 ++ tests/ui/lint/linker-warning.stderr | 2 +- tests/ui/process/nofile-limit.rs | 3 + 20 files changed, 268 insertions(+), 44 deletions(-) delete mode 100755 tests/run-make/linker-warning/fake-linker.sh create mode 100644 tests/run-make/macos-deployment-target-warning/foo.c create mode 100644 tests/run-make/macos-deployment-target-warning/main.rs create mode 100644 tests/run-make/macos-deployment-target-warning/rmake.rs create mode 100644 tests/run-make/macos-deployment-target-warning/warnings.txt create mode 100644 tests/run-make/windows-gnu-corrupt-drective/fake-linker.rs create mode 100644 tests/run-make/windows-gnu-corrupt-drective/main.rs create mode 100644 tests/run-make/windows-gnu-corrupt-drective/rmake.rs create mode 100644 tests/ui/linking/macos-ignoring-duplicate.rs create mode 100644 tests/ui/linking/macos-ignoring-duplicate.stderr create mode 100644 tests/ui/linking/macos-search-path.rs create mode 100644 tests/ui/linking/macos-search-path.stderr diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index f361ede04616d..56dca6c8b9021 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -22,6 +22,7 @@ use rustc_errors::DiagCtxtHandle; use rustc_fs_util::{TempDirBuilder, fix_windows_verbatim_for_gcc, try_canonicalize}; use rustc_hir::attrs::NativeLibKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; +use rustc_lint_defs::builtin::LINKER_INFO; use rustc_macros::Diagnostic; use rustc_metadata::fs::{METADATA_FILENAME, copy_to_stdout, emit_wrapper_file}; use rustc_metadata::{ @@ -60,10 +61,8 @@ use super::rpath::{self, RPathConfig}; use super::{apple, versioned_llvm_target}; use crate::base::needs_allocator_shim_for_linking; use crate::{ - CompiledModule, CompiledModules, CrateInfo, NativeLib, errors, looks_like_rust_object_file, -}; -use crate::{ - CodegenLintLevels, CodegenResults, CompiledModule, CrateInfo, NativeLib, errors, looks_like_rust_object_file + CodegenLintLevels, CompiledModule, CompiledModules, CrateInfo, NativeLib, errors, + looks_like_rust_object_file, }; pub fn ensure_removed(dcx: DiagCtxtHandle<'_>, path: &Path) { @@ -683,30 +682,105 @@ fn is_msvc_link_exe(sess: &Session) -> bool { && linker_path.to_str() == Some("link.exe") } +fn is_macos_ld(sess: &Session) -> bool { + let (_, flavor) = linker_and_flavor(sess); + sess.target.is_like_darwin && matches!(flavor, LinkerFlavor::Darwin(_, Lld::No)) +} + +fn is_windows_gnu_ld(sess: &Session) -> bool { + let (_, flavor) = linker_and_flavor(sess); + sess.target.is_like_windows + && !sess.target.is_like_msvc + && matches!(flavor, LinkerFlavor::Gnu(_, Lld::No)) +} + fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8], stderr: &[u8]) { - let escaped_stderr = escape_string(&stderr); + let mut escaped_stderr = escape_string(&stderr); let mut escaped_stdout = escape_string(&stdout); + let mut linker_info = String::new(); + info!("linker stderr:\n{}", &escaped_stderr); info!("linker stdout:\n{}", &escaped_stdout); - // Hide some progress messages from link.exe that we don't care about. - // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 - if is_msvc_link_exe(sess) { - if let Ok(str) = str::from_utf8(&stdout) { - let mut output = String::with_capacity(str.len()); + fn for_each(bytes: &[u8], mut f: impl FnMut(&str, &mut String)) -> String { + let mut output = String::new(); + if let Ok(str) = str::from_utf8(bytes) { + info!("line: {str}"); + output = String::with_capacity(str.len()); for line in str.lines() { - if line.starts_with(" Creating library") - || line.starts_with("Generating code") - || line.starts_with("Finished generating code") - { - continue; - } else { - output += line; - output += "\r\n" - } + f(line.trim(), &mut output); } - escaped_stdout = escape_string(output.trim().as_bytes()) } + escape_string(output.trim().as_bytes()) + } + + if is_msvc_link_exe(sess) { + info!("inferred MSVC link.exe"); + + escaped_stdout = for_each(&stdout, |line, output| { + // Hide some progress messages from link.exe that we don't care about. + // See https://github.com/chromium/chromium/blob/bfa41e41145ffc85f041384280caf2949bb7bd72/build/toolchain/win/tool_wrapper.py#L144-L146 + if line.starts_with(" Creating library") + || line.starts_with("Generating code") + || line.starts_with("Finished generating code") + { + linker_info += line; + linker_info += "\r\n"; + } else { + *output += line; + *output += "\r\n" + } + }); + } else if is_macos_ld(sess) { + info!("inferred macOS LD"); + + // FIXME: Tracked by https://github.com/rust-lang/rust/issues/136113 + let deployment_mismatch = |line: &str| { + line.starts_with("ld: warning: object file (") + && line.contains("was built for newer 'macOS' version") + && line.contains("than being linked") + }; + // FIXME: This is a real warning we would like to show, but it hits too many crates + // to want to turn it on immediately. + let search_path = |line: &str| { + line.starts_with("ld: warning: search path '") && line.ends_with("' not found") + }; + escaped_stderr = for_each(&stderr, |line, output| { + // This duplicate library warning is just not helpful at all. + if line.starts_with("ld: warning: ignoring duplicate libraries: ") + || deployment_mismatch(line) + || search_path(line) + { + linker_info += line; + linker_info += "\n"; + } else { + *output += line; + *output += "\n" + } + }); + } else if is_windows_gnu_ld(sess) { + info!("inferred Windows GNU LD"); + + let mut saw_exclude_symbol = false; + // See https://github.com/rust-lang/rust/issues/112368. + // FIXME: maybe check that binutils is older than 2.40 before downgrading this warning? + let exclude_symbols = |line: &str| { + line.starts_with("Warning: .drectve `-exclude-symbols:") + && line.ends_with("' unrecognized") + }; + escaped_stderr = for_each(&stderr, |line, output| { + if exclude_symbols(line) { + saw_exclude_symbol = true; + linker_info += line; + linker_info += "\n"; + } else if saw_exclude_symbol && line == "Warning: corrupt .drectve at end of def file" { + linker_info += line; + linker_info += "\n"; + } else { + *output += line; + *output += "\n" + } + }); } let lint_msg = |msg| { @@ -718,18 +792,27 @@ fn report_linker_output(sess: &Session, levels: CodegenLintLevels, stdout: &[u8] LinkerOutput { inner: msg }, ); }; + let lint_info = |msg| { + diag_lint_level(sess, LINKER_INFO, levels.linker_info, None, LinkerOutput { inner: msg }); + }; if !escaped_stderr.is_empty() { // We already print `warning:` at the start of the diagnostic. Remove it from the linker output if present. - let stderr = escaped_stderr - .strip_prefix("warning: ") + escaped_stderr = + escaped_stderr.strip_prefix("warning: ").unwrap_or(&escaped_stderr).to_owned(); + // Windows GNU LD prints uppercase Warning + escaped_stderr = escaped_stderr + .strip_prefix("Warning: ") .unwrap_or(&escaped_stderr) .replace(": warning: ", ": "); - lint_msg(format!("linker stderr: {stderr}")); + lint_msg(format!("linker stderr: {escaped_stderr}")); } if !escaped_stdout.is_empty() { lint_msg(format!("linker stdout: {}", escaped_stdout)) } + if !linker_info.is_empty() { + lint_info(linker_info); + } } /// Create a dynamic library or executable. @@ -971,6 +1054,7 @@ fn link_natively( sess.dcx().abort_if_errors(); } + info!("reporting linker output: flavor={flavor:?}"); report_linker_output(sess, crate_info.lint_levels, &prog.stdout, &prog.stderr); } Err(e) => { diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 6a0a9e7d51bed..62914b82747ce 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -24,6 +24,7 @@ use rustc_data_structures::unord::UnordMap; use rustc_hir::CRATE_HIR_ID; use rustc_hir::attrs::{CfgEntry, NativeLibKind, WindowsSubsystemKind}; use rustc_hir::def_id::CrateNum; +use rustc_lint_defs::builtin::LINKER_INFO; use rustc_macros::{Decodable, Encodable}; use rustc_metadata::EncodedMetadata; use rustc_middle::dep_graph::WorkProduct; @@ -364,10 +365,14 @@ impl CompiledModules { #[derive(Copy, Clone, Debug, Encodable, Decodable)] pub struct CodegenLintLevels { linker_messages: LevelAndSource, + linker_info: LevelAndSource, } impl CodegenLintLevels { pub fn from_tcx(tcx: TyCtxt<'_>) -> Self { - Self { linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID) } + Self { + linker_messages: tcx.lint_level_at_node(LINKER_MESSAGES, CRATE_HIR_ID), + linker_info: tcx.lint_level_at_node(LINKER_INFO, CRATE_HIR_ID), + } } } diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index c1df8aac6f319..2ef1d5bd14269 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -61,6 +61,7 @@ declare_lint_pass! { LARGE_ASSIGNMENTS, LATE_BOUND_LIFETIME_ARGUMENTS, LEGACY_DERIVE_HELPERS, + LINKER_INFO, LINKER_MESSAGES, LONG_RUNNING_CONST_EVAL, LOSSY_PROVENANCE_CASTS, @@ -4062,6 +4063,40 @@ declare_lint! { "warnings emitted at runtime by the target-specific linker program" } +declare_lint! { + /// The `linker_info` lint forwards warnings from the linker that are known to be informational-only. + /// + /// ### Example + /// + /// ```rust,ignore (needs CLI args, platform-specific) + /// #[warn(linker_info)] + /// fn main () {} + /// ``` + /// + /// On MacOS, using `-C link-arg=-lc` and the default linker, this will produce + /// + /// ```text + /// warning: linker stderr: ld: ignoring duplicate libraries: '-lc' + /// | + /// note: the lint level is defined here + /// --> ex.rs:1:9 + /// | + /// 1 | #![warn(linker_info)] + /// | ^^^^^^^^^^^^^^^ + /// ``` + /// + /// ### Explanation + /// + /// Many linkers are very "chatty" and print lots of information that is not necessarily + /// indicative of an issue. This output has been ignored for many years and is often not + /// actionable by developers. It is silenced unless the developer specifically requests for it + /// to be printed. See this tracking issue for more details: + /// . + pub LINKER_INFO, + Allow, + "linker warnings known to be informational-only and not indicative of a problem" +} + declare_lint! { /// The `named_arguments_used_positionally` lint detects cases where named arguments are only /// used positionally in format strings. This usage is valid but potentially very confusing. diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3e2f10df20b8f..9b729d238ea14 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1621,7 +1621,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::expect, ]) && let Some(meta) = attr.meta_item_list() && meta.iter().any(|meta| { - meta.meta_item().map_or(false, |item| item.path == sym::linker_messages) + meta.meta_item().map_or(false, |item| { + item.path == sym::linker_messages || item.path == sym::linker_info + }) }) { if hir_id != CRATE_HIR_ID { diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs index 8073cb257b032..accade79b1d3f 100644 --- a/compiler/rustc_passes/src/errors.rs +++ b/compiler/rustc_passes/src/errors.rs @@ -310,7 +310,7 @@ pub(crate) enum UnusedNote { #[note("`default_method_body_is_const` has been replaced with `const` on traits")] DefaultMethodBodyConst, #[note( - "the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked" + "the `linker_messages` and `linker_info` lints can only be controlled at the root of a crate that needs to be linked" )] LinkerMessagesBinaryCrateOnly, } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 495611a06e04a..a8d0fa9d8af27 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1152,6 +1152,7 @@ symbols! { link_section, linkage, linker, + linker_info, linker_messages, linkonce, linkonce_odr, diff --git a/tests/run-make/linker-warning/fake-linker.sh b/tests/run-make/linker-warning/fake-linker.sh deleted file mode 100755 index ed4d472c3bfbd..0000000000000 --- a/tests/run-make/linker-warning/fake-linker.sh +++ /dev/null @@ -1,17 +0,0 @@ -#!/bin/sh - -code=0 -while ! [ $# = 0 ]; do - case "$1" in - run_make_info) echo "foo" - ;; - run_make_warn) echo "warning: bar" >&2 - ;; - run_make_error) echo "error: baz" >&2; code=1 - ;; - *) ;; # rustc passes lots of args we don't care about - esac - shift -done - -exit $code diff --git a/tests/run-make/macos-deployment-target-warning/foo.c b/tests/run-make/macos-deployment-target-warning/foo.c new file mode 100644 index 0000000000000..85e6cd8c3909a --- /dev/null +++ b/tests/run-make/macos-deployment-target-warning/foo.c @@ -0,0 +1 @@ +void foo() {} diff --git a/tests/run-make/macos-deployment-target-warning/main.rs b/tests/run-make/macos-deployment-target-warning/main.rs new file mode 100644 index 0000000000000..2c3be92812e12 --- /dev/null +++ b/tests/run-make/macos-deployment-target-warning/main.rs @@ -0,0 +1,8 @@ +#![warn(linker_info, linker_messages)] +unsafe extern "C" { + safe fn foo(); +} + +fn main() { + foo(); +} diff --git a/tests/run-make/macos-deployment-target-warning/rmake.rs b/tests/run-make/macos-deployment-target-warning/rmake.rs new file mode 100644 index 0000000000000..e109b2adcc17a --- /dev/null +++ b/tests/run-make/macos-deployment-target-warning/rmake.rs @@ -0,0 +1,29 @@ +//@ only-apple +//! Tests that deployment target linker warnings are shown as `linker-info`, not `linker-messages` + +use run_make_support::external_deps::c_cxx_compiler::cc; +use run_make_support::external_deps::llvm::llvm_ar; +use run_make_support::{bare_rustc, diff}; + +fn main() { + let cwd = std::env::current_dir().unwrap().to_str().unwrap().to_owned(); + + cc().arg("-c").arg("-mmacosx-version-min=15.5").output("foo.o").input("foo.c").run(); + llvm_ar().obj_to_ar().output_input("libfoo.a", "foo.o").run(); + + let warnings = bare_rustc() + .arg("-L") + .arg(format!("native={cwd}")) + .arg("-lstatic=foo") + .link_arg("-mmacosx-version-min=11.2") + .input("main.rs") + .crate_type("bin") + .run() + .stderr_utf8(); + + diff() + .expected_file("warnings.txt") + .actual_text("(rustc -W linker-info)", &warnings) + .normalize(r"\(.*/rmake_out/", "(TEST_DIR/") + .run() +} diff --git a/tests/run-make/macos-deployment-target-warning/warnings.txt b/tests/run-make/macos-deployment-target-warning/warnings.txt new file mode 100644 index 0000000000000..ab08c6d9ae5b2 --- /dev/null +++ b/tests/run-make/macos-deployment-target-warning/warnings.txt @@ -0,0 +1,11 @@ +warning: ld: warning: object file (TEST_DIR/libfoo.a[2](foo.o)) was built for newer 'macOS' version (15.5) than being linked (11.2) + + | +note: the lint level is defined here + --> main.rs:1:9 + | +1 | #![warn(linker_info, linker_messages)] + | ^^^^^^^^^^^ + +warning: 1 warning emitted + diff --git a/tests/run-make/windows-gnu-corrupt-drective/fake-linker.rs b/tests/run-make/windows-gnu-corrupt-drective/fake-linker.rs new file mode 100644 index 0000000000000..63bcc41904c4e --- /dev/null +++ b/tests/run-make/windows-gnu-corrupt-drective/fake-linker.rs @@ -0,0 +1,8 @@ +// ignore-tidy-linelength + +fn main() { + println!( + "Warning: .drectve `-exclude-symbols:_ZN28windows_gnu_corrupt_drective4main17h291ed884c1aada69E ' unrecognized" + ); + println!("Warning: corrupt .drectve at end of def file"); +} diff --git a/tests/run-make/windows-gnu-corrupt-drective/main.rs b/tests/run-make/windows-gnu-corrupt-drective/main.rs new file mode 100644 index 0000000000000..983bddd2187a8 --- /dev/null +++ b/tests/run-make/windows-gnu-corrupt-drective/main.rs @@ -0,0 +1,6 @@ +//@ only-windows-gnu +//@ build-fail +//@ compile-flags: -C linker={{src-base}}/linking/auxiliary/fake-linker.ps1 +#![deny(linker_info)] +//~? ERROR Warning: .drectve +fn main() {} diff --git a/tests/run-make/windows-gnu-corrupt-drective/rmake.rs b/tests/run-make/windows-gnu-corrupt-drective/rmake.rs new file mode 100644 index 0000000000000..4000941d9f82e --- /dev/null +++ b/tests/run-make/windows-gnu-corrupt-drective/rmake.rs @@ -0,0 +1,14 @@ +//@ only-windows-gnu + +use run_make_support::{bare_rustc, rustc}; + +fn main() { + // bare_rustc so that this doesn't try to cross-compile our linker + bare_rustc().input("fake-linker.rs").output("fake-linker").run(); + rustc() + .input("main.rs") + .linker("./fake-linker") + .arg("-Wlinker-messages") + .run() + .assert_stderr_contains("Warning: .drectve"); +} diff --git a/tests/ui/linking/macos-ignoring-duplicate.rs b/tests/ui/linking/macos-ignoring-duplicate.rs new file mode 100644 index 0000000000000..0c9241c8ee195 --- /dev/null +++ b/tests/ui/linking/macos-ignoring-duplicate.rs @@ -0,0 +1,6 @@ +//@ only-apple +//@ compile-flags: -C link-arg=-lc -C link-arg=-lc +//@ build-fail +#![deny(linker_info)] +//~? ERROR ignoring duplicate libraries +fn main() {} diff --git a/tests/ui/linking/macos-ignoring-duplicate.stderr b/tests/ui/linking/macos-ignoring-duplicate.stderr new file mode 100644 index 0000000000000..9037e8f4e391b --- /dev/null +++ b/tests/ui/linking/macos-ignoring-duplicate.stderr @@ -0,0 +1,11 @@ +error: ld: warning: ignoring duplicate libraries: '-lc' + + | +note: the lint level is defined here + --> $DIR/macos-ignoring-duplicate.rs:4:9 + | +LL | #![deny(linker_info)] + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/linking/macos-search-path.rs b/tests/ui/linking/macos-search-path.rs new file mode 100644 index 0000000000000..6d3e420bcdf6d --- /dev/null +++ b/tests/ui/linking/macos-search-path.rs @@ -0,0 +1,6 @@ +//@ only-apple +//@ compile-flags: -C link-arg=-Wl,-L/no/such/file/or/directory +//@ build-fail +#![deny(linker_info)] +//~? ERROR search path +fn main() {} diff --git a/tests/ui/linking/macos-search-path.stderr b/tests/ui/linking/macos-search-path.stderr new file mode 100644 index 0000000000000..598036d0d403e --- /dev/null +++ b/tests/ui/linking/macos-search-path.stderr @@ -0,0 +1,11 @@ +error: ld: warning: search path '/no/such/file/or/directory' not found + + | +note: the lint level is defined here + --> $DIR/macos-search-path.rs:4:9 + | +LL | #![deny(linker_info)] + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/lint/linker-warning.stderr b/tests/ui/lint/linker-warning.stderr index ae5f6b3adece0..54994c48ea43a 100644 --- a/tests/ui/lint/linker-warning.stderr +++ b/tests/ui/lint/linker-warning.stderr @@ -20,7 +20,7 @@ warning: unused attribute LL | #![allow(linker_messages)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: remove this attribute | - = note: the `linker_messages` lint can only be controlled at the root of a crate that needs to be linked + = note: the `linker_messages` and `linker_info` lints can only be controlled at the root of a crate that needs to be linked warning: 2 warnings emitted diff --git a/tests/ui/process/nofile-limit.rs b/tests/ui/process/nofile-limit.rs index 64777b514256e..f5246856b80f2 100644 --- a/tests/ui/process/nofile-limit.rs +++ b/tests/ui/process/nofile-limit.rs @@ -11,6 +11,9 @@ #![feature(exit_status_error)] #![feature(rustc_private)] +// on aarch64, "Using 'getaddrinfo' in statically linked applications requires at runtime the shared +// libraries from the glibc version used for linking" +#![allow(linker_messages)] extern crate libc; use std::os::unix::process::CommandExt; From 15e839e00604815898e16ec25835ef9b33bb5205 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 6 Mar 2026 15:22:17 +0000 Subject: [PATCH 06/17] Fallback to fat LTO for -Clto=thin in cg_gcc Fallback to no LTO doesn't work in practice as Cargo asks rustc to produce LTO-only rlibs with -Clinker-plugin-lto without providing any indication if they will be used for thin or fat LTO, so we can't disable -Clinker-plugin-lto for ThinLTO when using cg_gcc. --- compiler/rustc_session/src/errors.rs | 2 +- compiler/rustc_session/src/session.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs index 219ec5c51279e..cb3f7363957ef 100644 --- a/compiler/rustc_session/src/errors.rs +++ b/compiler/rustc_session/src/errors.rs @@ -539,5 +539,5 @@ pub(crate) struct UnexpectedBuiltinCfg { } #[derive(Diagnostic)] -#[diag("ThinLTO is not supported by the codegen backend")] +#[diag("ThinLTO is not supported by the codegen backend, using fat LTO instead")] pub(crate) struct ThinLtoNotSupportedByBackend; diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 30840a4872733..0548380331bef 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -620,9 +620,9 @@ impl Session { config::LtoCli::Thin => { // The user explicitly asked for ThinLTO if !self.thin_lto_supported { - // Backend doesn't support ThinLTO, disable LTO. + // Backend doesn't support ThinLTO, fallback to fat LTO. self.dcx().emit_warn(errors::ThinLtoNotSupportedByBackend); - return config::Lto::No; + return config::Lto::Fat; } return config::Lto::Thin; } From 05174fbcc5564a4bd7ced9ac7154efab45c65f3f Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Fri, 14 Nov 2025 00:24:27 +0100 Subject: [PATCH 07/17] tidy never type `issue-*` tests --- src/tools/tidy/src/issues.txt | 8 ----- .../{issue-5500-1.rs => address-of-never.rs} | 7 ++-- .../regress/divergent-block-with-tail.stderr | 4 +-- tests/ui/never_type/regress/issue-13352.rs | 9 ----- .../ui/never_type/regress/issue-13352.stderr | 28 --------------- tests/ui/never_type/regress/issue-44402.rs | 34 ------------------- ...issue-52443.rs => loop-in-array-length.rs} | 2 ++ ...443.stderr => loop-in-array-length.stderr} | 10 +++--- ...e-96335.rs => malformed-range-to-never.rs} | 2 ++ ...stderr => malformed-range-to-never.stderr} | 4 +-- .../regress/never-as-function-argument.rs | 13 +++++++ ... never-as-spec-default-associated-type.rs} | 0 ...er-as-spec-default-associated-type.stderr} | 4 +-- .../return-without-semicolon-in-match.rs | 9 ++--- 14 files changed, 36 insertions(+), 98 deletions(-) rename tests/ui/never_type/regress/{issue-5500-1.rs => address-of-never.rs} (53%) delete mode 100644 tests/ui/never_type/regress/issue-13352.rs delete mode 100644 tests/ui/never_type/regress/issue-13352.stderr delete mode 100644 tests/ui/never_type/regress/issue-44402.rs rename tests/ui/never_type/regress/{issue-52443.rs => loop-in-array-length.rs} (84%) rename tests/ui/never_type/regress/{issue-52443.stderr => loop-in-array-length.stderr} (89%) rename tests/ui/never_type/regress/{issue-96335.rs => malformed-range-to-never.rs} (57%) rename tests/ui/never_type/regress/{issue-96335.stderr => malformed-range-to-never.stderr} (89%) create mode 100644 tests/ui/never_type/regress/never-as-function-argument.rs rename tests/ui/never_type/regress/{issue-51506.rs => never-as-spec-default-associated-type.rs} (100%) rename tests/ui/never_type/regress/{issue-51506.stderr => never-as-spec-default-associated-type.stderr} (80%) diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt index a533598cb4bd4..d889a1c0c0347 100644 --- a/src/tools/tidy/src/issues.txt +++ b/src/tools/tidy/src/issues.txt @@ -1726,14 +1726,6 @@ ui/moves/issue-46099-move-in-macro.rs ui/moves/issue-72649-uninit-in-loop.rs ui/moves/issue-75904-move-closure-loop.rs ui/moves/issue-99470-move-out-of-some.rs -ui/never_type/issue-10176.rs -ui/never_type/issue-13352.rs -ui/never_type/issue-2149.rs -ui/never_type/issue-44402.rs -ui/never_type/issue-51506.rs -ui/never_type/issue-52443.rs -ui/never_type/issue-5500-1.rs -ui/never_type/issue-96335.rs ui/nll/closure-requirements/issue-58127-mutliple-requirements.rs ui/nll/issue-112604-closure-output-normalize.rs ui/nll/issue-16223.rs diff --git a/tests/ui/never_type/regress/issue-5500-1.rs b/tests/ui/never_type/regress/address-of-never.rs similarity index 53% rename from tests/ui/never_type/regress/issue-5500-1.rs rename to tests/ui/never_type/regress/address-of-never.rs index 802bfa5f79bf1..4ab05a1fa8f59 100644 --- a/tests/ui/never_type/regress/issue-5500-1.rs +++ b/tests/ui/never_type/regress/address-of-never.rs @@ -1,8 +1,7 @@ +// Regression test for , +// check that you can take a reference to the never type. +// //@ edition:2015..2021 -// MIR doesn't generate an error because the assignment isn't reachable. This -// is OK because the test is here to check that the compiler doesn't ICE (cf. -// #5500). - //@ check-pass struct TrieMapIterator<'a> { diff --git a/tests/ui/never_type/regress/divergent-block-with-tail.stderr b/tests/ui/never_type/regress/divergent-block-with-tail.stderr index 90d0d4260d2dd..1f205e8967880 100644 --- a/tests/ui/never_type/regress/divergent-block-with-tail.stderr +++ b/tests/ui/never_type/regress/divergent-block-with-tail.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/diverging-tuple-parts-39485.rs:9:5 + --> $DIR/divergent-block-with-tail.rs:12:5 | LL | &panic!() | ^^^^^^^^^ expected `()`, found `&_` @@ -17,7 +17,7 @@ LL + panic!() | error[E0308]: mismatched types - --> $DIR/diverging-tuple-parts-39485.rs:13:5 + --> $DIR/divergent-block-with-tail.rs:17:5 | LL | fn f() -> isize { | ----- expected `isize` because of return type diff --git a/tests/ui/never_type/regress/issue-13352.rs b/tests/ui/never_type/regress/issue-13352.rs deleted file mode 100644 index 9c884a33c5fec..0000000000000 --- a/tests/ui/never_type/regress/issue-13352.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn foo(_: Box) {} - -fn main() { - foo(loop { - std::process::exit(0); - }); - 2_usize + (loop {}); - //~^ ERROR E0277 -} diff --git a/tests/ui/never_type/regress/issue-13352.stderr b/tests/ui/never_type/regress/issue-13352.stderr deleted file mode 100644 index 5fcbb4aab9937..0000000000000 --- a/tests/ui/never_type/regress/issue-13352.stderr +++ /dev/null @@ -1,28 +0,0 @@ -error[E0277]: cannot add `()` to `usize` - --> $DIR/issue-13352.rs:7:13 - | -LL | 2_usize + (loop {}); - | ^ no implementation for `usize + ()` - | - = help: the trait `Add<()>` is not implemented for `usize` -help: the following other types implement trait `Add` - --> $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: `usize` implements `Add` - ::: $SRC_DIR/core/src/ops/arith.rs:LL:COL - | - = note: in this macro invocation - --> $SRC_DIR/core/src/internal_macros.rs:LL:COL - | - = note: `&usize` implements `Add` - ::: $SRC_DIR/core/src/internal_macros.rs:LL:COL - | - = note: `usize` implements `Add<&usize>` - ::: $SRC_DIR/core/src/internal_macros.rs:LL:COL - | - = note: `&usize` implements `Add` - = note: this error originates in the macro `add_impl` (in Nightly builds, run with -Z macro-backtrace for more info) - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/never_type/regress/issue-44402.rs b/tests/ui/never_type/regress/issue-44402.rs deleted file mode 100644 index ae8c59a5cf06c..0000000000000 --- a/tests/ui/never_type/regress/issue-44402.rs +++ /dev/null @@ -1,34 +0,0 @@ -// Regression test for -// -// Previously inhabitedness check was handling cycles incorrectly causing this -// to not compile. -// -//@ check-pass - -#![allow(dead_code)] -#![feature(never_type)] -#![feature(exhaustive_patterns)] - -struct Foo { - field1: !, - field2: Option<&'static Bar>, -} - -struct Bar { - field1: &'static Foo -} - -fn test_a() { - let x: Option = None; - match x { None => () } -} - -fn test_b() { - let x: Option = None; - match x { - Some(_) => (), - None => () - } -} - -fn main() {} diff --git a/tests/ui/never_type/regress/issue-52443.rs b/tests/ui/never_type/regress/loop-in-array-length.rs similarity index 84% rename from tests/ui/never_type/regress/issue-52443.rs rename to tests/ui/never_type/regress/loop-in-array-length.rs index f505719bfcee4..77e21ff9a794f 100644 --- a/tests/ui/never_type/regress/issue-52443.rs +++ b/tests/ui/never_type/regress/loop-in-array-length.rs @@ -1,3 +1,5 @@ +// Regression test for + fn main() { [(); & { loop { continue } } ]; //~ ERROR mismatched types diff --git a/tests/ui/never_type/regress/issue-52443.stderr b/tests/ui/never_type/regress/loop-in-array-length.stderr similarity index 89% rename from tests/ui/never_type/regress/issue-52443.stderr rename to tests/ui/never_type/regress/loop-in-array-length.stderr index d754bc415781c..a51eb46fb244a 100644 --- a/tests/ui/never_type/regress/issue-52443.stderr +++ b/tests/ui/never_type/regress/loop-in-array-length.stderr @@ -1,5 +1,5 @@ warning: denote infinite loops with `loop { ... }` - --> $DIR/issue-52443.rs:6:11 + --> $DIR/loop-in-array-length.rs:8:11 | LL | [(); {while true {break}; 0}]; | ^^^^^^^^^^ help: use `loop` @@ -7,7 +7,7 @@ LL | [(); {while true {break}; 0}]; = note: `#[warn(while_true)]` on by default error[E0308]: mismatched types - --> $DIR/issue-52443.rs:2:10 + --> $DIR/loop-in-array-length.rs:4:10 | LL | [(); & { loop { continue } } ]; | ^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `&_` @@ -21,7 +21,7 @@ LL + [(); { loop { continue } } ]; | error[E0308]: mismatched types - --> $DIR/issue-52443.rs:4:17 + --> $DIR/loop-in-array-length.rs:6:17 | LL | [(); loop { break }]; | ^^^^^ expected `usize`, found `()` @@ -32,7 +32,7 @@ LL | [(); loop { break 42 }]; | ++ error[E0277]: the trait bound `std::ops::RangeFrom: const Iterator` is not satisfied - --> $DIR/issue-52443.rs:9:21 + --> $DIR/loop-in-array-length.rs:11:21 | LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ required by a bound introduced by this call @@ -42,7 +42,7 @@ note: trait `Iterator` is implemented but not `const` = note: required for `std::ops::RangeFrom` to implement `const IntoIterator` error[E0277]: the trait bound `std::ops::RangeFrom: const Iterator` is not satisfied - --> $DIR/issue-52443.rs:9:21 + --> $DIR/loop-in-array-length.rs:11:21 | LL | [(); { for _ in 0usize.. {}; 0}]; | ^^^^^^^^ diff --git a/tests/ui/never_type/regress/issue-96335.rs b/tests/ui/never_type/regress/malformed-range-to-never.rs similarity index 57% rename from tests/ui/never_type/regress/issue-96335.rs rename to tests/ui/never_type/regress/malformed-range-to-never.rs index 411a7c9df657b..415177b5f7dc6 100644 --- a/tests/ui/never_type/regress/issue-96335.rs +++ b/tests/ui/never_type/regress/malformed-range-to-never.rs @@ -1,3 +1,5 @@ +// Regression test for + fn main() { 0.....{loop{}1}; //~^ ERROR unexpected token diff --git a/tests/ui/never_type/regress/issue-96335.stderr b/tests/ui/never_type/regress/malformed-range-to-never.stderr similarity index 89% rename from tests/ui/never_type/regress/issue-96335.stderr rename to tests/ui/never_type/regress/malformed-range-to-never.stderr index 1193973d5ee8c..37c99430127d0 100644 --- a/tests/ui/never_type/regress/issue-96335.stderr +++ b/tests/ui/never_type/regress/malformed-range-to-never.stderr @@ -1,5 +1,5 @@ error: unexpected token: `...` - --> $DIR/issue-96335.rs:2:6 + --> $DIR/malformed-range-to-never.rs:4:6 | LL | 0.....{loop{}1}; | ^^^ @@ -16,7 +16,7 @@ LL + 0..=..{loop{}1}; | error[E0308]: mismatched types - --> $DIR/issue-96335.rs:2:9 + --> $DIR/malformed-range-to-never.rs:4:9 | LL | 0.....{loop{}1}; | ----^^^^^^^^^^^ diff --git a/tests/ui/never_type/regress/never-as-function-argument.rs b/tests/ui/never_type/regress/never-as-function-argument.rs new file mode 100644 index 0000000000000..c19db508e7c86 --- /dev/null +++ b/tests/ui/never_type/regress/never-as-function-argument.rs @@ -0,0 +1,13 @@ +// Regression test for , +// check that the never type can be used as a function argument. +// +//@run-pass + +fn foo(_: Box) {} + +fn main() { + #[expect(unreachable_code)] + foo(loop { + std::process::exit(0); + }); +} diff --git a/tests/ui/never_type/regress/issue-51506.rs b/tests/ui/never_type/regress/never-as-spec-default-associated-type.rs similarity index 100% rename from tests/ui/never_type/regress/issue-51506.rs rename to tests/ui/never_type/regress/never-as-spec-default-associated-type.rs diff --git a/tests/ui/never_type/regress/issue-51506.stderr b/tests/ui/never_type/regress/never-as-spec-default-associated-type.stderr similarity index 80% rename from tests/ui/never_type/regress/issue-51506.stderr rename to tests/ui/never_type/regress/never-as-spec-default-associated-type.stderr index 0e666e017f9c6..bcb2c7dfae8e7 100644 --- a/tests/ui/never_type/regress/issue-51506.stderr +++ b/tests/ui/never_type/regress/never-as-spec-default-associated-type.stderr @@ -1,12 +1,12 @@ error[E0277]: `!` is not an iterator - --> $DIR/issue-51506.rs:15:24 + --> $DIR/never-as-spec-default-associated-type.rs:15:24 | LL | default type Out = !; | ^ `!` is not an iterator | = help: the trait `Iterator` is not implemented for `!` note: required by a bound in `Trait::Out` - --> $DIR/issue-51506.rs:9:15 + --> $DIR/never-as-spec-default-associated-type.rs:9:15 | LL | type Out: Iterator; | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::Out` diff --git a/tests/ui/parser/return-without-semicolon-in-match.rs b/tests/ui/parser/return-without-semicolon-in-match.rs index a8d13254f101f..bb613ce16c733 100644 --- a/tests/ui/parser/return-without-semicolon-in-match.rs +++ b/tests/ui/parser/return-without-semicolon-in-match.rs @@ -1,12 +1,13 @@ // Tests that `return` without a semicolon parses correctly in a match arm. // See // -//@ run-pass +//@ check-pass -fn f() { +fn _f() { + #[rustfmt::skip] let _x = match true { - true => { 10 } - false => { return } + true => { 10 }, + false => { return }, }; } From 46cedc33b8af4f125e587f031584cd18b9e01a7d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 17:19:41 +0100 Subject: [PATCH 08/17] Use eager formatting in `#[derive(Subdiagnostic)]` --- compiler/rustc_errors/src/lib.rs | 2 +- .../src/diagnostics/subdiagnostic.rs | 38 +++++++++---------- 2 files changed, 19 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 7fc3e4a45d0ab..1db50df6ccbb4 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -66,7 +66,7 @@ use rustc_span::{DUMMY_SP, Span}; use tracing::debug; use crate::emitter::TimingEvent; -use crate::formatting::format_diag_message; +pub use crate::formatting::format_diag_message; use crate::timings::TimingRecord; pub mod annotate_snippet_emitter_writer; diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index 6237421322089..3e094ee8d42b6 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -227,9 +227,9 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let ident = format_ident!("{}", ident); // strip `r#` prefix, if present quote! { - #diag.arg( - stringify!(#ident), - #field_binding + sub_args.insert( + stringify!(#ident).into(), + rustc_errors::IntoDiagArg::into_diag_arg(#field_binding, &mut #diag.long_ty_path) ); } } @@ -529,14 +529,25 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { } }; - let span_field = self.span_field.value_ref(); + let plain_args: TokenStream = self + .variant + .bindings() + .iter() + .filter(|binding| should_generate_arg(binding.ast())) + .map(|binding| self.generate_field_arg(binding)) + .collect(); + let plain_args = quote! { + let mut sub_args = rustc_errors::DiagArgMap::default(); + #plain_args + }; + let span_field = self.span_field.value_ref(); let diag = &self.parent.diag; let mut calls = TokenStream::new(); for (kind, messages) in kind_messages { let message = format_ident!("__message"); let message_stream = messages.diag_message(Some(self.variant)); - calls.extend(quote! { let #message = #diag.eagerly_format(#message_stream); }); + calls.extend(quote! { let #message = rustc_errors::format_diag_message(&#message_stream, &sub_args); }); let name = format_ident!("{}{}", if span_field.is_some() { "span_" } else { "" }, kind); let call = match kind { @@ -600,19 +611,6 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { calls.extend(call); } - let store_args = quote! { - #diag.store_args(); - }; - let restore_args = quote! { - #diag.restore_args(); - }; - let plain_args: TokenStream = self - .variant - .bindings() - .iter() - .filter(|binding| should_generate_arg(binding.ast())) - .map(|binding| self.generate_field_arg(binding)) - .collect(); let formatting_init = &self.formatting_init; @@ -626,10 +624,10 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { #init #formatting_init #attr_args - #store_args + // #store_args #plain_args #calls - #restore_args + // #restore_args }) } } From 2b0552f0cb26703e45fc3d495734b960be782b0f Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 17:02:33 +0100 Subject: [PATCH 09/17] Add new eager formatting API --- compiler/rustc_errors/src/formatting.rs | 90 ++++++++++++++++++------- 1 file changed, 66 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_errors/src/formatting.rs b/compiler/rustc_errors/src/formatting.rs index 1e0d9b7f5f92a..7b617031d6c8e 100644 --- a/compiler/rustc_errors/src/formatting.rs +++ b/compiler/rustc_errors/src/formatting.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; pub use rustc_error_messages::FluentArgs; -use rustc_error_messages::{DiagArgMap, langid, register_functions}; +use rustc_error_messages::{DiagArgMap, DiagArgName, IntoDiagArg, langid, register_functions}; use tracing::{debug, trace}; use crate::fluent_bundle::FluentResource; @@ -33,30 +33,72 @@ pub fn format_diag_messages( /// Convert a `DiagMessage` to a string pub fn format_diag_message<'a>(message: &'a DiagMessage, args: &DiagArgMap) -> Cow<'a, str> { - trace!(?message, ?args); - match message { DiagMessage::Str(msg) => Cow::Borrowed(msg), - DiagMessage::Inline(msg) => { - const GENERATED_MSG_ID: &str = "generated_msg"; - let resource = - FluentResource::try_new(format!("{GENERATED_MSG_ID} = {msg}\n")).unwrap(); - let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); - bundle.set_use_isolating(false); - bundle.add_resource(resource).unwrap(); - register_functions(&mut bundle); - let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); - let value = message.value().unwrap(); - let args = to_fluent_args(args.iter()); - - let mut errs = vec![]; - let formatted = bundle.format_pattern(value, Some(&args), &mut errs).to_string(); - debug!(?formatted, ?errs); - if errs.is_empty() { - Cow::Owned(formatted) - } else { - panic!("Fluent errors while formatting message: {errs:?}"); - } - } + DiagMessage::Inline(msg) => format_fluent_str(msg, args), + } +} + +fn format_fluent_str(message: &str, args: &DiagArgMap) -> Cow<'static, str> { + trace!(?message, ?args); + const GENERATED_MSG_ID: &str = "generated_msg"; + let resource = FluentResource::try_new(format!("{GENERATED_MSG_ID} = {message}\n")).unwrap(); + let mut bundle = fluent_bundle::FluentBundle::new(vec![langid!("en-US")]); + bundle.set_use_isolating(false); + bundle.add_resource(resource).unwrap(); + register_functions(&mut bundle); + let message = bundle.get_message(GENERATED_MSG_ID).unwrap(); + let value = message.value().unwrap(); + let args = to_fluent_args(args.iter()); + + let mut errs = vec![]; + let formatted = bundle.format_pattern(value, Some(&args), &mut errs).to_string(); + debug!(?formatted, ?errs); + if errs.is_empty() { + Cow::Owned(formatted) + } else { + panic!("Fluent errors while formatting message: {errs:?}"); + } +} + +pub trait DiagMessageAddArg { + fn arg(self, name: impl Into, arg: impl IntoDiagArg) -> EagerDiagMessageBuilder; +} + +pub struct EagerDiagMessageBuilder { + fluent_str: Cow<'static, str>, + args: DiagArgMap, +} + +impl DiagMessageAddArg for EagerDiagMessageBuilder { + fn arg( + mut self, + name: impl Into, + arg: impl IntoDiagArg, + ) -> EagerDiagMessageBuilder { + let name = name.into(); + let value = arg.into_diag_arg(&mut None); + debug_assert!( + !self.args.contains_key(&name) || self.args.get(&name) == Some(&value), + "arg {} already exists", + name + ); + self.args.insert(name, value); + self + } +} + +impl DiagMessageAddArg for DiagMessage { + fn arg(self, name: impl Into, arg: impl IntoDiagArg) -> EagerDiagMessageBuilder { + let DiagMessage::Inline(fluent_str) = self else { + panic!("Tried to eagerly format an already formatted message") + }; + EagerDiagMessageBuilder { fluent_str, args: Default::default() }.arg(name, arg) + } +} + +impl EagerDiagMessageBuilder { + pub fn format(self) -> DiagMessage { + DiagMessage::Str(format_fluent_str(&self.fluent_str, &self.args)) } } From c2f1e9d71d149b88ca385ad567fa0af9d0fa3d09 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 17:24:52 +0100 Subject: [PATCH 10/17] Remove stored args from diagnostics --- compiler/rustc_errors/src/diagnostic.rs | 12 ----- compiler/rustc_trait_selection/src/errors.rs | 47 +++++++++---------- .../src/errors/note_and_explain.rs | 19 ++++---- 3 files changed, 31 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index cfc697b521fc5..f73409ce1be51 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -235,9 +235,6 @@ pub struct DiagInner { pub suggestions: Suggestions, pub args: DiagArgMap, - // This is used to store args and restore them after a subdiagnostic is rendered. - pub reserved_args: DiagArgMap, - /// This is not used for highlighting or rendering any error message. Rather, it can be used /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of /// `span` if there is one. Otherwise, it is `DUMMY_SP`. @@ -268,7 +265,6 @@ impl DiagInner { children: vec![], suggestions: Suggestions::Enabled(vec![]), args: Default::default(), - reserved_args: Default::default(), sort_span: DUMMY_SP, is_lint: None, long_ty_path: None, @@ -333,14 +329,6 @@ impl DiagInner { self.args.swap_remove(name); } - pub fn store_args(&mut self) { - self.reserved_args = self.args.clone(); - } - - pub fn restore_args(&mut self) { - self.args = std::mem::take(&mut self.reserved_args); - } - pub fn emitted_at_sub_diag(&self) -> Subdiag { let track = format!("-Ztrack-diagnostics: created at {}", self.emitted_at); Subdiag { diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 254a626ce2216..e4bc7c93fa637 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1,5 +1,6 @@ use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_errors::codes::*; +use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, @@ -450,28 +451,23 @@ impl Subdiagnostic for RegionOriginNote<'_> { requirement, expected_found: Some((expected, found)), } => { - // `RegionOriginNote` can appear multiple times on one diagnostic with different - // `requirement` values. Scope args per-note and eagerly translate to avoid - // cross-note arg collisions. - // See https://github.com/rust-lang/rust/issues/143872 for details. - diag.store_args(); - diag.arg("requirement", requirement); - let msg = diag.eagerly_format(msg!( + let msg = msg!( "...so that the {$requirement -> - [method_compat] method type is compatible with trait - [type_compat] associated type is compatible with trait - [const_compat] const is compatible with trait - [expr_assignable] expression is assignable - [if_else_different] `if` and `else` have incompatible types - [no_else] `if` missing an `else` returns `()` - [fn_main_correct_type] `main` function has the correct type - [fn_lang_correct_type] lang item function has the correct type - [intrinsic_correct_type] intrinsic has the correct type - [method_correct_type] method receiver has the correct type - *[other] types are compatible - }" - )); - diag.restore_args(); + [method_compat] method type is compatible with trait + [type_compat] associated type is compatible with trait + [const_compat] const is compatible with trait + [expr_assignable] expression is assignable + [if_else_different] `if` and `else` have incompatible types + [no_else] `if` missing an `else` returns `()` + [fn_main_correct_type] `main` function has the correct type + [fn_lang_correct_type] lang item function has the correct type + [intrinsic_correct_type] intrinsic has the correct type + [method_correct_type] method receiver has the correct type + *[other] types are compatible + }" + ) + .arg("requirement", requirement) + .format(); label_or_note(diag, span, msg); diag.note_expected_found("", expected, "", found); @@ -480,9 +476,7 @@ impl Subdiagnostic for RegionOriginNote<'_> { // FIXME: this really should be handled at some earlier stage. Our // handling of region checking when type errors are present is // *terrible*. - diag.store_args(); - diag.arg("requirement", requirement); - let msg = diag.eagerly_format(msg!( + let msg = msg!( "...so that {$requirement -> [method_compat] method type is compatible with trait [type_compat] associated type is compatible with trait @@ -496,8 +490,9 @@ impl Subdiagnostic for RegionOriginNote<'_> { [method_correct_type] method receiver has the correct type *[other] types are compatible }" - )); - diag.restore_args(); + ) + .arg("requirement", requirement) + .format(); label_or_note(diag, span, msg); } }; diff --git a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs index 5121ca886c1bd..fd943bff3700b 100644 --- a/compiler/rustc_trait_selection/src/errors/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/errors/note_and_explain.rs @@ -1,3 +1,4 @@ +use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{Diag, EmissionGuarantee, IntoDiagArg, Subdiagnostic, msg}; use rustc_hir::def_id::LocalDefId; use rustc_middle::bug; @@ -163,13 +164,7 @@ impl RegionExplanation<'_> { impl Subdiagnostic for RegionExplanation<'_> { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - diag.store_args(); - diag.arg("pref_kind", self.prefix); - diag.arg("suff_kind", self.suffix); - diag.arg("desc_kind", self.desc.kind); - diag.arg("desc_arg", self.desc.arg); - - let msg = diag.eagerly_format(msg!( + let msg = msg!( "{$pref_kind -> *[should_not_happen] [{$pref_kind}] [ref_valid_for] ...the reference is valid for @@ -202,8 +197,14 @@ impl Subdiagnostic for RegionExplanation<'_> { [continues] ... [req_by_binding] {\" \"}as required by this binding }" - )); - diag.restore_args(); + ) + .arg("pref_kind", self.prefix) + .arg("suff_kind", self.suffix) + .arg("desc_kind", self.desc.kind) + .arg("desc_arg", self.desc.arg) + .format(); + + // diag.restore_args(); if let Some(span) = self.desc.span { diag.span_note(span, msg); } else { From 828c0c06685a5193e830a85c048253cca48ec39c Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 17:33:15 +0100 Subject: [PATCH 11/17] Remove `remove_arg` from diagnostics --- .../rustc_borrowck/src/diagnostics/mod.rs | 10 ++--- compiler/rustc_builtin_macros/src/errors.rs | 21 +++++---- compiler/rustc_const_eval/src/errors.rs | 15 +++---- compiler/rustc_errors/src/diagnostic.rs | 6 --- compiler/rustc_lint/src/lints.rs | 7 +-- .../src/lint_tail_expr_drop_order.rs | 44 +++++++++---------- 6 files changed, 49 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 28be1a9fdf8eb..af8f723ff378d 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -4,6 +4,7 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_data_structures::fx::FxIndexMap; +use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{Applicability, Diag, DiagMessage, EmissionGuarantee, MultiSpan, listify, msg}; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{ @@ -1309,12 +1310,9 @@ impl<'infcx, 'tcx> MirBorrowckCtxt<'_, 'infcx, 'tcx> { && !spans.is_empty() { let mut span: MultiSpan = spans.clone().into(); - err.arg("ty", param_ty.to_string()); - let msg = err.dcx.eagerly_format_to_string( - msg!("`{$ty}` is made to be an `FnOnce` closure here"), - err.args.iter(), - ); - err.remove_arg("ty"); + let msg = msg!("`{$ty}` is made to be an `FnOnce` closure here") + .arg("ty", param_ty.to_string()) + .format(); for sp in spans { span.push_span_label(sp, msg.clone()); } diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 961644b977592..89dd23dfe281b 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -1,4 +1,5 @@ use rustc_errors::codes::*; +use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, MultiSpan, SingleLabelManySpans, Subdiagnostic, msg, @@ -763,15 +764,17 @@ pub(crate) struct FormatUnusedArg { // form of diagnostic. impl Subdiagnostic for FormatUnusedArg { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - diag.arg("named", self.named); - let msg = diag.eagerly_format(msg!( - "{$named -> - [true] named argument - *[false] argument - } never used" - )); - diag.remove_arg("named"); - diag.span_label(self.span, msg); + diag.span_label( + self.span, + msg!( + "{$named -> + [true] named argument + *[false] argument + } never used" + ) + .arg("named", self.named) + .format(), + ); } } diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 4797b039c9624..c05c6034d7215 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -4,6 +4,7 @@ use std::fmt::Write; use either::Either; use rustc_abi::WrappingRange; use rustc_errors::codes::*; +use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, Subdiagnostic, msg, @@ -359,14 +360,11 @@ pub struct FrameNote { impl Subdiagnostic for FrameNote { fn add_to_diag(self, diag: &mut Diag<'_, G>) { - diag.arg("times", self.times); - diag.arg("where_", self.where_); - diag.arg("instance", self.instance); let mut span: MultiSpan = self.span.into(); if self.has_label && !self.span.is_dummy() { span.push_span_label(self.span, msg!("the failure occurred here")); } - let msg = diag.eagerly_format(msg!( + let msg = msg!( r#"{$times -> [0] inside {$where_ -> [closure] closure @@ -379,10 +377,11 @@ impl Subdiagnostic for FrameNote { *[other] {""} } ...] }"# - )); - diag.remove_arg("times"); - diag.remove_arg("where_"); - diag.remove_arg("instance"); + ) + .arg("times", self.times) + .arg("where_", self.where_) + .arg("instance", self.instance) + .format(); diag.span_note(span, msg); } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index f73409ce1be51..a0c57ef019125 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1328,12 +1328,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self.downgrade_to_delayed_bug(); self.emit() } - - pub fn remove_arg(&mut self, name: &str) { - if let Some(diag) = self.diag.as_mut() { - diag.remove_arg(name); - } - } } /// Destructor bomb: every `Diag` must be consumed (emitted, cancelled, etc.) diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index 5597c5b4c839a..f3f6b099c60e9 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -3,6 +3,7 @@ use std::num::NonZero; use rustc_errors::codes::*; +use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ Applicability, Diag, DiagArgValue, DiagCtxtHandle, DiagMessage, DiagStyledString, Diagnostic, ElidedLifetimeInPathSubdiag, EmissionGuarantee, Level, MultiSpan, Subdiagnostic, @@ -3628,9 +3629,9 @@ impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { } Explicit { lifetime_name, suggestions, optional_alternative } => { - diag.arg("lifetime_name", lifetime_name); - let msg = diag.eagerly_format(msg!("consistently use `{$lifetime_name}`")); - diag.remove_arg("lifetime_name"); + let msg = msg!("consistently use `{$lifetime_name}`") + .arg("lifetime_name", lifetime_name) + .format(); diag.multipart_suggestion_with_style( msg, suggestions, diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index c8d19f2e920a3..c354279b8ed32 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -5,6 +5,7 @@ use std::rc::Rc; use itertools::Itertools as _; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::unord::{UnordMap, UnordSet}; +use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{Subdiagnostic, msg}; use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LocalDefId; @@ -524,31 +525,30 @@ struct LocalLabel<'a> { /// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order impl Subdiagnostic for LocalLabel<'_> { fn add_to_diag(self, diag: &mut rustc_errors::Diag<'_, G>) { - // Because parent uses this field , we need to remove it delay before adding it. - diag.remove_arg("name"); - diag.arg("name", self.name); - diag.remove_arg("is_generated_name"); - diag.arg("is_generated_name", self.is_generated_name); - diag.remove_arg("is_dropped_first_edition_2024"); - diag.arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024); - let msg = diag.eagerly_format(msg!( - "{$is_generated_name -> - [true] this value will be stored in a temporary; let us call it `{$name}` - *[false] `{$name}` calls a custom destructor - }" - )); - diag.span_label(self.span, msg); + diag.span_label( + self.span, + msg!( + "{$is_generated_name -> + [true] this value will be stored in a temporary; let us call it `{$name}` + *[false] `{$name}` calls a custom destructor + }" + ) + .arg("name", self.name) + .arg("is_generated_name", self.is_generated_name) + .format(), + ); for dtor in self.destructors { dtor.add_to_diag(diag); } - let msg = - diag.eagerly_format(msg!( - "{$is_dropped_first_edition_2024 -> - [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 - *[false] `{$name}` will be dropped later as of Edition 2024 - }" - )); - diag.span_label(self.span, msg); + diag.span_label(self.span, msg!( + "{$is_dropped_first_edition_2024 -> + [true] up until Edition 2021 `{$name}` is dropped last but will be dropped earlier in Edition 2024 + *[false] `{$name}` will be dropped later as of Edition 2024 + }" + ) + .arg("is_dropped_first_edition_2024", self.is_dropped_first_edition_2024) + .arg("name", self.name) + .format()); } } From 43221b43b610589c66ff53f2826444438585dbf8 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 17:35:07 +0100 Subject: [PATCH 12/17] Remove `eagerly_format` from `Diag` --- compiler/rustc_errors/src/diagnostic.rs | 10 ---------- compiler/rustc_hir_typeck/src/errors.rs | 6 +++--- compiler/rustc_lint/src/if_let_rescope.rs | 4 ++-- compiler/rustc_trait_selection/src/errors.rs | 12 +++++------- 4 files changed, 10 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index a0c57ef019125..ff212e7c01f0c 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1131,16 +1131,6 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> { self } - /// Fluent variables are not namespaced from each other, so when - /// `Diagnostic`s and `Subdiagnostic`s use the same variable name, - /// one value will clobber the other. Eagerly formatting the - /// diagnostic uses the variables defined right then, before the - /// clobbering occurs. - pub fn eagerly_format(&self, msg: impl Into) -> DiagMessage { - let args = self.args.iter(); - self.dcx.eagerly_format(msg.into(), args) - } - with_fn! { with_span, /// Add a span. pub fn span(&mut self, sp: impl Into) -> &mut Self { diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index 52f6b126a7d0e..e55a8d5f11f18 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -987,13 +987,13 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { fn add_to_diag(self, diag: &mut Diag<'_, G>) { match self { CastUnknownPointerSub::To(span) => { - let msg = diag.eagerly_format(msg!("needs more type information")); + let msg = msg!("needs more type information"); diag.span_label(span, msg); - let msg = diag.eagerly_format(msg!("the type information given here is insufficient to check whether the pointer cast is valid")); + let msg = msg!("the type information given here is insufficient to check whether the pointer cast is valid"); diag.note(msg); } CastUnknownPointerSub::From(span) => { - let msg = diag.eagerly_format(msg!("the type information given here is insufficient to check whether the pointer cast is valid")); + let msg = msg!("the type information given here is insufficient to check whether the pointer cast is valid"); diag.span_label(span, msg); } } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 0a754a7af03b2..14f7b68387056 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -354,9 +354,9 @@ impl Subdiagnostic for IfLetRescopeRewrite { .chain(repeat_n('}', closing_brackets.count)) .collect(), )); - let msg = diag.eagerly_format(msg!( + let msg = msg!( "a `match` with a single arm can preserve the drop order up to Edition 2021" - )); + ); diag.multipart_suggestion_with_style( msg, suggestions, diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index e4bc7c93fa637..823acfaa54093 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1169,7 +1169,7 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp { type_param_span .push_span_label(span, msg!("consider borrowing this type parameter in the trait")); } - let msg = diag.eagerly_format(msg!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`")); + let msg = msg!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`"); diag.span_help(type_param_span, msg); } } @@ -1213,9 +1213,9 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { self.ident.span, msg!("calling this method introduces the `impl`'s `'static` requirement"), ); - let msg = diag.eagerly_format(msg!("the used `impl` has a `'static` requirement")); + let msg = msg!("the used `impl` has a `'static` requirement"); diag.span_note(multi_span, msg); - let msg = diag.eagerly_format(msg!("consider relaxing the implicit `'static` requirement")); + let msg = msg!("consider relaxing the implicit `'static` requirement"); diag.span_suggestion_verbose( self.span.shrink_to_hi(), msg, @@ -1278,8 +1278,7 @@ impl Subdiagnostic for ReqIntroducedLocations { ); } self.span.push_span_label(self.cause_span, msg!("because of this returned expression")); - let msg = diag - .eagerly_format(msg!("\"`'static` lifetime requirement introduced by the return type")); + let msg = msg!("\"`'static` lifetime requirement introduced by the return type"); diag.span_note(self.span, msg); } } @@ -1719,8 +1718,7 @@ pub struct SuggestTuplePatternMany { impl Subdiagnostic for SuggestTuplePatternMany { fn add_to_diag(self, diag: &mut Diag<'_, G>) { diag.arg("path", self.path); - let message = - diag.eagerly_format(msg!("try wrapping the pattern in a variant of `{$path}`")); + let message = msg!("try wrapping the pattern in a variant of `{$path}`"); diag.multipart_suggestions( message, self.compatible_variants.into_iter().map(|variant| { From 8c87d0761f3c2a7fd8f6106037a64e04890b5825 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 17:38:30 +0100 Subject: [PATCH 13/17] Remove `eagerly_format` from `DiagCtxt` --- compiler/rustc_errors/src/lib.rs | 44 ++++---------------- compiler/rustc_hir_typeck/src/errors.rs | 8 +++- compiler/rustc_lint/src/if_let_rescope.rs | 5 +-- compiler/rustc_trait_selection/src/errors.rs | 4 +- 4 files changed, 19 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 1db50df6ccbb4..dbc8884a9fbc9 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -66,6 +66,7 @@ use rustc_span::{DUMMY_SP, Span}; use tracing::debug; use crate::emitter::TimingEvent; +use crate::formatting::DiagMessageAddArg; pub use crate::formatting::format_diag_message; use crate::timings::TimingRecord; @@ -482,16 +483,6 @@ impl DiagCtxt { self.inner.borrow_mut().emitter = emitter; } - /// Format `message` eagerly with `args` to `DiagMessage::Eager`. - pub fn eagerly_format<'a>( - &self, - message: DiagMessage, - args: impl Iterator>, - ) -> DiagMessage { - let inner = self.inner.borrow(); - inner.eagerly_format(message, args) - } - /// Format `message` eagerly with `args` to `String`. pub fn eagerly_format_to_string<'a>( &self, @@ -1417,15 +1408,6 @@ impl DiagCtxtInner { self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } - /// Format `message` eagerly with `args` to `DiagMessage::Eager`. - fn eagerly_format<'a>( - &self, - message: DiagMessage, - args: impl Iterator>, - ) -> DiagMessage { - DiagMessage::Str(Cow::from(self.eagerly_format_to_string(message, args))) - } - /// Format `message` eagerly with `args` to `String`. fn eagerly_format_to_string<'a>( &self, @@ -1436,14 +1418,6 @@ impl DiagCtxtInner { format_diag_message(&message, &args).to_string() } - fn eagerly_format_for_subdiag( - &self, - diag: &DiagInner, - msg: impl Into, - ) -> DiagMessage { - self.eagerly_format(msg.into(), diag.args.iter()) - } - fn flush_delayed(&mut self) { // Stashed diagnostics must be emitted before delayed bugs are flushed. // Otherwise, we might ICE prematurely when errors would have @@ -1493,7 +1467,7 @@ impl DiagCtxtInner { ); } - let mut bug = if decorate { bug.decorate(self) } else { bug.inner }; + let mut bug = if decorate { bug.decorate() } else { bug.inner }; // "Undelay" the delayed bugs into plain bugs. if bug.level != DelayedBug { @@ -1503,11 +1477,9 @@ impl DiagCtxtInner { // We are at the `DiagInner`/`DiagCtxtInner` level rather than // the usual `Diag`/`DiagCtxt` level, so we must augment `bug` // in a lower-level fashion. - bug.arg("level", bug.level); let msg = msg!( "`flushed_delayed` got diagnostic with level {$level}, instead of the expected `DelayedBug`" - ); - let msg = self.eagerly_format_for_subdiag(&bug, msg); // after the `arg` call + ).arg("level", bug.level).format(); bug.sub(Note, msg, bug.span.primary_span().unwrap().into()); } bug.level = Bug; @@ -1542,7 +1514,7 @@ impl DelayedDiagInner { DelayedDiagInner { inner: diagnostic, note: backtrace } } - fn decorate(self, dcx: &DiagCtxtInner) -> DiagInner { + fn decorate(self) -> DiagInner { // We are at the `DiagInner`/`DiagCtxtInner` level rather than the // usual `Diag`/`DiagCtxt` level, so we must construct `diag` in a // lower-level fashion. @@ -1555,10 +1527,10 @@ impl DelayedDiagInner { // Avoid the needless newline when no backtrace has been captured, // the display impl should just be a single line. _ => msg!("delayed at {$emitted_at} - {$note}"), - }; - diag.arg("emitted_at", diag.emitted_at.clone()); - diag.arg("note", self.note); - let msg = dcx.eagerly_format_for_subdiag(&diag, msg); // after the `arg` calls + } + .arg("emitted_at", diag.emitted_at.clone()) + .arg("note", self.note) + .format(); diag.sub(Note, msg, diag.span.primary_span().unwrap_or(DUMMY_SP).into()); diag } diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs index e55a8d5f11f18..5c6a66403019c 100644 --- a/compiler/rustc_hir_typeck/src/errors.rs +++ b/compiler/rustc_hir_typeck/src/errors.rs @@ -989,11 +989,15 @@ impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { CastUnknownPointerSub::To(span) => { let msg = msg!("needs more type information"); diag.span_label(span, msg); - let msg = msg!("the type information given here is insufficient to check whether the pointer cast is valid"); + let msg = msg!( + "the type information given here is insufficient to check whether the pointer cast is valid" + ); diag.note(msg); } CastUnknownPointerSub::From(span) => { - let msg = msg!("the type information given here is insufficient to check whether the pointer cast is valid"); + let msg = msg!( + "the type information given here is insufficient to check whether the pointer cast is valid" + ); diag.span_label(span, msg); } } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 14f7b68387056..cc8229b3f387b 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -354,9 +354,8 @@ impl Subdiagnostic for IfLetRescopeRewrite { .chain(repeat_n('}', closing_brackets.count)) .collect(), )); - let msg = msg!( - "a `match` with a single arm can preserve the drop order up to Edition 2021" - ); + let msg = + msg!("a `match` with a single arm can preserve the drop order up to Edition 2021"); diag.multipart_suggestion_with_style( msg, suggestions, diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 823acfaa54093..26ed2799fd5cc 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1169,7 +1169,9 @@ impl Subdiagnostic for ConsiderBorrowingParamHelp { type_param_span .push_span_label(span, msg!("consider borrowing this type parameter in the trait")); } - let msg = msg!("the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`"); + let msg = msg!( + "the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`" + ); diag.span_help(type_param_span, msg); } } From 10eb844bac7551efc821a7f55b2e1715098ed26b Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 17:52:48 +0100 Subject: [PATCH 14/17] Remove `eagerly_format_to_string` from `DiagCtxt` --- compiler/rustc_builtin_macros/src/errors.rs | 7 +-- compiler/rustc_codegen_llvm/src/errors.rs | 6 ++- compiler/rustc_const_eval/src/errors.rs | 50 +++++++++---------- .../src/interpret/eval_context.rs | 6 +-- compiler/rustc_errors/src/lib.rs | 20 -------- compiler/rustc_resolve/src/errors.rs | 9 ++-- 6 files changed, 38 insertions(+), 60 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs index 89dd23dfe281b..39d210e14a098 100644 --- a/compiler/rustc_builtin_macros/src/errors.rs +++ b/compiler/rustc_builtin_macros/src/errors.rs @@ -949,17 +949,14 @@ pub(crate) struct AsmClobberNoReg { impl<'a, G: EmissionGuarantee> Diagnostic<'a, G> for AsmClobberNoReg { fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { - // eager translation as `span_labels` takes `AsRef` - let lbl1 = dcx.eagerly_format_to_string(msg!("clobber_abi"), [].into_iter()); - let lbl2 = dcx.eagerly_format_to_string(msg!("generic outputs"), [].into_iter()); Diag::new( dcx, level, msg!("asm with `clobber_abi` must specify explicit registers for outputs"), ) .with_span(self.spans.clone()) - .with_span_labels(self.clobbers, &lbl1) - .with_span_labels(self.spans, &lbl2) + .with_span_labels(self.clobbers, "clobber_abi") + .with_span_labels(self.spans, "generic outputs") } } diff --git a/compiler/rustc_codegen_llvm/src/errors.rs b/compiler/rustc_codegen_llvm/src/errors.rs index 89bfdfbd9e579..a7b5bdbf7bdff 100644 --- a/compiler/rustc_codegen_llvm/src/errors.rs +++ b/compiler/rustc_codegen_llvm/src/errors.rs @@ -2,7 +2,9 @@ use std::ffi::CString; use std::path::Path; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, msg}; +use rustc_errors::{ + Diag, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level, format_diag_message, msg, +}; use rustc_macros::Diagnostic; use rustc_span::Span; @@ -24,7 +26,7 @@ impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { let diag: Diag<'_, G> = self.0.into_diag(dcx, level); let (message, _) = diag.messages.first().expect("`LlvmError` with no message"); - let message = dcx.eagerly_format_to_string(message.clone(), diag.args.iter()); + let message = format_diag_message(message, &diag.args); Diag::new( dcx, level, diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index c05c6034d7215..950201cb6272c 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -6,8 +6,8 @@ use rustc_abi::WrappingRange; use rustc_errors::codes::*; use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ - Diag, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, - Subdiagnostic, msg, + Diag, DiagArgMap, DiagArgValue, DiagMessage, Diagnostic, EmissionGuarantee, Level, MultiSpan, + Subdiagnostic, format_diag_message, msg, }; use rustc_hir::ConstContext; use rustc_macros::{Diagnostic, Subdiagnostic}; @@ -623,7 +623,7 @@ pub trait ReportErrorExt { let mut diag = dcx.struct_allow(DiagMessage::Str(String::new().into())); let message = self.diagnostic_message(); self.add_args(&mut diag); - let s = dcx.eagerly_format_to_string(message, diag.args.iter()); + let s = format_diag_message(&message, &diag.args).into_owned(); diag.cancel(); s }) @@ -1085,12 +1085,12 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } let message = if let Some(path) = self.path { - err.dcx.eagerly_format_to_string( - msg!("constructing invalid value at {$path}"), - [("path".into(), DiagArgValue::Str(path.into()))].iter().map(|(a, b)| (a, b)), + format_diag_message( + &msg!("constructing invalid value at {$path}"), + &DiagArgMap::from_iter([("path".into(), DiagArgValue::Str(path.into()))]), ) } else { - err.dcx.eagerly_format_to_string(msg!("constructing invalid value"), [].into_iter()) + Cow::Borrowed("constructing invalid value") }; err.arg("front_matter", message); @@ -1116,12 +1116,13 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { msg!("in the range {$lo}..={$hi}") }; - let args = [ - ("lo".into(), DiagArgValue::Str(lo.to_string().into())), - ("hi".into(), DiagArgValue::Str(hi.to_string().into())), - ]; - let args = args.iter().map(|(a, b)| (a, b)); - let message = err.dcx.eagerly_format_to_string(msg, args); + let message = format_diag_message( + &msg, + &DiagArgMap::from_iter([ + ("lo".into(), DiagArgValue::Str(lo.to_string().into())), + ("hi".into(), DiagArgValue::Str(hi.to_string().into())), + ]), + ); err.arg("in_range", message); } @@ -1131,19 +1132,18 @@ impl<'tcx> ReportErrorExt for ValidationErrorInfo<'tcx> { } PointerAsInt { expected } | Uninit { expected } => { let msg = match expected { - ExpectedKind::Reference => msg!("expected a reference"), - ExpectedKind::Box => msg!("expected a box"), - ExpectedKind::RawPtr => msg!("expected a raw pointer"), - ExpectedKind::InitScalar => msg!("expected initialized scalar value"), - ExpectedKind::Bool => msg!("expected a boolean"), - ExpectedKind::Char => msg!("expected a unicode scalar value"), - ExpectedKind::Float => msg!("expected a floating point number"), - ExpectedKind::Int => msg!("expected an integer"), - ExpectedKind::FnPtr => msg!("expected a function pointer"), - ExpectedKind::EnumTag => msg!("expected a valid enum tag"), - ExpectedKind::Str => msg!("expected a string"), + ExpectedKind::Reference => "expected a reference", + ExpectedKind::Box => "expected a box", + ExpectedKind::RawPtr => "expected a raw pointer", + ExpectedKind::InitScalar => "expected initialized scalar value", + ExpectedKind::Bool => "expected a boolean", + ExpectedKind::Char => "expected a unicode scalar value", + ExpectedKind::Float => "expected a floating point number", + ExpectedKind::Int => "expected an integer", + ExpectedKind::FnPtr => "expected a function pointer", + ExpectedKind::EnumTag => "expected a valid enum tag", + ExpectedKind::Str => "expected a string", }; - let msg = err.dcx.eagerly_format_to_string(msg, [].into_iter()); err.arg("expected", msg); } InvalidEnumTag { value } diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 0878584c8769c..1653bbdaa36d7 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -1,7 +1,7 @@ use either::{Left, Right}; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout}; use rustc_data_structures::debug_assert_matches; -use rustc_errors::{DiagCtxtHandle, msg}; +use rustc_errors::{DiagCtxtHandle, format_diag_message, msg}; use rustc_hir::def_id::DefId; use rustc_hir::limit::Limit; use rustc_middle::mir::interpret::{ErrorHandled, InvalidMetaKind, ReportedErrorInfo}; @@ -235,9 +235,9 @@ pub fn format_interp_error<'tcx>(dcx: DiagCtxtHandle<'_>, e: InterpErrorInfo<'tc let mut diag = dcx.struct_allow(""); let msg = e.diagnostic_message(); e.add_args(&mut diag); - let s = dcx.eagerly_format_to_string(msg, diag.args.iter()); + let msg = format_diag_message(&msg, &diag.args).into_owned(); diag.cancel(); - s + msg } impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index dbc8884a9fbc9..e3c2d93aff1a8 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -483,16 +483,6 @@ impl DiagCtxt { self.inner.borrow_mut().emitter = emitter; } - /// Format `message` eagerly with `args` to `String`. - pub fn eagerly_format_to_string<'a>( - &self, - message: DiagMessage, - args: impl Iterator>, - ) -> String { - let inner = self.inner.borrow(); - inner.eagerly_format_to_string(message, args) - } - // This is here to not allow mutation of flags; // as of this writing it's used in Session::consider_optimizing and // in tests in rustc_interface. @@ -1408,16 +1398,6 @@ impl DiagCtxtInner { self.has_errors().or_else(|| self.delayed_bugs.get(0).map(|(_, guar)| guar).copied()) } - /// Format `message` eagerly with `args` to `String`. - fn eagerly_format_to_string<'a>( - &self, - message: DiagMessage, - args: impl Iterator>, - ) -> String { - let args = args.map(|(name, val)| (name.clone(), val.clone())).collect(); - format_diag_message(&message, &args).to_string() - } - fn flush_delayed(&mut self) { // Stashed diagnostics must be emitted before delayed bugs are flushed. // Otherwise, we might ICE prematurely when errors would have diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 54427535c5f6e..3a984d881c79d 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -1,4 +1,5 @@ use rustc_errors::codes::*; +use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, ElidedLifetimeInPathSubdiag, EmissionGuarantee, IntoDiagArg, Level, MultiSpan, Subdiagnostic, msg, @@ -1364,12 +1365,10 @@ impl Subdiagnostic for FoundItemConfigureOut { let mut multispan: MultiSpan = self.span.into(); match self.item_was { ItemWas::BehindFeature { feature, span } => { - let key = "feature".into(); let value = feature.into_diag_arg(&mut None); - let msg = diag.dcx.eagerly_format_to_string( - msg!("the item is gated behind the `{$feature}` feature"), - [(&key, &value)].into_iter(), - ); + let msg = msg!("the item is gated behind the `{$feature}` feature") + .arg("feature", value) + .format(); multispan.push_span_label(span, msg); } ItemWas::CfgOut { span } => { From e58ddb5ae575f13d5624cb6fb0a8324a806bc1c4 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 18:19:58 +0100 Subject: [PATCH 15/17] Fix `variable_references` logic to catch all variable references --- .../rustc_macros/src/diagnostics/message.rs | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index dfc5c7e800c65..11bf904c18e1b 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -64,26 +64,46 @@ fn verify_variables_used(msg_span: Span, message_str: &str, variant: Option<&Var fn variable_references<'a>(msg: &fluent_syntax::ast::Message<&'a str>) -> Vec<&'a str> { let mut refs = vec![]; + if let Some(Pattern { elements }) = &msg.value { for elt in elements { - if let PatternElement::Placeable { - expression: Expression::Inline(InlineExpression::VariableReference { id }), - } = elt - { - refs.push(id.name); - } + traverse_pattern(elt, &mut refs); } } for attr in &msg.attributes { for elt in &attr.value.elements { - if let PatternElement::Placeable { - expression: Expression::Inline(InlineExpression::VariableReference { id }), - } = elt - { - refs.push(id.name); + traverse_pattern(elt, &mut refs); + } + } + + fn traverse_pattern<'a>(elem: &PatternElement<&'a str>, refs: &mut Vec<&'a str>) { + match elem { + PatternElement::TextElement { .. } => {} + PatternElement::Placeable { expression } => traverse_expression(expression, refs), + } + } + fn traverse_expression<'a>(expr: &Expression<&'a str>, refs: &mut Vec<&'a str>) { + match expr { + Expression::Select { selector, variants } => { + traverse_inline_expr(selector, refs); + for variant in variants { + for pattern in &variant.value.elements { + traverse_pattern(pattern, refs); + } + } + } + Expression::Inline(expr) => { + traverse_inline_expr(expr, refs); } } } + fn traverse_inline_expr<'a>(elem: &InlineExpression<&'a str>, refs: &mut Vec<&'a str>) { + match elem { + InlineExpression::VariableReference { id } => refs.push(id.name), + _ => {} + } + } + refs } From 4e0b64408c4aee1066eefa6a80a56803a69467aa Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 6 Mar 2026 18:20:30 +0100 Subject: [PATCH 16/17] Fix newly detected subdiagnostics using variables from parent --- .../rustc_const_eval/src/check_consts/ops.rs | 5 +-- compiler/rustc_const_eval/src/errors.rs | 4 +-- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/lints.rs | 2 +- compiler/rustc_parse/src/errors.rs | 1 + compiler/rustc_parse/src/parser/expr.rs | 1 + compiler/rustc_resolve/src/diagnostics.rs | 2 ++ compiler/rustc_resolve/src/errors.rs | 1 + compiler/rustc_trait_selection/src/errors.rs | 32 ------------------- 9 files changed, 12 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 13e78259e2680..d64cf8e032935 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -265,6 +265,7 @@ fn build_error_for_const_call<'tcx>( } } CallKind::FnCall { fn_trait_id, self_ty } => { + let kind = ccx.const_kind(); let note = match self_ty.kind() { FnDef(def_id, ..) => { let span = tcx.def_span(*def_id); @@ -274,8 +275,8 @@ fn build_error_for_const_call<'tcx>( Some(errors::NonConstClosureNote::FnDef { span }) } - FnPtr(..) => Some(errors::NonConstClosureNote::FnPtr), - Closure(..) => Some(errors::NonConstClosureNote::Closure), + FnPtr(..) => Some(errors::NonConstClosureNote::FnPtr { kind }), + Closure(..) => Some(errors::NonConstClosureNote::Closure { kind }), _ => None, }; diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs index 950201cb6272c..07d001e9d847f 100644 --- a/compiler/rustc_const_eval/src/errors.rs +++ b/compiler/rustc_const_eval/src/errors.rs @@ -533,7 +533,7 @@ pub enum NonConstClosureNote { *[other] {""} }s"# )] - FnPtr, + FnPtr { kind: ConstContext }, #[note( r#"closures need an RFC before allowed to be called in {$kind -> [const] constant @@ -542,7 +542,7 @@ pub enum NonConstClosureNote { *[other] {""} }s"# )] - Closure, + Closure { kind: ConstContext }, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 85b881cddc2b8..54c8c75b88fcb 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2242,10 +2242,10 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { EXPLICIT_OUTLIVES_REQUIREMENTS, lint_spans.clone(), BuiltinExplicitOutlives { - count: bound_count, suggestion: BuiltinExplicitOutlivesSuggestion { spans: lint_spans, applicability, + count: bound_count, }, }, ); diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs index f3f6b099c60e9..d8b62e81b0cbc 100644 --- a/compiler/rustc_lint/src/lints.rs +++ b/compiler/rustc_lint/src/lints.rs @@ -493,7 +493,6 @@ pub(crate) struct BuiltinKeywordIdents { #[derive(Diagnostic)] #[diag("outlives requirements can be inferred")] pub(crate) struct BuiltinExplicitOutlives { - pub count: usize, #[subdiagnostic] pub suggestion: BuiltinExplicitOutlivesSuggestion, } @@ -510,6 +509,7 @@ pub(crate) struct BuiltinExplicitOutlivesSuggestion { pub spans: Vec, #[applicability] pub applicability: Applicability, + pub count: usize, } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs index c1ccb6a298315..f4f7182922050 100644 --- a/compiler/rustc_parse/src/errors.rs +++ b/compiler/rustc_parse/src/errors.rs @@ -1179,6 +1179,7 @@ pub(crate) enum MatchArmBodyWithoutBracesSugg { left: Span, #[suggestion_part(code = " }}")] right: Span, + num_statements: usize, }, #[suggestion( "replace `;` with `,` to end a `match` arm expression", diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index e6f73e41f0821..4297086983b40 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -3207,6 +3207,7 @@ impl<'a> Parser<'a> { errors::MatchArmBodyWithoutBracesSugg::AddBraces { left: span.shrink_to_lo(), right: span.shrink_to_hi(), + num_statements: stmts.len(), } } else { errors::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 6c7cc311da2a0..1b1198af41c0e 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -1,3 +1,4 @@ +// ignore-tidy-filelength use std::ops::ControlFlow; use itertools::Itertools as _; @@ -579,6 +580,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { errs::GenericParamsFromOuterItemInnerItem { span: *span, descr: kind.descr().to_string(), + is_self, } }), }; diff --git a/compiler/rustc_resolve/src/errors.rs b/compiler/rustc_resolve/src/errors.rs index 3a984d881c79d..63ffdbc37f7d1 100644 --- a/compiler/rustc_resolve/src/errors.rs +++ b/compiler/rustc_resolve/src/errors.rs @@ -52,6 +52,7 @@ pub(crate) struct GenericParamsFromOuterItemInnerItem { #[primary_span] pub(crate) span: Span, pub(crate) descr: String, + pub(crate) is_self: bool, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 26ed2799fd5cc..6f63c1d663f13 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -1227,38 +1227,6 @@ impl Subdiagnostic for DynTraitConstraintSuggestion { } } -#[derive(Diagnostic)] -#[diag("{$has_param_name -> - [true] `{$param_name}` - *[false] `fn` parameter -} has {$lifetime_kind -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` -} but calling `{$assoc_item}` introduces an implicit `'static` lifetime requirement", code = E0772)] -pub struct ButCallingIntroduces { - #[label( - "{$has_lifetime -> - [true] lifetime `{$lifetime}` - *[false] an anonymous lifetime `'_` - }" - )] - pub param_ty_span: Span, - #[primary_span] - #[label("...is used and required to live as long as `'static` here because of an implicit lifetime bound on the {$has_impl_path -> - [true] `impl` of `{$impl_path}` - *[false] inherent `impl` - }")] - pub cause_span: Span, - - pub has_param_name: bool, - pub param_name: String, - pub has_lifetime: bool, - pub lifetime: String, - pub assoc_item: Symbol, - pub has_impl_path: bool, - pub impl_path: String, -} - pub struct ReqIntroducedLocations { pub span: MultiSpan, pub spans: Vec, From 7baf2be12a95fc489c3fc4111baeedbf867b0f46 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Sat, 7 Mar 2026 01:23:58 +0100 Subject: [PATCH 17/17] Fix uitests --- .../diagnostic-derive-doc-comment-field.stderr | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr index 2d90b2a96b015..9149baaa40871 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr @@ -35,12 +35,6 @@ help: the nightly-only, unstable trait `IntoDiagArg` is not implemented for `Not LL | struct NotIntoDiagArg; | ^^^^^^^^^^^^^^^^^^^^^ = help: normalized in stderr -note: required by a bound in `Diag::<'a, G>::arg` - --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC - ::: $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC - | - = note: in this macro invocation - = note: this error originates in the macro `with_fn` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors