Skip to content

Commit 8eb7a14

Browse files
committed
E0379: Suggest #[const_trait] in diagnostic
1 parent d62ea0e commit 8eb7a14

File tree

5 files changed

+49
-5
lines changed

5 files changed

+49
-5
lines changed

compiler/rustc_ast_passes/messages.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,7 @@ ast_passes_trait_fn_const =
244244
.const_context_label = this declares all associated functions implicitly const
245245
.remove_const_sugg = remove the `const`
246246
.make_impl_const_sugg = and declare the impl to be const instead
247+
.make_trait_const_sugg = and declare the trait to be a `#[const_trait]` instead
247248
248249
ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
249250

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,11 @@ struct AstValidator<'a> {
6363
/// If so, this is the span of the constness.
6464
in_const_trait_or_impl: Option<Span>,
6565

66+
/// Are we inside a trait?
67+
///
68+
/// If so, this is the span of the trait.
69+
in_trait: Option<Span>,
70+
6671
has_proc_macro_decls: bool,
6772

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

104-
fn with_in_trait(&mut self, is_const: Option<Span>, f: impl FnOnce(&mut Self)) {
109+
fn with_in_trait(&mut self, span: Span, is_const: Option<Span>, f: impl FnOnce(&mut Self)) {
105110
let old = mem::replace(&mut self.in_const_trait_or_impl, is_const);
111+
let old_trait = mem::replace(&mut self.in_trait, Some(span));
106112
f(self);
107113
self.in_const_trait_or_impl = old;
114+
self.in_trait = old_trait;
108115
}
109116

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

317-
// FIXME(const_trait_impl): If the trait is not const and feature `const_trait_impl`
318-
// is enabled, provide a structured suggestion to make the trait const.
324+
let make_trait_const_sugg = if self.in_const_trait_or_impl.is_none()
325+
&& let Some(trait_) = self.in_trait
326+
&& self.features.const_trait_impl
327+
{
328+
Some(trait_.shrink_to_lo())
329+
} else {
330+
None
331+
};
332+
319333
self.dcx().emit_err(errors::TraitFnConst {
320334
span,
321335
in_impl: self.in_trait_impl.is_some(),
@@ -328,6 +342,7 @@ impl<'a> AstValidator<'a> {
328342
},
329343
),
330344
make_impl_const_sugg,
345+
make_trait_const_sugg,
331346
});
332347
}
333348

@@ -999,7 +1014,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
9991014
ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
10001015
let is_const_trait =
10011016
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
1002-
self.with_in_trait(is_const_trait, |this| {
1017+
self.with_in_trait(item.span, is_const_trait, |this| {
10031018
if *is_auto == IsAuto::Yes {
10041019
// Auto traits cannot have generics, super traits nor contain items.
10051020
this.deny_generic_params(generics, item.ident.span);
@@ -1585,6 +1600,7 @@ pub fn check_crate(
15851600
extern_mod: None,
15861601
in_trait_impl: None,
15871602
in_const_trait_or_impl: None,
1603+
in_trait: None,
15881604
has_proc_macro_decls: false,
15891605
outer_impl_trait: None,
15901606
disallow_tilde_const: Some(DisallowTildeConstContext::Item),

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,12 @@ pub struct TraitFnConst {
6060
applicability = "maybe-incorrect"
6161
)]
6262
pub make_impl_const_sugg: Option<Span>,
63+
#[suggestion(
64+
ast_passes_make_trait_const_sugg,
65+
code = "#[const_trait]\n",
66+
applicability = "maybe-incorrect"
67+
)]
68+
pub make_trait_const_sugg: Option<Span>,
6369
}
6470

6571
#[derive(Diagnostic)]

tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ impl Trait for u32 {
1414
const fn fun() {} //~ ERROR functions in trait impls cannot be declared const
1515
}
1616

17+
trait NonConst {
18+
const fn fun(); //~ ERROR functions in traits cannot be declared const
19+
}
20+
1721
fn main() {}

tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,23 @@ help: and declare the impl to be const instead
3737
LL | impl const Trait for u32 {
3838
| +++++
3939

40-
error: aborting due to 3 previous errors
40+
error[E0379]: functions in traits cannot be declared const
41+
--> $DIR/trait-fn-const.rs:18:5
42+
|
43+
LL | const fn fun();
44+
| ^^^^^ functions in traits cannot be const
45+
|
46+
help: remove the `const`
47+
|
48+
LL - const fn fun();
49+
LL + fn fun();
50+
|
51+
help: and declare the trait to be a `#[const_trait]` instead
52+
|
53+
LL + #[const_trait]
54+
LL | trait NonConst {
55+
|
56+
57+
error: aborting due to 4 previous errors
4158

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

0 commit comments

Comments
 (0)