Skip to content

Commit d62ea0e

Browse files
committed
E0379: Suggest impl const in diagnostic
1 parent 7b22bc6 commit d62ea0e

File tree

5 files changed

+56
-16
lines changed

5 files changed

+56
-16
lines changed

compiler/rustc_ast_passes/messages.ftl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,7 @@ ast_passes_trait_fn_const =
243243
} cannot be const
244244
.const_context_label = this declares all associated functions implicitly const
245245
.remove_const_sugg = remove the `const`
246+
.make_impl_const_sugg = and declare the impl to be const instead
246247
247248
ast_passes_trait_object_single_bound = only a single explicit lifetime bound is permitted
248249

compiler/rustc_ast_passes/src/ast_validation.rs

Lines changed: 28 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ struct AstValidator<'a> {
5454
extern_mod: Option<&'a Item>,
5555

5656
/// Are we inside a trait impl?
57-
in_trait_impl: bool,
57+
///
58+
/// If so, this is the trait ref together with its polarity.
59+
in_trait_impl: Option<(ImplPolarity, &'a TraitRef)>,
5860

5961
/// Are we inside a const trait defn or impl?
6062
///
@@ -80,15 +82,17 @@ struct AstValidator<'a> {
8082
impl<'a> AstValidator<'a> {
8183
fn with_in_trait_impl(
8284
&mut self,
83-
is_in: bool,
84-
constness: Option<Const>,
85+
trait_ref: Option<(Const, ImplPolarity, &'a TraitRef)>,
8586
f: impl FnOnce(&mut Self),
8687
) {
87-
let old = mem::replace(&mut self.in_trait_impl, is_in);
88+
let old = mem::replace(
89+
&mut self.in_trait_impl,
90+
trait_ref.map(|(_, polarity, trait_ref)| (polarity, trait_ref)),
91+
);
8892
let old_const = mem::replace(
8993
&mut self.in_const_trait_or_impl,
90-
match constness {
91-
Some(Const::Yes(span)) => Some(span),
94+
match trait_ref {
95+
Some((Const::Yes(span), ..)) => Some(span),
9296
_ => None,
9397
},
9498
);
@@ -301,11 +305,20 @@ impl<'a> AstValidator<'a> {
301305
return;
302306
};
303307

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.
308+
let make_impl_const_sugg = if self.in_const_trait_or_impl.is_none()
309+
&& let Some((ImplPolarity::Positive, trait_ref)) = self.in_trait_impl
310+
&& self.features.const_trait_impl
311+
{
312+
Some(trait_ref.path.span.shrink_to_lo())
313+
} else {
314+
None
315+
};
316+
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.
306319
self.dcx().emit_err(errors::TraitFnConst {
307320
span,
308-
in_impl: self.in_trait_impl,
321+
in_impl: self.in_trait_impl.is_some(),
309322
const_context_label: self.in_const_trait_or_impl,
310323
remove_const_sugg: (
311324
self.session.source_map().span_extend_while(span, |c| c == ' ').unwrap_or(span),
@@ -314,6 +327,7 @@ impl<'a> AstValidator<'a> {
314327
None => rustc_errors::Applicability::MaybeIncorrect,
315328
},
316329
),
330+
make_impl_const_sugg,
317331
});
318332
}
319333

@@ -837,7 +851,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
837851
self_ty,
838852
items,
839853
}) => {
840-
self.with_in_trait_impl(true, Some(*constness), |this| {
854+
self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| {
841855
this.visibility_not_permitted(
842856
&item.vis,
843857
errors::VisibilityNotPermittedNote::TraitImpl,
@@ -1376,7 +1390,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13761390
self.check_nomangle_item_asciionly(item.ident, item.span);
13771391
}
13781392

1379-
if ctxt == AssocCtxt::Trait || !self.in_trait_impl {
1393+
if ctxt == AssocCtxt::Trait || self.in_trait_impl.is_none() {
13801394
self.check_defaultness(item.span, item.kind.defaultness());
13811395
}
13821396

@@ -1424,7 +1438,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14241438
);
14251439
}
14261440

1427-
if ctxt == AssocCtxt::Trait || self.in_trait_impl {
1441+
if ctxt == AssocCtxt::Trait || self.in_trait_impl.is_some() {
14281442
self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
14291443
if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
14301444
self.check_trait_fn_not_const(sig.header.constness);
@@ -1453,8 +1467,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14531467
);
14541468
self.visit_fn(kind, item.span, item.id);
14551469
}
1456-
_ => self
1457-
.with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)),
1470+
_ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)),
14581471
}
14591472
}
14601473
}
@@ -1570,7 +1583,7 @@ pub fn check_crate(
15701583
session,
15711584
features,
15721585
extern_mod: None,
1573-
in_trait_impl: false,
1586+
in_trait_impl: None,
15741587
in_const_trait_or_impl: None,
15751588
has_proc_macro_decls: false,
15761589
outer_impl_trait: None,

compiler/rustc_ast_passes/src/errors.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,12 @@ pub struct TraitFnConst {
5454
pub const_context_label: Option<Span>,
5555
#[suggestion(ast_passes_remove_const_sugg, code = "")]
5656
pub remove_const_sugg: (Span, Applicability),
57+
#[suggestion(
58+
ast_passes_make_impl_const_sugg,
59+
code = "const ",
60+
applicability = "maybe-incorrect"
61+
)]
62+
pub make_impl_const_sugg: Option<Span>,
5763
}
5864

5965
#[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
@@ -10,4 +10,8 @@ impl const Trait for () {
1010
const fn fun() {} //~ ERROR functions in trait impls cannot be declared const
1111
}
1212

13+
impl Trait for u32 {
14+
const fn fun() {} //~ ERROR functions in trait impls cannot be declared const
15+
}
16+
1317
fn main() {}

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

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,22 @@ LL | const fn fun() {}
2121
| functions in trait impls cannot be const
2222
| help: remove the `const`
2323

24-
error: aborting due to 2 previous errors
24+
error[E0379]: functions in trait impls cannot be declared const
25+
--> $DIR/trait-fn-const.rs:14:5
26+
|
27+
LL | const fn fun() {}
28+
| ^^^^^ functions in trait impls cannot be const
29+
|
30+
help: remove the `const`
31+
|
32+
LL - const fn fun() {}
33+
LL + fn fun() {}
34+
|
35+
help: and declare the impl to be const instead
36+
|
37+
LL | impl const Trait for u32 {
38+
| +++++
39+
40+
error: aborting due to 3 previous errors
2541

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

0 commit comments

Comments
 (0)