From b82f09a48d45dd8cbb8a313d26a94858766f0001 Mon Sep 17 00:00:00 2001 From: Sanidhya Singh Date: Wed, 3 Jun 2026 12:09:35 +0530 Subject: [PATCH 1/8] Document error conditions for Command::{spawn, output, status} These methods return `io::Result` but did not document why they can fail or, importantly, that a child terminated by a signal is reported through its `ExitStatus` rather than as an `Err`. Add `# Errors` sections describing the common reasons spawning a child can fail (program not found, missing permission, resource exhaustion) and clarifying that a running child which exits unsuccessfully or is killed by a signal is not an error: those methods still return `Ok` and the outcome is reflected in the resulting `ExitStatus`. --- library/std/src/process.rs | 47 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/library/std/src/process.rs b/library/std/src/process.rs index 0b8db439a6370..990cb0eb8c7e4 100644 --- a/library/std/src/process.rs +++ b/library/std/src/process.rs @@ -1070,6 +1070,26 @@ impl Command { /// /// By default, stdin, stdout and stderr are inherited from the parent. /// + /// # Errors + /// + /// This method returns an [`io::Error`] if the child process could not be + /// spawned. Common reasons include: + /// + /// * the program could not be found (for example, it does not exist, or, + /// when given a bare name, it is not present in the `PATH`); + /// * the current process does not have permission to execute the program + /// (for example, the file is not marked executable, or execution is + /// denied by a security policy such as `seccomp`); + /// * the operating system could not create the new process because of + /// resource exhaustion (for example, a limit on the number of processes + /// was reached). + /// + /// An error is only returned for failures that occur while the child is + /// being spawned. Once the child has started successfully, anything that + /// happens to it afterwards — including being terminated by a signal — is + /// reported through its [`ExitStatus`] rather than as an error from the + /// spawning method. + /// /// # Examples /// /// ```no_run @@ -1092,6 +1112,20 @@ impl Command { /// attempt by the child process to read from the stdin stream will result /// in the stream immediately closing. /// + /// # Errors + /// + /// Like [`spawn`], this method returns an [`io::Error`] if the child + /// process could not be spawned; see [`spawn`] for the common reasons. It + /// may also return an error if reading the child's output or waiting on the + /// child fails. + /// + /// Note that this method does **not** return an error if the child runs and + /// then exits unsuccessfully, or is terminated by a signal. In those cases + /// it still returns [`Ok`], and the outcome is reflected in the + /// [`ExitStatus`] stored in the returned [`Output`]. + /// + /// [`spawn`]: Command::spawn + /// /// # Examples /// /// ```should_panic @@ -1119,6 +1153,19 @@ impl Command { /// /// By default, stdin, stdout and stderr are inherited from the parent. /// + /// # Errors + /// + /// Like [`spawn`], this method returns an [`io::Error`] if the child + /// process could not be spawned; see [`spawn`] for the common reasons. It + /// may also return an error if waiting on the child fails. + /// + /// Note that this method does **not** return an error if the child runs and + /// then exits unsuccessfully, or is terminated by a signal. In those cases + /// it still returns [`Ok`], and the outcome is reflected in the returned + /// [`ExitStatus`]. + /// + /// [`spawn`]: Command::spawn + /// /// # Examples /// /// ```should_panic From bdb15892919043d7171c3f7619640007f7eac635 Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Sat, 30 May 2026 09:31:44 +0800 Subject: [PATCH 2/8] fix armv7a-none-eabihf tier doc --- src/doc/rustc/src/platform-support/arm-none-eabi.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc/src/platform-support/arm-none-eabi.md b/src/doc/rustc/src/platform-support/arm-none-eabi.md index 5d22cef92d220..4a6c4783f6d7b 100644 --- a/src/doc/rustc/src/platform-support/arm-none-eabi.md +++ b/src/doc/rustc/src/platform-support/arm-none-eabi.md @@ -12,7 +12,7 @@ their own document. ### Tier 2 Target List - Arm A-Profile Architectures - - [`armv7a-none-eabi`](armv7a-none-eabi.md) + - [`armv7a-none-eabi` and `armv7a-none-eabihf`](armv7a-none-eabi.md) - [`thumbv7a-none-eabi` and `thumbv7a-none-eabihf`](armv7a-none-eabi.md) - Arm R-Profile Architectures - [`armv7r-none-eabi` and `armv7r-none-eabihf`](armv7r-none-eabi.md) @@ -32,7 +32,7 @@ their own document. ### Tier 3 Target List - Arm A-Profile Architectures - - [`armv7a-none-eabihf`](armv7a-none-eabi.md) + - None - Arm R-Profile Architectures - None - Arm M-Profile Architectures From 3bdd720f57ae5a1e60f36ddc3bad5b99d9db8dc8 Mon Sep 17 00:00:00 2001 From: Kjetil Kjeka Date: Thu, 4 Jun 2026 10:27:46 +0200 Subject: [PATCH 3/8] NVPTX: Add @kulst to the target maintainers --- src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md index 02510d9f3dee2..5c74e7b95d9ab 100644 --- a/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md +++ b/src/doc/rustc/src/platform-support/nvptx64-nvidia-cuda.md @@ -8,6 +8,7 @@ platform. ## Target maintainers [@kjetilkjeka](https://github.com/kjetilkjeka) +[@kulst](https://github.com/kulst) ## Requirements From 7ed4c9df4a7598b0fb4d0cf4a2216406ef985ae9 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 4 Jun 2026 21:39:52 +0200 Subject: [PATCH 4/8] Make distinction between crate-level attributes that are warned vs errored --- .../src/attributes/crate_level.rs | 60 ++++++++++++------- .../src/attributes/link_attrs.rs | 6 +- .../src/attributes/rustc_dump.rs | 6 +- .../src/attributes/rustc_internal.rs | 3 +- .../src/attributes/stability.rs | 3 +- .../src/attributes/test_attrs.rs | 6 +- compiler/rustc_attr_parsing/src/errors.rs | 1 + .../rustc_attr_parsing/src/target_checking.rs | 35 ++++++----- 8 files changed, 77 insertions(+), 43 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index d6d9b761a1e76..4ae66c1f56fc9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -13,7 +13,8 @@ impl SingleAttributeParser for CrateNameParser { const PATH: &[Symbol] = &[sym::crate_name]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -31,7 +32,8 @@ impl CombineAttributeParser for CrateTypeParser { const PATH: &[Symbol] = &[sym::crate_type]; type Item = CrateType; const CONVERT: ConvertFn = |items, _| AttributeKind::CrateType(items); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "crate type", "https://doc.rust-lang.org/reference/linkage.html"); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -74,7 +76,8 @@ impl SingleAttributeParser for RecursionLimitParser { const PATH: &[Symbol] = &[sym::recursion_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -89,7 +92,8 @@ pub(crate) struct MoveSizeLimitParser; impl SingleAttributeParser for MoveSizeLimitParser { const PATH: &[Symbol] = &[sym::move_size_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(large_assignments); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -105,7 +109,8 @@ impl SingleAttributeParser for TypeLengthLimitParser { const PATH: &[Symbol] = &[sym::type_length_limit]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -120,7 +125,8 @@ pub(crate) struct PatternComplexityLimitParser; impl SingleAttributeParser for PatternComplexityLimitParser { const PATH: &[Symbol] = &[sym::pattern_complexity_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!( rustc_attrs, "the `#[pattern_complexity_limit]` attribute is used for rustc unit tests" @@ -137,7 +143,8 @@ pub(crate) struct NoCoreParser; impl NoArgsAttributeParser for NoCoreParser { const PATH: &[Symbol] = &[sym::no_core]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(no_core); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoCore; } @@ -147,7 +154,8 @@ pub(crate) struct NoStdParser; impl NoArgsAttributeParser for NoStdParser { const PATH: &[Symbol] = &[sym::no_std]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoStd; } @@ -157,7 +165,8 @@ pub(crate) struct NoMainParser; impl NoArgsAttributeParser for NoMainParser { const PATH: &[Symbol] = &[sym::no_main]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoMain; } @@ -166,7 +175,8 @@ pub(crate) struct RustcCoherenceIsCoreParser; impl NoArgsAttributeParser for RustcCoherenceIsCoreParser { const PATH: &[Symbol] = &[sym::rustc_coherence_is_core]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoherenceIsCore; } @@ -176,7 +186,8 @@ pub(crate) struct WindowsSubsystemParser; impl SingleAttributeParser for WindowsSubsystemParser { const PATH: &[Symbol] = &[sym::windows_subsystem]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute"); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -203,7 +214,8 @@ pub(crate) struct PanicRuntimeParser; impl NoArgsAttributeParser for PanicRuntimeParser { const PATH: &[Symbol] = &[sym::panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime; } @@ -212,7 +224,8 @@ pub(crate) struct NeedsPanicRuntimeParser; impl NoArgsAttributeParser for NeedsPanicRuntimeParser { const PATH: &[Symbol] = &[sym::needs_panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(needs_panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; } @@ -221,7 +234,8 @@ pub(crate) struct ProfilerRuntimeParser; impl NoArgsAttributeParser for ProfilerRuntimeParser { const PATH: &[Symbol] = &[sym::profiler_runtime]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(profiler_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; } @@ -231,7 +245,8 @@ pub(crate) struct NoBuiltinsParser; impl NoArgsAttributeParser for NoBuiltinsParser { const PATH: &[Symbol] = &[sym::no_builtins]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoBuiltins; } @@ -240,7 +255,8 @@ pub(crate) struct RustcPreserveUbChecksParser; impl NoArgsAttributeParser for RustcPreserveUbChecksParser { const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; } @@ -249,7 +265,8 @@ pub(crate) struct RustcNoImplicitBoundsParser; impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; } @@ -258,7 +275,8 @@ pub(crate) struct DefaultLibAllocatorParser; impl NoArgsAttributeParser for DefaultLibAllocatorParser { const PATH: &[Symbol] = &[sym::default_lib_allocator]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator; } @@ -269,7 +287,8 @@ impl CombineAttributeParser for FeatureParser { const PATH: &[Symbol] = &[sym::feature]; type Item = Ident; const CONVERT: ConvertFn = AttributeKind::Feature; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["feature1, feature2, ..."]); const STABILITY: AttributeStability = AttributeStability::Stable; @@ -314,7 +333,8 @@ impl CombineAttributeParser for RegisterToolParser { const PATH: &[Symbol] = &[sym::register_tool]; type Item = Ident; const CONVERT: ConvertFn = |tools, _span| AttributeKind::RegisterTool(tools); - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]); const STABILITY: AttributeStability = unstable!(register_tool); diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index bc500ddd48acf..0fb63a8cb5722 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -688,7 +688,8 @@ pub(crate) struct NeedsAllocatorParser; impl NoArgsAttributeParser for NeedsAllocatorParser { const PATH: &[Symbol] = &[sym::needs_allocator]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; } @@ -697,7 +698,8 @@ pub(crate) struct CompilerBuiltinsParser; impl NoArgsAttributeParser for CompilerBuiltinsParser { const PATH: &[Symbol] = &[sym::compiler_builtins]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(compiler_builtins); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CompilerBuiltins; } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index a80a46e90ac0c..7d4c93b5b7020 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -49,7 +49,8 @@ pub(crate) struct RustcDumpHiddenTypeOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpHiddenTypeOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_hidden_type_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpHiddenTypeOfOpaques; } @@ -242,7 +243,8 @@ pub(crate) struct RustcDumpVariancesOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpVariancesOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques; } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 6e1060ea05ae9..95397c7118552 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -370,7 +370,8 @@ pub(crate) struct RustcNeverTypeOptionsParser; impl SingleAttributeParser for RustcNeverTypeOptionsParser { const PATH: &[Symbol] = &[sym::rustc_never_type_options]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[ r#"fallback = "unit", "never", "no""#, r#"diverging_block_default = "unit", "never""#, diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index b38bb6d535770..3d3a5e7f1816b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -460,7 +460,8 @@ pub(crate) struct UnstableRemovedParser; impl CombineAttributeParser for UnstableRemovedParser { type Item = UnstableRemovedFeature; const PATH: &[Symbol] = &[sym::unstable_removed]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[r#"feature = "name", reason = "...", link = "...", since = "version""#]); const STABILITY: AttributeStability = unstable!(staged_api); diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 00e113f171715..70a2aac26aee5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -83,7 +83,8 @@ pub(crate) struct ReexportTestHarnessMainParser; impl SingleAttributeParser for ReexportTestHarnessMainParser { const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); @@ -174,7 +175,8 @@ pub(crate) struct TestRunnerParser; impl SingleAttributeParser for TestRunnerParser { const PATH: &[Symbol] = &[sym::test_runner]; - const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = + AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["path"]); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index 5f898295d5afa..0a03e82754f00 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -148,6 +148,7 @@ pub(crate) struct InvalidAttrStyle { pub crate_root_path: String, #[help("the crate root is at `{$crate_root_path}`")] pub show_crate_root_help: bool, + pub span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_attr_parsing/src/target_checking.rs b/compiler/rustc_attr_parsing/src/target_checking.rs index 483a3d6a1329b..87b0eb9504e0e 100644 --- a/compiler/rustc_attr_parsing/src/target_checking.rs +++ b/compiler/rustc_attr_parsing/src/target_checking.rs @@ -114,7 +114,11 @@ impl<'sess> AttributeParser<'sess> { // For crate-level attributes we emit a specific set of lints to warn // people about accidentally not using them on the crate. if let &AllowedTargets::AllowList(&[Allow(Target::Crate)]) = allowed_targets { - Self::check_crate_level(cx); + Self::check_crate_level(cx, false); + return; + } + if let &AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]) = allowed_targets { + Self::check_crate_level(cx, true); return; } @@ -181,7 +185,7 @@ impl<'sess> AttributeParser<'sess> { } } - pub(crate) fn check_crate_level(cx: &mut AcceptContext<'_, 'sess>) { + pub(crate) fn check_crate_level(cx: &mut AcceptContext<'_, 'sess>, warn: bool) { if cx.target == Target::Crate { return; } @@ -205,19 +209,20 @@ impl<'sess> AttributeParser<'sess> { }) .unwrap_or_default(); - let target = cx.target; - cx.emit_lint( - rustc_session::lint::builtin::UNUSED_ATTRIBUTES, - crate::errors::InvalidAttrStyle { - name, - is_used_as_inner, - target_span: (!is_used_as_inner).then_some(target_span), - target: target.name(), - crate_root_path, - show_crate_root_help, - }, - attr_span, - ); + let diag = crate::errors::InvalidAttrStyle { + name, + is_used_as_inner, + target_span: (!is_used_as_inner).then_some(target_span), + target: cx.target.name(), + crate_root_path, + show_crate_root_help, + span: attr_span, + }; + if warn { + cx.emit_lint(rustc_session::lint::builtin::UNUSED_ATTRIBUTES, diag, attr_span); + } else { + cx.emit_err(diag); + } } // FIXME: Fix "Cannot determine resolution" error and remove built-in macros From 73c631d5ae6a753f70a88612b61daa7ff8ff2fdb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Thu, 4 Jun 2026 21:52:07 +0200 Subject: [PATCH 5/8] Make all unstable crate-level attributes on incorrect targets an error --- .../src/attributes/crate_level.rs | 33 +++++++------------ .../src/attributes/link_attrs.rs | 6 ++-- .../src/attributes/rustc_dump.rs | 6 ++-- .../src/attributes/rustc_internal.rs | 3 +- .../src/attributes/stability.rs | 3 +- .../src/attributes/test_attrs.rs | 6 ++-- compiler/rustc_attr_parsing/src/errors.rs | 1 + tests/ui/attributes/attr-on-mac-call.rs | 2 +- tests/ui/attributes/attr-on-mac-call.stderr | 26 +++++++-------- tests/ui/attributes/malformed-no-std.stderr | 24 +++++++------- tests/ui/attributes/register-tool-target.rs | 3 +- .../ui/attributes/register-tool-target.stderr | 9 +++-- 12 files changed, 51 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs index 4ae66c1f56fc9..502b2740d21be 100644 --- a/compiler/rustc_attr_parsing/src/attributes/crate_level.rs +++ b/compiler/rustc_attr_parsing/src/attributes/crate_level.rs @@ -92,8 +92,7 @@ pub(crate) struct MoveSizeLimitParser; impl SingleAttributeParser for MoveSizeLimitParser { const PATH: &[Symbol] = &[sym::move_size_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(large_assignments); fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option { @@ -125,8 +124,7 @@ pub(crate) struct PatternComplexityLimitParser; impl SingleAttributeParser for PatternComplexityLimitParser { const PATH: &[Symbol] = &[sym::pattern_complexity_limit]; const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N"); - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!( rustc_attrs, "the `#[pattern_complexity_limit]` attribute is used for rustc unit tests" @@ -143,8 +141,7 @@ pub(crate) struct NoCoreParser; impl NoArgsAttributeParser for NoCoreParser { const PATH: &[Symbol] = &[sym::no_core]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(no_core); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NoCore; } @@ -175,8 +172,7 @@ pub(crate) struct RustcCoherenceIsCoreParser; impl NoArgsAttributeParser for RustcCoherenceIsCoreParser { const PATH: &[Symbol] = &[sym::rustc_coherence_is_core]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCoherenceIsCore; } @@ -214,8 +210,7 @@ pub(crate) struct PanicRuntimeParser; impl NoArgsAttributeParser for PanicRuntimeParser { const PATH: &[Symbol] = &[sym::panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PanicRuntime; } @@ -224,8 +219,7 @@ pub(crate) struct NeedsPanicRuntimeParser; impl NoArgsAttributeParser for NeedsPanicRuntimeParser { const PATH: &[Symbol] = &[sym::needs_panic_runtime]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(needs_panic_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsPanicRuntime; } @@ -234,8 +228,7 @@ pub(crate) struct ProfilerRuntimeParser; impl NoArgsAttributeParser for ProfilerRuntimeParser { const PATH: &[Symbol] = &[sym::profiler_runtime]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(profiler_runtime); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::ProfilerRuntime; } @@ -255,8 +248,7 @@ pub(crate) struct RustcPreserveUbChecksParser; impl NoArgsAttributeParser for RustcPreserveUbChecksParser { const PATH: &[Symbol] = &[sym::rustc_preserve_ub_checks]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPreserveUbChecks; } @@ -265,8 +257,7 @@ pub(crate) struct RustcNoImplicitBoundsParser; impl NoArgsAttributeParser for RustcNoImplicitBoundsParser { const PATH: &[Symbol] = &[sym::rustc_no_implicit_bounds]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitBounds; } @@ -275,8 +266,7 @@ pub(crate) struct DefaultLibAllocatorParser; impl NoArgsAttributeParser for DefaultLibAllocatorParser { const PATH: &[Symbol] = &[sym::default_lib_allocator]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::DefaultLibAllocator; } @@ -333,8 +323,7 @@ impl CombineAttributeParser for RegisterToolParser { const PATH: &[Symbol] = &[sym::register_tool]; type Item = Ident; const CONVERT: ConvertFn = |tools, _span| AttributeKind::RegisterTool(tools); - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["tool1, tool2, ..."]); const STABILITY: AttributeStability = unstable!(register_tool); diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 0fb63a8cb5722..bc500ddd48acf 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -688,8 +688,7 @@ pub(crate) struct NeedsAllocatorParser; impl NoArgsAttributeParser for NeedsAllocatorParser { const PATH: &[Symbol] = &[sym::needs_allocator]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(allocator_internals); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::NeedsAllocator; } @@ -698,8 +697,7 @@ pub(crate) struct CompilerBuiltinsParser; impl NoArgsAttributeParser for CompilerBuiltinsParser { const PATH: &[Symbol] = &[sym::compiler_builtins]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(compiler_builtins); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CompilerBuiltins; } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs index 7d4c93b5b7020..a80a46e90ac0c 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_dump.rs @@ -49,8 +49,7 @@ pub(crate) struct RustcDumpHiddenTypeOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpHiddenTypeOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_hidden_type_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpHiddenTypeOfOpaques; } @@ -243,8 +242,7 @@ pub(crate) struct RustcDumpVariancesOfOpaquesParser; impl NoArgsAttributeParser for RustcDumpVariancesOfOpaquesParser { const PATH: &[Symbol] = &[sym::rustc_dump_variances_of_opaques]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDumpVariancesOfOpaques; } diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 95397c7118552..6e1060ea05ae9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -370,8 +370,7 @@ pub(crate) struct RustcNeverTypeOptionsParser; impl SingleAttributeParser for RustcNeverTypeOptionsParser { const PATH: &[Symbol] = &[sym::rustc_never_type_options]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[ r#"fallback = "unit", "never", "no""#, r#"diverging_block_default = "unit", "never""#, diff --git a/compiler/rustc_attr_parsing/src/attributes/stability.rs b/compiler/rustc_attr_parsing/src/attributes/stability.rs index 3d3a5e7f1816b..b38bb6d535770 100644 --- a/compiler/rustc_attr_parsing/src/attributes/stability.rs +++ b/compiler/rustc_attr_parsing/src/attributes/stability.rs @@ -460,8 +460,7 @@ pub(crate) struct UnstableRemovedParser; impl CombineAttributeParser for UnstableRemovedParser { type Item = UnstableRemovedFeature; const PATH: &[Symbol] = &[sym::unstable_removed]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &[r#"feature = "name", reason = "...", link = "...", since = "version""#]); const STABILITY: AttributeStability = unstable!(staged_api); diff --git a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs index 70a2aac26aee5..00e113f171715 100644 --- a/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/test_attrs.rs @@ -83,8 +83,7 @@ pub(crate) struct ReexportTestHarnessMainParser; impl SingleAttributeParser for ReexportTestHarnessMainParser { const PATH: &[Symbol] = &[sym::reexport_test_harness_main]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name"); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); @@ -175,8 +174,7 @@ pub(crate) struct TestRunnerParser; impl SingleAttributeParser for TestRunnerParser { const PATH: &[Symbol] = &[sym::test_runner]; - const ALLOWED_TARGETS: AllowedTargets = - AllowedTargets::AllowListWarnRest(&[Allow(Target::Crate)]); + const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]); const TEMPLATE: AttributeTemplate = template!(List: &["path"]); const STABILITY: AttributeStability = unstable!(custom_test_frameworks); diff --git a/compiler/rustc_attr_parsing/src/errors.rs b/compiler/rustc_attr_parsing/src/errors.rs index 0a03e82754f00..ae5dc7b0d4dc2 100644 --- a/compiler/rustc_attr_parsing/src/errors.rs +++ b/compiler/rustc_attr_parsing/src/errors.rs @@ -148,6 +148,7 @@ pub(crate) struct InvalidAttrStyle { pub crate_root_path: String, #[help("the crate root is at `{$crate_root_path}`")] pub show_crate_root_help: bool, + #[primary_span] pub span: Span, } diff --git a/tests/ui/attributes/attr-on-mac-call.rs b/tests/ui/attributes/attr-on-mac-call.rs index 2875ff0c74e6d..1fdc2a6ed3562 100644 --- a/tests/ui/attributes/attr-on-mac-call.rs +++ b/tests/ui/attributes/attr-on-mac-call.rs @@ -108,6 +108,6 @@ fn main() { //~| WARN previously accepted unreachable!(); #[register_tool(xyz)] - //~^ WARN crate-level attribute should be an inner attribute + //~^ ERROR crate-level attribute should be an inner attribute unreachable!(); } diff --git a/tests/ui/attributes/attr-on-mac-call.stderr b/tests/ui/attributes/attr-on-mac-call.stderr index 8d19137da4457..9c042b301241a 100644 --- a/tests/ui/attributes/attr-on-mac-call.stderr +++ b/tests/ui/attributes/attr-on-mac-call.stderr @@ -6,6 +6,18 @@ LL | #[sanitize(address = "off")] | = help: `#[sanitize]` can be applied to crates, functions, impl blocks, modules, and statics +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![register_tool]` + --> $DIR/attr-on-mac-call.rs:110:5 + | +LL | #[register_tool(xyz)] + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this macro call + --> $DIR/attr-on-mac-call.rs:112:5 + | +LL | unreachable!(); + | ^^^^^^^^^^^^^^ + warning: `#[export_name]` attribute cannot be used on macro calls --> $DIR/attr-on-mac-call.rs:8:5 | @@ -289,17 +301,5 @@ LL | #[repr(simd)] = help: `#[repr(simd)]` can only be applied to structs = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![register_tool]` - --> $DIR/attr-on-mac-call.rs:110:5 - | -LL | #[register_tool(xyz)] - | ^^^^^^^^^^^^^^^^^^^^^ - | -note: this attribute does not have an `!`, which means it is applied to this macro call - --> $DIR/attr-on-mac-call.rs:112:5 - | -LL | unreachable!(); - | ^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error; 32 warnings emitted +error: aborting due to 2 previous errors; 31 warnings emitted diff --git a/tests/ui/attributes/malformed-no-std.stderr b/tests/ui/attributes/malformed-no-std.stderr index 07963e6256648..a965b7e235b36 100644 --- a/tests/ui/attributes/malformed-no-std.stderr +++ b/tests/ui/attributes/malformed-no-std.stderr @@ -106,6 +106,18 @@ note: attribute also specified here LL | #![no_core = "foo"] | ^^^^^^^^^^^^^^^^^^^ +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_core]` + --> $DIR/malformed-no-std.rs:23:1 + | +LL | #[no_core] + | ^^^^^^^^^^ + | +note: this attribute does not have an `!`, which means it is applied to this extern crate + --> $DIR/malformed-no-std.rs:26:1 + | +LL | extern crate core; + | ^^^^^^^^^^^^^^^^^^ + error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_std]` --> $DIR/malformed-no-std.rs:21:1 | @@ -123,18 +135,6 @@ note: the lint level is defined here LL | #[deny(unused_attributes)] | ^^^^^^^^^^^^^^^^^ -error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![no_core]` - --> $DIR/malformed-no-std.rs:23:1 - | -LL | #[no_core] - | ^^^^^^^^^^ - | -note: this attribute does not have an `!`, which means it is applied to this extern crate - --> $DIR/malformed-no-std.rs:26:1 - | -LL | extern crate core; - | ^^^^^^^^^^^^^^^^^^ - warning: unused attribute --> $DIR/malformed-no-std.rs:5:1 | diff --git a/tests/ui/attributes/register-tool-target.rs b/tests/ui/attributes/register-tool-target.rs index a92b946c95f2d..8498e7fa0f15c 100644 --- a/tests/ui/attributes/register-tool-target.rs +++ b/tests/ui/attributes/register-tool-target.rs @@ -1,8 +1,7 @@ -//@ check-pass #![feature(register_tool)] #[register_tool(no_valid_target)] -//~^ WARN crate-level attribute should be an inner attribute +//~^ ERROR crate-level attribute should be an inner attribute fn main() { } diff --git a/tests/ui/attributes/register-tool-target.stderr b/tests/ui/attributes/register-tool-target.stderr index 4808ee49ee6a4..bf865c29c9965 100644 --- a/tests/ui/attributes/register-tool-target.stderr +++ b/tests/ui/attributes/register-tool-target.stderr @@ -1,17 +1,16 @@ -warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![register_tool]` - --> $DIR/register-tool-target.rs:4:1 +error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![register_tool]` + --> $DIR/register-tool-target.rs:3:1 | LL | #[register_tool(no_valid_target)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: this attribute does not have an `!`, which means it is applied to this function - --> $DIR/register-tool-target.rs:6:1 + --> $DIR/register-tool-target.rs:5:1 | LL | / fn main() { LL | | LL | | } | |_^ - = note: requested on the command line with `-W unused-attributes` -warning: 1 warning emitted +error: aborting due to 1 previous error From f4b269dc744227db286b2feac92ea2d2f0f23cd2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 4 Jun 2026 21:04:53 +0200 Subject: [PATCH 6/8] Create non-exhaustive `proc_macro::EscapeError` enum mirrorring rustc-literal-escaper's --- library/proc_macro/src/lib.rs | 148 +++++++++++++++++++++++++++++++--- 1 file changed, 137 insertions(+), 11 deletions(-) diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index a01bf38a62dbf..7b21896cc4cae 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -44,6 +44,7 @@ mod diagnostic; mod escape; mod to_tokens; +use core::convert::From; use core::ops::BitOr; use std::ffi::CStr; use std::ops::{Range, RangeBounds}; @@ -53,8 +54,6 @@ use std::{error, fmt}; #[unstable(feature = "proc_macro_diagnostic", issue = "54140")] pub use diagnostic::{Diagnostic, Level, MultiSpan}; -#[unstable(feature = "proc_macro_value", issue = "136652")] -pub use rustc_literal_escaper::EscapeError; use rustc_literal_escaper::{ MixedUnit, unescape_byte, unescape_byte_str, unescape_c_str, unescape_char, unescape_str, }; @@ -64,6 +63,135 @@ pub use to_tokens::ToTokens; use crate::bridge::client::Methods as BridgeMethods; use crate::escape::{EscapeOptions, escape_bytes}; +/// Mostly relating to malformed escape sequences, but also a few other problems. +#[unstable(feature = "proc_macro_value", issue = "136652")] +#[derive(Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum EscapeError { + /// Expected 1 char, but 0 were found. + ZeroChars, + /// Expected 1 char, but more than 1 were found. + MoreThanOneChar, + + /// Escaped '\' character without continuation. + LoneSlash, + /// Invalid escape character (e.g. '\z'). + InvalidEscape, + /// Raw '\r' encountered. + BareCarriageReturn, + /// Raw '\r' encountered in raw string. + BareCarriageReturnInRawString, + /// Unescaped character that was expected to be escaped (e.g. raw '\t'). + EscapeOnlyChar, + + /// Numeric character escape is too short (e.g. '\x1'). + TooShortHexEscape, + /// Invalid character in numeric escape (e.g. '\xz') + InvalidCharInHexEscape, + /// Character code in numeric escape is non-ascii (e.g. '\xFF'). + OutOfRangeHexEscape, + + /// '\u' not followed by '{'. + NoBraceInUnicodeEscape, + /// Non-hexadecimal value in '\u{..}'. + InvalidCharInUnicodeEscape, + /// '\u{}' + EmptyUnicodeEscape, + /// No closing brace in '\u{..}', e.g. '\u{12'. + UnclosedUnicodeEscape, + /// '\u{_12}' + LeadingUnderscoreUnicodeEscape, + /// More than 6 characters in '\u{..}', e.g. '\u{10FFFF_FF}' + OverlongUnicodeEscape, + /// Invalid in-bound unicode character code, e.g. '\u{DFFF}'. + LoneSurrogateUnicodeEscape, + /// Out of bounds unicode character code, e.g. '\u{FFFFFF}'. + OutOfRangeUnicodeEscape, + + /// Unicode escape code in byte literal. + UnicodeEscapeInByte, + /// Non-ascii character in byte literal, byte string literal, or raw byte string literal. + NonAsciiCharInByte, + + /// `\0` in a C string literal. + NulInCStr, + + /// After a line ending with '\', the next line contains whitespace + /// characters that are not skipped. + UnskippedWhitespaceWarning, + + /// After a line ending with '\', multiple lines are skipped. + MultipleSkippedLinesWarning, +} + +#[unstable(feature = "proc_macro_value", issue = "136652")] +#[doc(hidden)] +impl From for EscapeError { + fn from(value: rustc_literal_escaper::EscapeError) -> Self { + use rustc_literal_escaper::EscapeError as EE; + + match value { + EE::ZeroChars => Self::ZeroChars, + EE::MoreThanOneChar => Self::MoreThanOneChar, + EE::LoneSlash => Self::LoneSlash, + EE::InvalidEscape => Self::InvalidEscape, + EE::BareCarriageReturn => Self::BareCarriageReturn, + EE::BareCarriageReturnInRawString => Self::BareCarriageReturnInRawString, + EE::EscapeOnlyChar => Self::EscapeOnlyChar, + EE::TooShortHexEscape => Self::TooShortHexEscape, + EE::InvalidCharInHexEscape => Self::InvalidCharInHexEscape, + EE::OutOfRangeHexEscape => Self::OutOfRangeHexEscape, + EE::NoBraceInUnicodeEscape => Self::NoBraceInUnicodeEscape, + EE::InvalidCharInUnicodeEscape => Self::InvalidCharInUnicodeEscape, + EE::EmptyUnicodeEscape => Self::EmptyUnicodeEscape, + EE::UnclosedUnicodeEscape => Self::UnclosedUnicodeEscape, + EE::LeadingUnderscoreUnicodeEscape => Self::LeadingUnderscoreUnicodeEscape, + EE::OverlongUnicodeEscape => Self::OverlongUnicodeEscape, + EE::LoneSurrogateUnicodeEscape => Self::LoneSurrogateUnicodeEscape, + EE::OutOfRangeUnicodeEscape => Self::OutOfRangeUnicodeEscape, + EE::UnicodeEscapeInByte => Self::UnicodeEscapeInByte, + EE::NonAsciiCharInByte => Self::NonAsciiCharInByte, + EE::NulInCStr => Self::NulInCStr, + EE::UnskippedWhitespaceWarning => Self::UnskippedWhitespaceWarning, + EE::MultipleSkippedLinesWarning => Self::MultipleSkippedLinesWarning, + } + } +} + +#[unstable(feature = "proc_macro_value", issue = "136652")] +impl error::Error for EscapeError {} + +#[unstable(feature = "proc_macro_value", issue = "136652")] +impl fmt::Display for EscapeError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(match self { + Self::ZeroChars => "zero chars", + Self::MoreThanOneChar => "more than one char", + Self::LoneSlash => "lone slash", + Self::InvalidEscape => "invalid escape", + Self::BareCarriageReturn => "bare carriage return", + Self::BareCarriageReturnInRawString => "bare carriage return in raw string", + Self::EscapeOnlyChar => "escape only char", + Self::TooShortHexEscape => "too short hex escape", + Self::InvalidCharInHexEscape => "invalid char in hex escape", + Self::OutOfRangeHexEscape => "out of range hex escape", + Self::NoBraceInUnicodeEscape => "no brace in unicode escape", + Self::InvalidCharInUnicodeEscape => "invalid char in unicode escape", + Self::EmptyUnicodeEscape => "empty unicode escape", + Self::UnclosedUnicodeEscape => "unclosed unicode escape", + Self::LeadingUnderscoreUnicodeEscape => "leading underscore unicode escape", + Self::OverlongUnicodeEscape => "overlong unicode escape", + Self::LoneSurrogateUnicodeEscape => "lone surrogate unicode escape", + Self::OutOfRangeUnicodeEscape => "out of range unicode escape", + Self::UnicodeEscapeInByte => "unicode escape in byte", + Self::NonAsciiCharInByte => "non ascii char in byte", + Self::NulInCStr => "nul in CStr", + Self::UnskippedWhitespaceWarning => "unskipped whitespace warning", + Self::MultipleSkippedLinesWarning => "multiple skipped lines warning", + }) + } +} + /// Errors returned when trying to retrieve a literal unescaped value. #[unstable(feature = "proc_macro_value", issue = "136652")] #[derive(Debug, PartialEq, Eq)] @@ -1461,9 +1589,8 @@ impl Literal { #[unstable(feature = "proc_macro_value", issue = "136652")] pub fn byte_character_value(&self) -> Result { self.0.symbol.with(|symbol| match self.0.kind { - bridge::LitKind::Char => { - unescape_byte(symbol).map_err(ConversionErrorKind::FailedToUnescape) - } + bridge::LitKind::Char => unescape_byte(symbol) + .map_err(|err| ConversionErrorKind::FailedToUnescape(err.into())), _ => Err(ConversionErrorKind::InvalidLiteralKind), }) } @@ -1472,9 +1599,8 @@ impl Literal { #[unstable(feature = "proc_macro_value", issue = "136652")] pub fn character_value(&self) -> Result { self.0.symbol.with(|symbol| match self.0.kind { - bridge::LitKind::Char => { - unescape_char(symbol).map_err(ConversionErrorKind::FailedToUnescape) - } + bridge::LitKind::Char => unescape_char(symbol) + .map_err(|err| ConversionErrorKind::FailedToUnescape(err.into())), _ => Err(ConversionErrorKind::InvalidLiteralKind), }) } @@ -1497,7 +1623,7 @@ impl Literal { Ok(c) => buf.push(c), Err(err) => { if err.is_fatal() { - error = Some(ConversionErrorKind::FailedToUnescape(err)); + error = Some(ConversionErrorKind::FailedToUnescape(err.into())); } } }, @@ -1528,7 +1654,7 @@ impl Literal { Ok(MixedUnit::HighByte(b)) => buf.push(b.get()), Err(err) => { if err.is_fatal() { - error = Some(ConversionErrorKind::FailedToUnescape(err)); + error = Some(ConversionErrorKind::FailedToUnescape(err.into())); } } }); @@ -1564,7 +1690,7 @@ impl Literal { Ok(b) => buf.push(b), Err(err) => { if err.is_fatal() { - error = Some(ConversionErrorKind::FailedToUnescape(err)); + error = Some(ConversionErrorKind::FailedToUnescape(err.into())); } } }); From 00b8189a187f353752039b72c10edd0ce2e038f9 Mon Sep 17 00:00:00 2001 From: Dnreikronos Date: Thu, 4 Jun 2026 21:42:10 +0000 Subject: [PATCH 7/8] Suppress --- .../nice_region_error/named_anon_conflict.rs | 21 ++++++++++++++++- .../infer/nice_region_error/util.rs | 11 ++++++++- compiler/rustc_trait_selection/src/errors.rs | 14 +++++++++-- ...t-ref-aliases-pointee-lifetime-distinct.rs | 10 ++++++++ ...f-aliases-pointee-lifetime-distinct.stderr | 14 +++++++++++ .../e0621-mut-ref-aliases-pointee-lifetime.rs | 23 +++++++++++++++++++ ...21-mut-ref-aliases-pointee-lifetime.stderr | 19 +++++++++++++++ 7 files changed, 108 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.stderr create mode 100644 tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.rs create mode 100644 tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs index 73a04d78519c8..ad8cc5d279af1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/named_anon_conflict.rs @@ -2,6 +2,7 @@ //! where one region is named and the other is anonymous. use rustc_errors::Diag; +use rustc_middle::ty; use tracing::debug; use crate::error_reporting::infer::nice_region_error::NiceRegionError; @@ -72,7 +73,18 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { { return None; } + let orig_ty = anon_param_info.orig_param_ty; + // Don't suggest naming the outer lifetime when it already appears in the pointee + // (e.g. `&'a mut Buffer<'a>`); point at borrow splitting instead. + let suggestion_would_alias_lifetime = + if let ty::Ref(_, orig_inner_ty, ty::Mutability::Mut) = orig_ty.kind() { + self.tcx().any_free_region_meets(orig_inner_ty, |r| r == named) + } else { + false + }; + let named = named.to_string(); + let new_ty_span = if suggestion_would_alias_lifetime { None } else { Some(new_ty_span) }; let err = match param.pat.simple_ident() { Some(simple_ident) => ExplicitLifetimeRequired::WithIdent { span, @@ -80,8 +92,15 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { named, new_ty_span, new_ty, + link_nomicon: suggestion_would_alias_lifetime, + }, + None => ExplicitLifetimeRequired::WithParamType { + span, + named, + new_ty_span, + new_ty, + link_nomicon: suggestion_would_alias_lifetime, }, - None => ExplicitLifetimeRequired::WithParamType { span, named, new_ty_span, new_ty }, }; Some(self.tcx().sess.dcx().create_err(err)) } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs index 3ec97ce76ef07..50eeb3a243266 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/util.rs @@ -16,6 +16,8 @@ pub struct AnonymousParamInfo<'tcx> { pub param: &'tcx hir::Param<'tcx>, /// The type corresponding to the anonymous region parameter. pub param_ty: Ty<'tcx>, + /// The original type before region replacement. + pub orig_param_ty: Ty<'tcx>, /// The `ty::LateParamRegionKind` corresponding to the anonymous region. pub kind: ty::LateParamRegionKind, /// The `Span` of the parameter type. @@ -94,7 +96,14 @@ pub fn find_param_with_region<'tcx>( let ty_hir_id = fn_decl.inputs[index].hir_id; let param_ty_span = tcx.hir_span(ty_hir_id); let is_first = index == 0; - AnonymousParamInfo { param, param_ty: new_param_ty, param_ty_span, kind, is_first } + AnonymousParamInfo { + param, + param_ty: new_param_ty, + orig_param_ty: ty, + param_ty_span, + kind, + is_first, + } }) }) } diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs index 5a926dc46c707..662480587fdd2 100644 --- a/compiler/rustc_trait_selection/src/errors.rs +++ b/compiler/rustc_trait_selection/src/errors.rs @@ -868,8 +868,13 @@ pub(crate) enum ExplicitLifetimeRequired<'a> { applicability = "unspecified", style = "verbose" )] - new_ty_span: Span, + new_ty_span: Option, new_ty: Ty<'a>, + #[help( + "see \ + for more information about lifetime errors related to mutable references" + )] + link_nomicon: bool, }, #[diag("explicit lifetime required in parameter type", code = E0621)] WithParamType { @@ -883,8 +888,13 @@ pub(crate) enum ExplicitLifetimeRequired<'a> { applicability = "unspecified", style = "verbose" )] - new_ty_span: Span, + new_ty_span: Option, new_ty: Ty<'a>, + #[help( + "see \ + for more information about lifetime errors related to mutable references" + )] + link_nomicon: bool, }, } diff --git a/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs new file mode 100644 index 0000000000000..a6995df36567c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs @@ -0,0 +1,10 @@ +// Regression test for #156682 +// When the suggested type would NOT alias the outer reference's lifetime with one +// already used inside the pointee, the normal suggestion should still apply. + +pub fn push<'a>(x: &mut Vec<&'a u8>, y: &u8) { + x.push(y); + //~^ ERROR explicit lifetime required in the type of `y` +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.stderr b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.stderr new file mode 100644 index 0000000000000..fdc087aa4d979 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime-distinct.stderr @@ -0,0 +1,14 @@ +error[E0621]: explicit lifetime required in the type of `y` + --> $DIR/e0621-mut-ref-aliases-pointee-lifetime-distinct.rs:6:5 + | +LL | x.push(y); + | ^^^^^^^^^ lifetime `'a` required + | +help: add explicit lifetime `'a` to the type of `y` + | +LL | pub fn push<'a>(x: &mut Vec<&'a u8>, y: &'a u8) { + | ++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0621`. diff --git a/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.rs b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.rs new file mode 100644 index 0000000000000..5b78d566bf98c --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.rs @@ -0,0 +1,23 @@ +// Regression test for #156682 +// E0621 should not suggest `&'a mut Buffer<'a>`, which would alias the outer +// reference's lifetime with one already used inside the pointee. + +pub struct Buffer<'a> { + buf: &'a mut [u8], +} + +pub fn foo<'a>(buffer: &mut Buffer<'a>) { + buffer.buf = &mut buffer.buf[..]; + //~^ ERROR explicit lifetime required in the type of `buffer` +} + +pub struct Wrapper<'a> { + inner: Buffer<'a>, +} + +pub fn baz<'a>(wrapper: &mut Wrapper<'a>) { + wrapper.inner.buf = &mut wrapper.inner.buf[..]; + //~^ ERROR explicit lifetime required in the type of `wrapper` +} + +fn main() {} diff --git a/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.stderr b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.stderr new file mode 100644 index 0000000000000..488c96061a3e9 --- /dev/null +++ b/tests/ui/lifetimes/lifetime-errors/e0621-mut-ref-aliases-pointee-lifetime.stderr @@ -0,0 +1,19 @@ +error[E0621]: explicit lifetime required in the type of `buffer` + --> $DIR/e0621-mut-ref-aliases-pointee-lifetime.rs:10:5 + | +LL | buffer.buf = &mut buffer.buf[..]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | + = help: see for more information about lifetime errors related to mutable references + +error[E0621]: explicit lifetime required in the type of `wrapper` + --> $DIR/e0621-mut-ref-aliases-pointee-lifetime.rs:19:5 + | +LL | wrapper.inner.buf = &mut wrapper.inner.buf[..]; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required + | + = help: see for more information about lifetime errors related to mutable references + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0621`. From 8dd946747efb4b0eca12b99fd4dd3d1b3473a706 Mon Sep 17 00:00:00 2001 From: Michael Goulet Date: Mon, 15 Sep 2025 12:51:57 -0400 Subject: [PATCH 8/8] Dont bail in error predicate unless self ty is error --- .../src/solve/assembly/mod.rs | 5 +++-- .../src/solve/effect_goals.rs | 1 + .../src/solve/normalizes_to/mod.rs | 17 ++++++++++++++--- .../src/solve/trait_goals.rs | 1 + compiler/rustc_type_ir/src/ty_kind/closure.rs | 9 +++++++++ ...am-type-whensubstituting-in-region-112823.rs | 2 +- 6 files changed, 29 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 16f2134684889..1c7d03f2d9771 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -224,6 +224,7 @@ where /// but prevents incorrect normalization while hiding any trait errors. fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, + goal: Goal, guar: I::ErrorGuaranteed, ) -> Result, NoSolutionOrRerunNonErased>; @@ -578,8 +579,8 @@ where // Instead of adding the logic here, it's a better idea to add it in // `EvalCtxt::disqualify_auto_trait_candidate_due_to_possible_impl` in // `solve::trait_goals` instead. - let result = if let Err(guar) = goal.predicate.error_reported() { - G::consider_error_guaranteed_candidate(self, guar) + let result = if let ty::Error(guar) = goal.predicate.self_ty().kind() { + G::consider_error_guaranteed_candidate(self, goal, guar) } else if cx.trait_is_auto(trait_def_id) { G::consider_auto_trait_candidate(self, goal) } else if cx.trait_is_alias(trait_def_id) { diff --git a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs index d6ddd9fec7c08..75ba3285e13f2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -191,6 +191,7 @@ where fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, + _goal: Goal, _guar: I::ErrorGuaranteed, ) -> Result, NoSolutionOrRerunNonErased> { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs index d35e05aa33cf2..e4c3cc110e3db 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to/mod.rs @@ -436,10 +436,21 @@ where /// Fail to normalize if the predicate contains an error, alternatively, we could normalize to `ty::Error` /// and succeed. Can experiment with this to figure out what results in better error messages. fn consider_error_guaranteed_candidate( - _ecx: &mut EvalCtxt<'_, D>, - _guar: I::ErrorGuaranteed, + ecx: &mut EvalCtxt<'_, D>, + goal: Goal, + guar: I::ErrorGuaranteed, ) -> Result, NoSolutionOrRerunNonErased> { - Err(NoSolution.into()) + let cx = ecx.cx(); + let error_term = match goal.predicate.alias.kind { + ty::AliasTermKind::ProjectionTy { .. } => Ty::new_error(cx, guar).into(), + ty::AliasTermKind::ProjectionConst { .. } => Const::new_error(cx, guar).into(), + kind => panic!("expected projection, found {kind:?}"), + }; + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + ecx.instantiate_normalizes_to_term(goal, error_term); + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } fn consider_auto_trait_candidate( diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 5e66225e5ccb3..37fc5286175bf 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -125,6 +125,7 @@ where fn consider_error_guaranteed_candidate( ecx: &mut EvalCtxt<'_, D>, + _goal: Goal, _guar: I::ErrorGuaranteed, ) -> Result, NoSolutionOrRerunNonErased> { ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) diff --git a/compiler/rustc_type_ir/src/ty_kind/closure.rs b/compiler/rustc_type_ir/src/ty_kind/closure.rs index 3b8ed0a15994d..b688a001f73fa 100644 --- a/compiler/rustc_type_ir/src/ty_kind/closure.rs +++ b/compiler/rustc_type_ir/src/ty_kind/closure.rs @@ -454,6 +454,15 @@ impl CoroutineClosureSignature { coroutine_captures_by_ref_ty: I::Ty, env_region: I::Region, ) -> I::Ty { + // If either of the tupled capture types are constrained to error + // (e.g. during typeck when the infcx is tainted), then just return + // the error type directly. + if let ty::Error(_) = tupled_inputs_ty.kind() { + return tupled_inputs_ty; + } else if let ty::Error(_) = coroutine_captures_by_ref_ty.kind() { + return coroutine_captures_by_ref_ty; + } + match kind { ty::ClosureKind::Fn | ty::ClosureKind::FnMut => { let ty::FnPtr(sig_tys, _) = coroutine_captures_by_ref_ty.kind() else { diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs index dd94458d988e6..4c3ec862675aa 100644 --- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs +++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs @@ -29,7 +29,7 @@ impl X for Y { fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {} //~^ ERROR method `line_stream` is not a member of trait `X` //[current]~^^ ERROR `()` is not a future - //[next]~^^^ ERROR: type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` + //[next]~^^^ ERROR type mismatch resolving `::LineStreamFut<'a, Repr> normalizes-to _` [E0271] } pub fn main() {}