diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 45357aca53390..c618953461cf6 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1241,11 +1241,13 @@ impl<'hir> LoweringContext<'_, 'hir> { coroutine_kind: Option, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header); + // Don't pass along the user-provided constness of trait associated functions; we don't want to + // synthesize a host effect param for them. We reject `const` on them during AST validation. + let constness = if kind == FnDeclKind::Inherent { sig.header.constness } else { Const::No }; let itctx = ImplTraitContext::Universal; - let (generics, decl) = - self.lower_generics(generics, sig.header.constness, id, &itctx, |this| { - this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) - }); + let (generics, decl) = self.lower_generics(generics, constness, id, &itctx, |this| { + this.lower_fn_decl(&sig.decl, id, sig.span, kind, coroutine_kind) + }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl index b5612c1820d0c..feea02c679ce1 100644 --- a/compiler/rustc_ast_passes/messages.ftl +++ b/compiler/rustc_ast_passes/messages.ftl @@ -233,8 +233,21 @@ ast_passes_tilde_const_disallowed = `~const` is not allowed here .item = this item cannot have `~const` trait bounds ast_passes_trait_fn_const = - functions in traits cannot be declared const - .label = functions in traits cannot be const + functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be declared const + .label = functions in {$in_impl -> + [true] trait impls + *[false] traits + } cannot be const + .const_context_label = this declares all associated functions implicitly const + .remove_const_sugg = remove the `const`{$requires_multiple_changes -> + [true] {" ..."} + *[false] {""} + } + .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 diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs index bc5cf463f1204..b69d4cccaf04f 100644 --- a/compiler/rustc_ast_passes/src/ast_validation.rs +++ b/compiler/rustc_ast_passes/src/ast_validation.rs @@ -46,6 +46,21 @@ enum DisallowTildeConstContext<'a> { Item, } +enum TraitOrTraitImpl<'a> { + Trait { span: Span, constness: Option }, + TraitImpl { constness: Const, polarity: ImplPolarity, trait_ref: &'a TraitRef }, +} + +impl<'a> TraitOrTraitImpl<'a> { + fn constness(&self) -> Option { + match self { + Self::Trait { constness: Some(span), .. } + | Self::TraitImpl { constness: Const::Yes(span), .. } => Some(*span), + _ => None, + } + } +} + struct AstValidator<'a> { session: &'a Session, features: &'a Features, @@ -53,11 +68,7 @@ struct AstValidator<'a> { /// The span of the `extern` in an `extern { ... }` block, if any. extern_mod: Option<&'a Item>, - /// Are we inside a trait impl? - in_trait_impl: bool, - - /// Are we inside a const trait defn or impl? - in_const_trait_or_impl: bool, + outer_trait_or_trait_impl: Option>, has_proc_macro_decls: bool, @@ -78,24 +89,28 @@ struct AstValidator<'a> { impl<'a> AstValidator<'a> { fn with_in_trait_impl( &mut self, - is_in: bool, - constness: Option, + trait_: Option<(Const, ImplPolarity, &'a TraitRef)>, f: impl FnOnce(&mut Self), ) { - let old = mem::replace(&mut self.in_trait_impl, is_in); - let old_const = mem::replace( - &mut self.in_const_trait_or_impl, - matches!(constness, Some(Const::Yes(_))), + let old = mem::replace( + &mut self.outer_trait_or_trait_impl, + trait_.map(|(constness, polarity, trait_ref)| TraitOrTraitImpl::TraitImpl { + constness, + polarity, + trait_ref, + }), ); f(self); - self.in_trait_impl = old; - self.in_const_trait_or_impl = old_const; + self.outer_trait_or_trait_impl = old; } - fn with_in_trait(&mut self, is_const: bool, f: impl FnOnce(&mut Self)) { - let old = mem::replace(&mut self.in_const_trait_or_impl, is_const); + fn with_in_trait(&mut self, span: Span, constness: Option, f: impl FnOnce(&mut Self)) { + let old = mem::replace( + &mut self.outer_trait_or_trait_impl, + Some(TraitOrTraitImpl::Trait { span, constness }), + ); f(self); - self.in_const_trait_or_impl = old; + self.outer_trait_or_trait_impl = old; } fn with_banned_impl_trait(&mut self, f: impl FnOnce(&mut Self)) { @@ -291,10 +306,48 @@ impl<'a> AstValidator<'a> { } } - fn check_trait_fn_not_const(&self, constness: Const) { - if let Const::Yes(span) = constness { - self.dcx().emit_err(errors::TraitFnConst { span }); - } + fn check_trait_fn_not_const(&self, constness: Const, parent: &TraitOrTraitImpl<'a>) { + let Const::Yes(span) = constness else { + return; + }; + + let make_impl_const_sugg = if self.features.const_trait_impl + && let TraitOrTraitImpl::TraitImpl { + constness: Const::No, + polarity: ImplPolarity::Positive, + trait_ref, + } = parent + { + Some(trait_ref.path.span.shrink_to_lo()) + } else { + None + }; + + let make_trait_const_sugg = if self.features.const_trait_impl + && let TraitOrTraitImpl::Trait { span, constness: None } = parent + { + Some(span.shrink_to_lo()) + } else { + None + }; + + let parent_constness = parent.constness(); + self.dcx().emit_err(errors::TraitFnConst { + span, + in_impl: matches!(parent, TraitOrTraitImpl::TraitImpl { .. }), + const_context_label: parent_constness, + remove_const_sugg: ( + self.session.source_map().span_extend_while(span, |c| c == ' ').unwrap_or(span), + match parent_constness { + Some(_) => rustc_errors::Applicability::MachineApplicable, + None => rustc_errors::Applicability::MaybeIncorrect, + }, + ), + requires_multiple_changes: make_impl_const_sugg.is_some() + || make_trait_const_sugg.is_some(), + make_impl_const_sugg, + make_trait_const_sugg, + }); } fn check_fn_decl(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) { @@ -817,7 +870,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self_ty, items, }) => { - self.with_in_trait_impl(true, Some(*constness), |this| { + self.with_in_trait_impl(Some((*constness, *polarity, t)), |this| { this.visibility_not_permitted( &item.vis, errors::VisibilityNotPermittedNote::TraitImpl, @@ -963,8 +1016,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { } } ItemKind::Trait(box Trait { is_auto, generics, bounds, items, .. }) => { - let is_const_trait = attr::contains_name(&item.attrs, sym::const_trait); - self.with_in_trait(is_const_trait, |this| { + let is_const_trait = + attr::find_by_name(&item.attrs, sym::const_trait).map(|attr| attr.span); + 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); @@ -977,8 +1031,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> { // context for the supertraits. this.visit_vis(&item.vis); this.visit_ident(item.ident); - let disallowed = - (!is_const_trait).then(|| DisallowTildeConstContext::Trait(item.span)); + let disallowed = is_const_trait + .is_none() + .then(|| DisallowTildeConstContext::Trait(item.span)); this.with_tilde_const(disallowed, |this| { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits) @@ -1342,7 +1397,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> { let tilde_const_allowed = matches!(fk.header(), Some(FnHeader { constness: ast::Const::Yes(_), .. })) - || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_)) if self.in_const_trait_or_impl); + || matches!(fk.ctxt(), Some(FnCtxt::Assoc(_))) + && self + .outer_trait_or_trait_impl + .as_ref() + .and_then(TraitOrTraitImpl::constness) + .is_some(); let disallowed = (!tilde_const_allowed).then(|| DisallowTildeConstContext::Fn(fk)); self.with_tilde_const(disallowed, |this| visit::walk_fn(this, fk)); @@ -1353,7 +1413,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { self.check_nomangle_item_asciionly(item.ident, item.span); } - if ctxt == AssocCtxt::Trait || !self.in_trait_impl { + if ctxt == AssocCtxt::Trait || self.outer_trait_or_trait_impl.is_none() { self.check_defaultness(item.span, item.kind.defaultness()); } @@ -1401,10 +1461,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ); } - if ctxt == AssocCtxt::Trait || self.in_trait_impl { + if let Some(parent) = &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); + self.check_trait_fn_not_const(sig.header.constness, parent); } } @@ -1414,7 +1474,11 @@ impl<'a> Visitor<'a> for AstValidator<'a> { match &item.kind { AssocItemKind::Fn(box Fn { sig, generics, body, .. }) - if self.in_const_trait_or_impl + if self + .outer_trait_or_trait_impl + .as_ref() + .and_then(TraitOrTraitImpl::constness) + .is_some() || ctxt == AssocCtxt::Trait || matches!(sig.header.constness, Const::Yes(_)) => { @@ -1430,8 +1494,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> { ); self.visit_fn(kind, item.span, item.id); } - _ => self - .with_in_trait_impl(false, None, |this| visit::walk_assoc_item(this, item, ctxt)), + _ => self.with_in_trait_impl(None, |this| visit::walk_assoc_item(this, item, ctxt)), } } } @@ -1547,8 +1610,7 @@ pub fn check_crate( session, features, extern_mod: None, - in_trait_impl: false, - in_const_trait_or_impl: false, + outer_trait_or_trait_impl: None, has_proc_macro_decls: false, outer_impl_trait: None, disallow_tilde_const: Some(DisallowTildeConstContext::Item), diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs index 0cec4374be2ee..42ada39f51589 100644 --- a/compiler/rustc_ast_passes/src/errors.rs +++ b/compiler/rustc_ast_passes/src/errors.rs @@ -1,7 +1,7 @@ //! Errors emitted by ast_passes. use rustc_ast::ParamKindOrd; -use rustc_errors::AddToDiagnostic; +use rustc_errors::{AddToDiagnostic, Applicability}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_span::{symbol::Ident, Span, Symbol}; @@ -49,6 +49,24 @@ pub struct TraitFnConst { #[primary_span] #[label] pub span: Span, + pub in_impl: bool, + #[label(ast_passes_const_context_label)] + pub const_context_label: Option, + #[suggestion(ast_passes_remove_const_sugg, code = "")] + pub remove_const_sugg: (Span, Applicability), + pub requires_multiple_changes: bool, + #[suggestion( + ast_passes_make_impl_const_sugg, + code = "const ", + applicability = "maybe-incorrect" + )] + pub make_impl_const_sugg: Option, + #[suggestion( + ast_passes_make_trait_const_sugg, + code = "#[const_trait]\n", + applicability = "maybe-incorrect" + )] + pub make_trait_const_sugg: Option, } #[derive(Diagnostic)] diff --git a/compiler/rustc_error_codes/src/error_codes/E0379.md b/compiler/rustc_error_codes/src/error_codes/E0379.md index ab438e4144712..35f546cfdb737 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0379.md +++ b/compiler/rustc_error_codes/src/error_codes/E0379.md @@ -6,6 +6,10 @@ Erroneous code example: trait Foo { const fn bar() -> u32; // error! } + +impl Foo for () { + const fn bar() -> u32 { 0 } // error! +} ``` Trait methods cannot be declared `const` by design. For more information, see diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 5abc752309ad5..b44b2eefabbc6 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -315,7 +315,10 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { if is_host_effect { if let Some(idx) = host_effect_index { - bug!("parent also has host effect param? index: {idx}, def: {def_id:?}"); + tcx.dcx().span_delayed_bug( + param.span, + format!("parent also has host effect param? index: {idx}, def: {def_id:?}"), + ); } host_effect_index = Some(index as usize); diff --git a/tests/ui/consts/const-fn-mismatch.rs b/tests/ui/consts/const-fn-mismatch.rs index 3107b8128e602..b17e4cedd3ff6 100644 --- a/tests/ui/consts/const-fn-mismatch.rs +++ b/tests/ui/consts/const-fn-mismatch.rs @@ -9,7 +9,7 @@ trait Foo { impl Foo for u32 { const fn f() -> u32 { - //~^ ERROR functions in traits cannot be declared const + //~^ ERROR functions in trait impls cannot be declared const 22 } } diff --git a/tests/ui/consts/const-fn-mismatch.stderr b/tests/ui/consts/const-fn-mismatch.stderr index beaf52c0cfb36..9e7d93b0c97bb 100644 --- a/tests/ui/consts/const-fn-mismatch.stderr +++ b/tests/ui/consts/const-fn-mismatch.stderr @@ -1,8 +1,11 @@ -error[E0379]: functions in traits cannot be declared const +error[E0379]: functions in trait impls cannot be declared const --> $DIR/const-fn-mismatch.rs:11:5 | LL | const fn f() -> u32 { - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` error: aborting due to 1 previous error diff --git a/tests/ui/consts/const-fn-not-in-trait.stderr b/tests/ui/consts/const-fn-not-in-trait.stderr index 5d364eb882dba..04430610ad00c 100644 --- a/tests/ui/consts/const-fn-not-in-trait.stderr +++ b/tests/ui/consts/const-fn-not-in-trait.stderr @@ -2,13 +2,19 @@ error[E0379]: functions in traits cannot be declared const --> $DIR/const-fn-not-in-trait.rs:5:5 | LL | const fn f() -> u32; - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` error[E0379]: functions in traits cannot be declared const --> $DIR/const-fn-not-in-trait.rs:7:5 | LL | const fn g() -> u32 { - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` error: aborting due to 2 previous errors diff --git a/tests/ui/consts/issue-54954.stderr b/tests/ui/consts/issue-54954.stderr index b0701bab793c5..03c47030c0e3f 100644 --- a/tests/ui/consts/issue-54954.stderr +++ b/tests/ui/consts/issue-54954.stderr @@ -2,7 +2,10 @@ error[E0379]: functions in traits cannot be declared const --> $DIR/issue-54954.rs:5:5 | LL | const fn const_val() -> usize { - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` error[E0790]: cannot call associated function on trait without specifying the corresponding `impl` type --> $DIR/issue-54954.rs:1:24 diff --git a/tests/ui/feature-gates/feature-gate-min_const_fn.rs b/tests/ui/feature-gates/feature-gate-min_const_fn.rs index 8f9b433009d3c..3d61a9eb93777 100644 --- a/tests/ui/feature-gates/feature-gate-min_const_fn.rs +++ b/tests/ui/feature-gates/feature-gate-min_const_fn.rs @@ -8,7 +8,7 @@ trait Foo { } impl Foo for u32 { - const fn foo() -> u32 { 0 } //~ ERROR functions in traits cannot be declared const + const fn foo() -> u32 { 0 } //~ ERROR functions in trait impls cannot be declared const } trait Bar {} diff --git a/tests/ui/feature-gates/feature-gate-min_const_fn.stderr b/tests/ui/feature-gates/feature-gate-min_const_fn.stderr index d7a58591364ed..0b16f9abb7071 100644 --- a/tests/ui/feature-gates/feature-gate-min_const_fn.stderr +++ b/tests/ui/feature-gates/feature-gate-min_const_fn.stderr @@ -2,19 +2,28 @@ error[E0379]: functions in traits cannot be declared const --> $DIR/feature-gate-min_const_fn.rs:6:5 | LL | const fn foo() -> u32; - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` error[E0379]: functions in traits cannot be declared const --> $DIR/feature-gate-min_const_fn.rs:7:5 | LL | const fn bar() -> u32 { 0 } - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` -error[E0379]: functions in traits cannot be declared const +error[E0379]: functions in trait impls cannot be declared const --> $DIR/feature-gate-min_const_fn.rs:11:5 | LL | const fn foo() -> u32 { 0 } - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` error: aborting due to 3 previous errors diff --git a/tests/ui/mismatched_types/const-fn-in-trait.stderr b/tests/ui/mismatched_types/const-fn-in-trait.stderr index 7d1fbe45c5302..06976933b2f94 100644 --- a/tests/ui/mismatched_types/const-fn-in-trait.stderr +++ b/tests/ui/mismatched_types/const-fn-in-trait.stderr @@ -2,13 +2,19 @@ error[E0379]: functions in traits cannot be declared const --> $DIR/const-fn-in-trait.rs:3:5 | LL | const fn g(); - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` -error[E0379]: functions in traits cannot be declared const +error[E0379]: functions in trait impls cannot be declared const --> $DIR/const-fn-in-trait.rs:7:5 | LL | const fn f() -> u32 { 22 } - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` error: aborting due to 2 previous errors diff --git a/tests/ui/parser/fn-header-semantic-fail.rs b/tests/ui/parser/fn-header-semantic-fail.rs index f8b58cad7c144..f01e1c2277c6f 100644 --- a/tests/ui/parser/fn-header-semantic-fail.rs +++ b/tests/ui/parser/fn-header-semantic-fail.rs @@ -26,10 +26,10 @@ fn main() { impl X for Y { async fn ft1() {} // OK. unsafe fn ft2() {} // OK. - const fn ft3() {} //~ ERROR functions in traits cannot be declared const + const fn ft3() {} //~ ERROR functions in trait impls cannot be declared const extern "C" fn ft4() {} const async unsafe extern "C" fn ft5() {} - //~^ ERROR functions in traits cannot be declared const + //~^ ERROR functions in trait impls cannot be declared const //~| ERROR functions cannot be both `const` and `async` } diff --git a/tests/ui/parser/fn-header-semantic-fail.stderr b/tests/ui/parser/fn-header-semantic-fail.stderr index cdf01e0c5df64..696d8e01b6387 100644 --- a/tests/ui/parser/fn-header-semantic-fail.stderr +++ b/tests/ui/parser/fn-header-semantic-fail.stderr @@ -11,13 +11,19 @@ error[E0379]: functions in traits cannot be declared const --> $DIR/fn-header-semantic-fail.rs:18:9 | LL | const fn ft3(); - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` error[E0379]: functions in traits cannot be declared const --> $DIR/fn-header-semantic-fail.rs:20:9 | LL | const async unsafe extern "C" fn ft5(); - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:20:9 @@ -28,17 +34,23 @@ LL | const async unsafe extern "C" fn ft5(); | | `async` because of this | `const` because of this -error[E0379]: functions in traits cannot be declared const +error[E0379]: functions in trait impls cannot be declared const --> $DIR/fn-header-semantic-fail.rs:29:9 | LL | const fn ft3() {} - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` -error[E0379]: functions in traits cannot be declared const +error[E0379]: functions in trait impls cannot be declared const --> $DIR/fn-header-semantic-fail.rs:31:9 | LL | const async unsafe extern "C" fn ft5() {} - | ^^^^^ functions in traits cannot be const + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` error: functions cannot be both `const` and `async` --> $DIR/fn-header-semantic-fail.rs:31:9 diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs new file mode 100644 index 0000000000000..891e87d3b97d4 --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.rs @@ -0,0 +1,21 @@ +// Regression test for issue #113378. +#![feature(const_trait_impl, effects)] + +#[const_trait] +trait Trait { + const fn fun(); //~ ERROR functions in traits cannot be declared const +} + +impl const Trait for () { + const fn fun() {} //~ ERROR functions in trait impls cannot be declared const +} + +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() {} diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr new file mode 100644 index 0000000000000..4d0b03046d27d --- /dev/null +++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/trait-fn-const.stderr @@ -0,0 +1,59 @@ +error[E0379]: functions in traits cannot be declared const + --> $DIR/trait-fn-const.rs:6:5 + | +LL | #[const_trait] + | -------------- this declares all associated functions implicitly const +LL | trait Trait { +LL | const fn fun(); + | ^^^^^- + | | + | functions in traits cannot be const + | help: remove the `const` + +error[E0379]: functions in trait impls cannot be declared const + --> $DIR/trait-fn-const.rs:10:5 + | +LL | impl const Trait for () { + | ----- this declares all associated functions implicitly const +LL | const fn fun() {} + | ^^^^^- + | | + | functions in trait impls cannot be const + | help: remove the `const` + +error[E0379]: functions in trait impls cannot be declared const + --> $DIR/trait-fn-const.rs:14:5 + | +LL | const fn fun() {} + | ^^^^^ functions in trait impls cannot be const + | +help: remove the `const` ... + | +LL - const fn fun() {} +LL + fn fun() {} + | +help: ... and declare the impl to be const instead + | +LL | impl const Trait for u32 { + | +++++ + +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`.