Rollup merge of #149307 - lapla-cogito:deny_const_auto_trait, r=fmease

Deny const auto traits

close rust-lang/rust#149285

The AST validation now detects and rejects const auto traits. Additionally, I updated an existing test that was using `const unsafe auto trait`.

r? fmease
This commit is contained in:
Stuart Cook 2025-11-26 23:32:08 +11:00 committed by GitHub
commit aa98135ace
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 61 additions and 2 deletions

View file

@ -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 =

View file

@ -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);

View file

@ -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 {

View file

@ -189,10 +189,11 @@ where
}
fn consider_auto_trait_candidate(
_ecx: &mut EvalCtxt<'_, D>,
ecx: &mut EvalCtxt<'_, D>,
_goal: Goal<I, Self>,
) -> Result<Candidate<I>, NoSolution> {
unreachable!("auto traits are never const")
ecx.cx().delay_bug("auto traits are never const");
Err(NoSolution)
}
fn consider_trait_alias_candidate(

View file

@ -0,0 +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<T: const Marker>() {}
check::<()>();
//~^ ERROR: the trait bound `(): const Marker` is not satisfied
}
fn main() {}

View file

@ -0,0 +1,23 @@
error: auto traits cannot be const
--> $DIR/const-auto-trait.rs:6:1
|
LL | const auto trait Marker {}
| ^^^^^
|
= help: remove the `const` keyword
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<T: const Marker>() {}
| ^^^^^^^^^^^^ required by this bound in `check`
error: aborting due to 2 previous errors
For more information about this error, try `rustc --explain E0277`.

View file

@ -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)]