Forbid const fn within const impls
This commit is contained in:
parent
ababa26251
commit
b41c2a2870
8 changed files with 101 additions and 8 deletions
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
}
|
||||
|
|
@ -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() {
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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() {}
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue