Skip to content

Commit

Permalink
E0379: Suggest #[const_trait] in diagnostic
Browse files Browse the repository at this point in the history
  • Loading branch information
fmease committed Jan 2, 2024
1 parent d62ea0e commit 8eb7a14
Show file tree
Hide file tree
Showing 5 changed files with 49 additions and 5 deletions.
1 change: 1 addition & 0 deletions compiler/rustc_ast_passes/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ ast_passes_trait_fn_const =
.const_context_label = this declares all associated functions implicitly const
.remove_const_sugg = remove the `const`
.make_impl_const_sugg = and declare the impl to be const instead
.make_trait_const_sugg = and declare the trait to be a `#[const_trait]` instead
ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
Expand Down
24 changes: 20 additions & 4 deletions compiler/rustc_ast_passes/src/ast_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ struct AstValidator<'a> {
/// If so, this is the span of the constness.
in_const_trait_or_impl: Option<Span>,

/// Are we inside a trait?
///
/// If so, this is the span of the trait.
in_trait: Option<Span>,

has_proc_macro_decls: bool,

/// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
Expand Down Expand Up @@ -101,10 +106,12 @@ impl<'a> AstValidator<'a> {
self.in_const_trait_or_impl = old_const;
}

fn with_in_trait(&mut self, is_const: Option<Span>, f: impl FnOnce(&mut Self)) {
fn with_in_trait(&mut self, span: Span, is_const: Option<Span>, f: impl FnOnce(&mut Self)) {
let old = mem::replace(&mut self.in_const_trait_or_impl, is_const);
let old_trait = mem::replace(&mut self.in_trait, Some(span));
f(self);
self.in_const_trait_or_impl = old;
self.in_trait = old_trait;
}

fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) {
Expand Down Expand Up @@ -314,8 +321,15 @@ impl<'a> AstValidator<'a> {
None
};

// FIXME(const_trait_impl): If the trait is not const and feature `const_trait_impl`
// is enabled, provide a structured suggestion to make the trait const.
let make_trait_const_sugg = if self.in_const_trait_or_impl.is_none()
&& let Some(trait_) = self.in_trait
&& self.features.const_trait_impl
{
Some(trait_.shrink_to_lo())
} else {
None
};

self.dcx().emit_err(errors::TraitFnConst {
span,
in_impl: self.in_trait_impl.is_some(),
Expand All @@ -328,6 +342,7 @@ impl<'a> AstValidator<'a> {
},
),
make_impl_const_sugg,
make_trait_const_sugg,
});
}

Expand Down Expand Up @@ -999,7 +1014,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
let is_const_trait =
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
self.with_in_trait(is_const_trait, |this| {
self.with_in_trait(item.span, is_const_trait, |this| {
if *is_auto == IsAuto::Yes {
// Auto traits cannot have generics, super traits nor contain items.
this.deny_generic_params(generics, item.ident.span);
Expand Down Expand Up @@ -1585,6 +1600,7 @@ pub fn check_crate(
extern_mod: None,
in_trait_impl: None,
in_const_trait_or_impl: None,
in_trait: None,
has_proc_macro_decls: false,
outer_impl_trait: None,
disallow_tilde_const: Some(DisallowTildeConstContext::Item),
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_ast_passes/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,12 @@ pub struct TraitFnConst {
applicability = "maybe-incorrect"
)]
pub make_impl_const_sugg: Option<Span>,
#[suggestion(
ast_passes_make_trait_const_sugg,
code = "#[const_trait]\n",
applicability = "maybe-incorrect"
)]
pub make_trait_const_sugg: Option<Span>,
}

#[derive(Diagnostic)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,8 @@ impl Trait for u32 {
const fn fun() {} //~ ERROR functions in trait impls cannot be declared const
}

trait NonConst {
const fn fun(); //~ ERROR functions in traits cannot be declared const
}

fn main() {}
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,23 @@ help: and declare the impl to be const instead
LL | impl const Trait for u32 {
| +++++

error: aborting due to 3 previous errors
error[E0379]: functions in traits cannot be declared const
--> $DIR/trait-fn-const.rs:18:5
|
LL | const fn fun();
| ^^^^^ functions in traits cannot be const
|
help: remove the `const`
|
LL - const fn fun();
LL + fn fun();
|
help: and declare the trait to be a `#[const_trait]` instead
|
LL + #[const_trait]
LL | trait NonConst {
|

error: aborting due to 4 previous errors

For more information about this error, try `rustc --explain E0379`.

0 comments on commit 8eb7a14

Please sign in to comment.