Skip to content

Commit 7b22bc6

Browse files
committed
E0379: Provide help and more context for diagnostic
1 parent 7ab8a5f commit 7b22bc6

File tree

11 files changed

+110
-31
lines changed

11 files changed

+110
-31
lines changed

compiler/rustc_ast_passes/messages.ftl

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -241,6 +241,8 @@ ast_passes_trait_fn_const =
241241
[true] trait impls
242242
*[false] traits
243243
} cannot be const
244+
.const_context_label = this declares all associated functions implicitly const
245+
.remove_const_sugg = remove the `const`
244246
245247
ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
246248

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 37 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@ struct AstValidator<'a> {
5757
in_trait_impl: bool,
5858

5959
/// Are we inside a const trait defn or impl?
60-
in_const_trait_or_impl: bool,
60+
///
61+
/// If so, this is the span of the constness.
62+
in_const_trait_or_impl: Option<Span>,
6163

6264
has_proc_macro_decls: bool,
6365

@@ -85,14 +87,17 @@ impl<'a> AstValidator<'a> {
8587
let old = mem::replace(&mut self.in_trait_impl, is_in);
8688
let old_const = mem::replace(
8789
&mut self.in_const_trait_or_impl,
88-
matches!(constness, Some(Const::Yes(_))),
90+
match constness {
91+
Some(Const::Yes(span)) => Some(span),
92+
_ => None,
93+
},
8994
);
9095
f(self);
9196
self.in_trait_impl = old;
9297
self.in_const_trait_or_impl = old_const;
9398
}
9499

95-
fn with_in_trait(&mut self, is_const: bool, f: impl FnOnce(&mut Self)) {
100+
fn with_in_trait(&mut self, is_const: Option<Span>, f: impl FnOnce(&mut Self)) {
96101
let old = mem::replace(&mut self.in_const_trait_or_impl, is_const);
97102
f(self);
98103
self.in_const_trait_or_impl = old;
@@ -292,9 +297,24 @@ impl<'a> AstValidator<'a> {
292297
}
293298

294299
fn check_trait_fn_not_const(&self, constness: Const) {
295-
if let Const::Yes(span) = constness {
296-
self.dcx().emit_err(errors::TraitFnConst { span, in_impl: self.in_trait_impl });
297-
}
300+
let Const::Yes(span) = constness else {
301+
return;
302+
};
303+
304+
// FIXME(const_trait_impl): If the trait or impl is not const and feature `const_trait_impl`
305+
// is enabled, provide a structured suggestion to make the trait (impl) const.
306+
self.dcx().emit_err(errors::TraitFnConst {
307+
span,
308+
in_impl: self.in_trait_impl,
309+
const_context_label: self.in_const_trait_or_impl,
310+
remove_const_sugg: (
311+
self.session.source_map().span_extend_while(span, |c| c == ' ').unwrap_or(span),
312+
match self.in_const_trait_or_impl {
313+
Some(_) => rustc_errors::Applicability::MachineApplicable,
314+
None => rustc_errors::Applicability::MaybeIncorrect,
315+
},
316+
),
317+
});
298318
}
299319

300320
fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
@@ -963,7 +983,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
963983
}
964984
}
965985
ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => {
966-
let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait);
986+
let is_const_trait =
987+
attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span);
967988
self.with_in_trait(is_const_trait, |this| {
968989
if *is_auto == IsAuto::Yes {
969990
// Auto traits cannot have generics, super traits nor contain items.
@@ -977,8 +998,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
977998
// context for the supertraits.
978999
this.visit_vis(&item.vis);
9791000
this.visit_ident(item.ident);
980-
let disallowed =
981-
(!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span));
1001+
let disallowed = is_const_trait
1002+
.is_none()
1003+
.then(|| DisallowTildeConstContext::Trait(item.span));
9821004
this.with_tilde_const(disallowed, |this| {
9831005
this.visit_generics(generics);
9841006
walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits)
@@ -1340,9 +1362,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13401362
});
13411363
}
13421364

1343-
let tilde_const_allowed =
1344-
matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. }))
1345-
|| matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl);
1365+
let tilde_const_allowed = matches!(
1366+
fk.header(),
1367+
Some(FnHeader { constness: ast::Const::Yes(_), .. })
1368+
) || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl.is_some());
13461369

13471370
let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk));
13481371
self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk));
@@ -1414,7 +1437,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14141437

14151438
match &item.kind {
14161439
AssocItemKind::Fn(box Fn { sig, generics, body, .. })
1417-
if self.in_const_trait_or_impl
1440+
if self.in_const_trait_or_impl.is_some()
14181441
|| ctxt == AssocCtxt::Trait
14191442
|| matches!(sig.header.constness, Const::Yes(_)) =>
14201443
{
@@ -1548,7 +1571,7 @@ pub fn check_crate(
15481571
features,
15491572
extern_mod: None,
15501573
in_trait_impl: false,
1551-
in_const_trait_or_impl: false,
1574+
in_const_trait_or_impl: None,
15521575
has_proc_macro_decls: false,
15531576
outer_impl_trait: None,
15541577
disallow_tilde_const: Some(DisallowTildeConstContext::Item),

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! Errors emitted by ast_passes.
22
33
use rustc_ast::ParamKindOrd;
4-
use rustc_errors::AddToDiagnostic;
4+
use rustc_errors::{AddToDiagnostic, Applicability};
55
use rustc_macros::{Diagnostic, Subdiagnostic};
66
use rustc_span::{symbol::Ident, Span, Symbol};
77

@@ -50,6 +50,10 @@ pub struct TraitFnConst {
5050
#[label]
5151
pub span: Span,
5252
pub in_impl: bool,
53+
#[label(ast_passes_const_context_label)]
54+
pub const_context_label: Option<Span>,
55+
#[suggestion(ast_passes_remove_const_sugg, code = "")]
56+
pub remove_const_sugg: (Span, Applicability),
5357
}
5458

5559
#[derive(Diagnostic)]

tests/ui/consts/const-fn-mismatch.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0379]: functions in trait impls cannot be declared const
22
--> $DIR/const-fn-mismatch.rs:11:5
33
|
44
LL | const fn f() -> u32 {
5-
| ^^^^^ functions in trait impls cannot be const
5+
| ^^^^^-
6+
| |
7+
| functions in trait impls cannot be const
8+
| help: remove the `const`
69

710
error: aborting due to 1 previous error
811

tests/ui/consts/const-fn-not-in-trait.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ error[E0379]: functions in traits cannot be declared const
22
--> $DIR/const-fn-not-in-trait.rs:5:5
33
|
44
LL | const fn f() -> u32;
5-
| ^^^^^ functions in traits cannot be const
5+
| ^^^^^-
6+
| |
7+
| functions in traits cannot be const
8+
| help: remove the `const`
69

710
error[E0379]: functions in traits cannot be declared const
811
--> $DIR/const-fn-not-in-trait.rs:7:5
912
|
1013
LL | const fn g() -> u32 {
11-
| ^^^^^ functions in traits cannot be const
14+
| ^^^^^-
15+
| |
16+
| functions in traits cannot be const
17+
| help: remove the `const`
1218

1319
error: aborting due to 2 previous errors
1420

tests/ui/consts/issue-54954.stderr

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ error[E0379]: functions in traits cannot be declared const
22
--> $DIR/issue-54954.rs:5:5
33
|
44
LL | const fn const_val<T: Sized>() -> usize {
5-
| ^^^^^ functions in traits cannot be const
5+
| ^^^^^-
6+
| |
7+
| functions in traits cannot be const
8+
| help: remove the `const`
69

710
error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type
811
--> $DIR/issue-54954.rs:1:24

tests/ui/feature-gates/feature-gate-min_const_fn.stderr

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,28 @@ error[E0379]: functions in traits cannot be declared const
22
--> $DIR/feature-gate-min_const_fn.rs:6:5
33
|
44
LL | const fn foo() -> u32;
5-
| ^^^^^ functions in traits cannot be const
5+
| ^^^^^-
6+
| |
7+
| functions in traits cannot be const
8+
| help: remove the `const`
69

710
error[E0379]: functions in traits cannot be declared const
811
--> $DIR/feature-gate-min_const_fn.rs:7:5
912
|
1013
LL | const fn bar() -> u32 { 0 }
11-
| ^^^^^ functions in traits cannot be const
14+
| ^^^^^-
15+
| |
16+
| functions in traits cannot be const
17+
| help: remove the `const`
1218

1319
error[E0379]: functions in trait impls cannot be declared const
1420
--> $DIR/feature-gate-min_const_fn.rs:11:5
1521
|
1622
LL | const fn foo() -> u32 { 0 }
17-
| ^^^^^ functions in trait impls cannot be const
23+
| ^^^^^-
24+
| |
25+
| functions in trait impls cannot be const
26+
| help: remove the `const`
1827

1928
error: aborting due to 3 previous errors
2029

tests/ui/mismatched_types/const-fn-in-trait.stderr

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,19 @@ error[E0379]: functions in traits cannot be declared const
22
--> $DIR/const-fn-in-trait.rs:3:5
33
|
44
LL | const fn g();
5-
| ^^^^^ functions in traits cannot be const
5+
| ^^^^^-
6+
| |
7+
| functions in traits cannot be const
8+
| help: remove the `const`
69

710
error[E0379]: functions in trait impls cannot be declared const
811
--> $DIR/const-fn-in-trait.rs:7:5
912
|
1013
LL | const fn f() -> u32 { 22 }
11-
| ^^^^^ functions in trait impls cannot be const
14+
| ^^^^^-
15+
| |
16+
| functions in trait impls cannot be const
17+
| help: remove the `const`
1218

1319
error: aborting due to 2 previous errors
1420

tests/ui/parser/fn-header-semantic-fail.stderr

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ error[E0379]: functions in traits cannot be declared const
1111
--> $DIR/fn-header-semantic-fail.rs:18:9
1212
|
1313
LL | const fn ft3();
14-
| ^^^^^ functions in traits cannot be const
14+
| ^^^^^-
15+
| |
16+
| functions in traits cannot be const
17+
| help: remove the `const`
1518

1619
error[E0379]: functions in traits cannot be declared const
1720
--> $DIR/fn-header-semantic-fail.rs:20:9
1821
|
1922
LL | const async unsafe extern "C" fn ft5();
20-
| ^^^^^ functions in traits cannot be const
23+
| ^^^^^-
24+
| |
25+
| functions in traits cannot be const
26+
| help: remove the `const`
2127

2228
error: functions cannot be both `const` and `async`
2329
--> $DIR/fn-header-semantic-fail.rs:20:9
@@ -32,13 +38,19 @@ error[E0379]: functions in trait impls cannot be declared const
3238
--> $DIR/fn-header-semantic-fail.rs:29:9
3339
|
3440
LL | const fn ft3() {}
35-
| ^^^^^ functions in trait impls cannot be const
41+
| ^^^^^-
42+
| |
43+
| functions in trait impls cannot be const
44+
| help: remove the `const`
3645

3746
error[E0379]: functions in trait impls cannot be declared const
3847
--> $DIR/fn-header-semantic-fail.rs:31:9
3948
|
4049
LL | const async unsafe extern "C" fn ft5() {}
41-
| ^^^^^ functions in trait impls cannot be const
50+
| ^^^^^-
51+
| |
52+
| functions in trait impls cannot be const
53+
| help: remove the `const`
4254

4355
error: functions cannot be both `const` and `async`
4456
--> $DIR/fn-header-semantic-fail.rs:31:9

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ trait Trait {
77
}
88

99
impl const Trait for () {
10-
const fn fun() {} //~ ERROR functions in trait impls cannot be declared const
10+
const fn fun() {} //~ ERROR functions in trait impls cannot be declared const
1111
}
1212

1313
fn main() {}

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,25 @@
11
error[E0379]: functions in traits cannot be declared const
22
--> $DIR/trait-fn-const.rs:6:5
33
|
4+
LL | #[const_trait]
5+
| -------------- this declares all associated functions implicitly const
6+
LL | trait Trait {
47
LL | const fn fun();
5-
| ^^^^^ functions in traits cannot be const
8+
| ^^^^^-
9+
| |
10+
| functions in traits cannot be const
11+
| help: remove the `const`
612

713
error[E0379]: functions in trait impls cannot be declared const
814
--> $DIR/trait-fn-const.rs:10:5
915
|
16+
LL | impl const Trait for () {
17+
| ----- this declares all associated functions implicitly const
1018
LL | const fn fun() {}
11-
| ^^^^^ functions in trait impls cannot be const
19+
| ^^^^^-
20+
| |
21+
| functions in trait impls cannot be const
22+
| help: remove the `const`
1223

1324
error: aborting due to 2 previous errors
1425

0 commit comments

Comments
 (0)