From 231a3a241bbf91771533d3c3b35e868a50ee6d15 Mon Sep 17 00:00:00 2001 From: lapla Date: Tue, 25 Nov 2025 17:53:48 +0900 Subject: [PATCH 1/3] Deny const auto traits --- compiler/rustc_ast_passes/messages.ftl | 3 +++ compiler/rustc_ast_passes/src/ast_validation.rs | 8 ++++++++ compiler/rustc_ast_passes/src/errors.rs | 8 ++++++++ tests/ui/traits/const-traits/const-auto-trait.rs | 6 ++++++ tests/ui/traits/const-traits/const-auto-trait.stderr | 10 ++++++++++ 5 files changed, 35 insertions(+) create mode 100644 tests/ui/traits/const-traits/const-auto-trait.rs create mode 100644 tests/ui/traits/const-traits/const-auto-trait.stderr diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index 9bdbcf6ab9071..f03c7dd5b9d59 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -89,6 +89,9 @@ ast_passes_const_and_coroutine = functions cannot be both `const` and `{$corouti .coroutine = `{$coroutine_kind}` because of this .label = {""} +ast_passes_const_auto_trait = auto traits cannot be const + .help = remove the `const` keyword + ast_passes_const_bound_trait_object = const trait bounds are not allowed in trait object types ast_passes_const_without_body = diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index 163dbc3350ba2..e57f8da26769b 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -820,6 +820,12 @@ impl<'a> AstValidator<'a> { self.dcx().emit_err(errors::ModuleNonAscii { span: ident.span, name: ident.name }); } + fn deny_const_auto_traits(&self, constness: Const) { + if let Const::Yes(span) = constness { + self.dcx().emit_err(errors::ConstAutoTrait { span }); + } + } + fn deny_generic_params(&self, generics: &Generics, ident_span: Span) { if !generics.params.is_empty() { self.dcx() @@ -1257,6 +1263,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> { }) => { self.visit_attrs_vis_ident(&item.attrs, &item.vis, ident); if *is_auto == IsAuto::Yes { + // For why we reject `const auto trait`, see rust-lang/rust#149285. + self.deny_const_auto_traits(*constness); // Auto traits cannot have generics, super traits nor contain items. self.deny_generic_params(generics, ident.span); self.deny_super_traits(bounds, ident.span); diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 02e6ecfbaee74..c700ae517140c 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -429,6 +429,14 @@ pub(crate) struct AutoTraitItems { pub ident: Span, } +#[derive(Diagnostic)] +#[diag(ast_passes_const_auto_trait)] +#[help] +pub(crate) struct ConstAutoTrait { + #[primary_span] + pub span: Span, +} + #[derive(Diagnostic)] #[diag(ast_passes_generic_before_constraints)] pub(crate) struct ArgsBeforeConstraint { diff --git a/tests/ui/traits/const-traits/const-auto-trait.rs b/tests/ui/traits/const-traits/const-auto-trait.rs new file mode 100644 index 0000000000000..06558df4623f9 --- /dev/null +++ b/tests/ui/traits/const-traits/const-auto-trait.rs @@ -0,0 +1,6 @@ +#![feature(auto_traits, const_trait_impl)] + +const auto trait Marker {} +//~^ ERROR: auto traits cannot be const + +fn main() {} diff --git a/tests/ui/traits/const-traits/const-auto-trait.stderr b/tests/ui/traits/const-traits/const-auto-trait.stderr new file mode 100644 index 0000000000000..cb8ff8001ba09 --- /dev/null +++ b/tests/ui/traits/const-traits/const-auto-trait.stderr @@ -0,0 +1,10 @@ +error: auto traits cannot be const + --> $DIR/const-auto-trait.rs:3:1 + | +LL | const auto trait Marker {} + | ^^^^^ + | + = help: remove the `const` keyword + +error: aborting due to 1 previous error + From 3326fbd1f4670e0270cd92734cf468e90e2ccc0c Mon Sep 17 00:00:00 2001 From: lapla Date: Tue, 25 Nov 2025 17:54:16 +0900 Subject: [PATCH 2/3] Check existing tests to only verify const auto traits parsing --- tests/ui/traits/const-traits/parse-const-unsafe-trait.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs b/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs index 3d62405d9ae20..58a3b5a4cc61f 100644 --- a/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs +++ b/tests/ui/traits/const-traits/parse-const-unsafe-trait.rs @@ -1,5 +1,6 @@ // Test that `const unsafe trait` and `const unsafe auto trait` works. +//@ compile-flags: -Zparse-crate-root-only //@ check-pass #![feature(const_trait_impl)] From ae699c8e78469207ccd39f1165ab7f6e1e3f58fe Mon Sep 17 00:00:00 2001 From: lapla Date: Wed, 26 Nov 2025 01:02:01 +0900 Subject: [PATCH 3/3] Avoid ICE when handling const auto traits in the next-gen solver --- .../src/solve/effect_goals.rs | 5 +++-- .../ui/traits/const-traits/const-auto-trait.rs | 9 +++++++++ .../traits/const-traits/const-auto-trait.stderr | 17 +++++++++++++++-- 3 files changed, 27 insertions(+), 4 deletions(-) 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 2cb79a0219f6e..2837b8565f603 100644 --- a/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/effect_goals.rs @@ -189,10 +189,11 @@ where } fn consider_auto_trait_candidate( - _ecx: &mut EvalCtxt<'_, D>, + ecx: &mut EvalCtxt<'_, D>, _goal: Goal, ) -> Result, NoSolution> { - unreachable!("auto traits are never const") + ecx.cx().delay_bug("auto traits are never const"); + Err(NoSolution) } fn consider_trait_alias_candidate( diff --git a/tests/ui/traits/const-traits/const-auto-trait.rs b/tests/ui/traits/const-traits/const-auto-trait.rs index 06558df4623f9..d1745a2ec4c72 100644 --- a/tests/ui/traits/const-traits/const-auto-trait.rs +++ b/tests/ui/traits/const-traits/const-auto-trait.rs @@ -1,6 +1,15 @@ +//@ compile-flags: -Znext-solver +// See rust-lang/rust#149285 for this test + #![feature(auto_traits, const_trait_impl)] const auto trait Marker {} //~^ ERROR: auto traits cannot be const +fn scope() { + fn check() {} + check::<()>(); + //~^ ERROR: the trait bound `(): const Marker` is not satisfied +} + fn main() {} diff --git a/tests/ui/traits/const-traits/const-auto-trait.stderr b/tests/ui/traits/const-traits/const-auto-trait.stderr index cb8ff8001ba09..094c334fc2897 100644 --- a/tests/ui/traits/const-traits/const-auto-trait.stderr +++ b/tests/ui/traits/const-traits/const-auto-trait.stderr @@ -1,10 +1,23 @@ error: auto traits cannot be const - --> $DIR/const-auto-trait.rs:3:1 + --> $DIR/const-auto-trait.rs:6:1 | LL | const auto trait Marker {} | ^^^^^ | = help: remove the `const` keyword -error: aborting due to 1 previous error +error[E0277]: the trait bound `(): const Marker` is not satisfied + --> $DIR/const-auto-trait.rs:11:13 + | +LL | check::<()>(); + | ^^ + | +note: required by a bound in `check` + --> $DIR/const-auto-trait.rs:10:17 + | +LL | fn check() {} + | ^^^^^^^^^^^^ required by this bound in `check` + +error: aborting due to 2 previous errors +For more information about this error, try `rustc --explain E0277`.