Forbid const fn within const impls

This commit is contained in:
Oli Scherer 2025-07-22 11:11:47 +00:00 committed by Oli Scherer
parent ababa26251
commit b41c2a2870
8 changed files with 101 additions and 8 deletions

View file

@ -204,6 +204,11 @@ ast_passes_generic_before_constraints = generic arguments must come before the f
ast_passes_generic_default_trailing = generic parameters with a default must be trailing
ast_passes_impl_fn_const =
redundant `const` fn marker in const impl
.parent_constness = this declares all associated functions implicitly const
.label = remove the `const`
ast_passes_incompatible_features = `{$f1}` and `{$f2}` are incompatible, using them at the same time is not allowed
.help = remove one of these features

View file

@ -242,6 +242,20 @@ impl<'a> AstValidator<'a> {
}
}
fn check_impl_fn_not_const(&self, constness: Const, parent_constness: Const) {
let Const::Yes(span) = constness else {
return;
};
let span = self.sess.source_map().span_extend_while_whitespace(span);
let Const::Yes(parent_constness) = parent_constness else {
return;
};
self.dcx().emit_err(errors::ImplFnConst { span, parent_constness });
}
fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrImpl) {
let Const::Yes(span) = constness else {
return;
@ -1689,14 +1703,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
);
}
if let Some(parent @ (TraitOrImpl::Trait { .. } | TraitOrImpl::TraitImpl { .. })) =
&self.outer_trait_or_trait_impl
{
self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
self.check_trait_fn_not_const(sig.header.constness, parent);
self.check_async_fn_in_const_trait_or_impl(sig, parent);
match &self.outer_trait_or_trait_impl {
Some(parent @ (TraitOrImpl::Trait { .. } | TraitOrImpl::TraitImpl { .. })) => {
self.visibility_not_permitted(
&item.vis,
errors::VisibilityNotPermittedNote::TraitImpl,
);
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
self.check_trait_fn_not_const(sig.header.constness, parent);
self.check_async_fn_in_const_trait_or_impl(sig, parent);
}
}
Some(TraitOrImpl::Impl { constness }) => {
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
self.check_impl_fn_not_const(sig.header.constness, *constness);
}
}
None => {}
}
if let AssocItemKind::Const(ci) = &item.kind {

View file

@ -35,6 +35,15 @@ pub(crate) enum VisibilityNotPermittedNote {
#[note(ast_passes_individual_foreign_items)]
IndividualForeignItems,
}
#[derive(Diagnostic)]
#[diag(ast_passes_impl_fn_const)]
pub(crate) struct ImplFnConst {
#[primary_span]
#[suggestion(ast_passes_label, code = "", applicability = "machine-applicable")]
pub span: Span,
#[label(ast_passes_parent_constness)]
pub parent_constness: Span,
}
#[derive(Diagnostic)]
#[diag(ast_passes_trait_fn_const, code = E0379)]

View file

@ -0,0 +1,18 @@
//@run-rustfix
#![feature(const_trait_impl)]
struct Foo;
const impl Foo {
fn bar() {}
fn baz() {}
//~^ ERROR: redundant `const`
}
const _: () = {
Foo::bar();
Foo::baz();
};
fn main() {
}

View file

@ -0,0 +1,18 @@
//@run-rustfix
#![feature(const_trait_impl)]
struct Foo;
const impl Foo {
fn bar() {}
const fn baz() {}
//~^ ERROR: redundant `const`
}
const _: () = {
Foo::bar();
Foo::baz();
};
fn main() {
}

View file

@ -0,0 +1,11 @@
error: redundant `const` fn marker in const impl
--> $DIR/const-impl-inherent-double-const.rs:8:5
|
LL | const impl Foo {
| ----- this declares all associated functions implicitly const
LL | fn bar() {}
LL | const fn baz() {}
| ^^^^^^ help: remove the `const`
error: aborting due to 1 previous error

View file

@ -7,6 +7,7 @@ impl const dyn T {
pub const fn new() -> std::sync::Mutex<dyn T> {}
//~^ ERROR mismatched types
//~| ERROR cannot be known at compilation time
//~| ERROR redundant `const` fn marker in const impl
}
fn main() {}

View file

@ -1,3 +1,11 @@
error: redundant `const` fn marker in const impl
--> $DIR/span-bug-issue-121418.rs:7:9
|
LL | impl const dyn T {
| ----- this declares all associated functions implicitly const
LL | pub const fn new() -> std::sync::Mutex<dyn T> {}
| ^^^^^^ help: remove the `const`
error[E0277]: the size for values of type `(dyn T + 'static)` cannot be known at compilation time
--> $DIR/span-bug-issue-121418.rs:7:27
|
@ -20,7 +28,7 @@ LL | pub const fn new() -> std::sync::Mutex<dyn T> {}
= note: expected struct `std::sync::Mutex<(dyn T + 'static)>`
found unit type `()`
error: aborting due to 2 previous errors
error: aborting due to 3 previous errors
Some errors have detailed explanations: E0277, E0308.
For more information about an error, try `rustc --explain E0277`.