@@ -253,12 +253,55 @@ impl<'a> AstValidator<'a> {
253253 }
254254 }
255255
256- fn check_trait_fn_not_const ( & self , constness : Const , parent : & TraitOrTraitImpl ) {
257- let Const :: Yes ( span) = constness else {
258- return ;
256+ fn check_trait_fn_not_const (
257+ & self ,
258+ constness : BoundConstness ,
259+ sig_span : Span ,
260+ parent : & TraitOrTraitImpl ,
261+ ) {
262+ let const_trait_impl = self . features . const_trait_impl ( ) ;
263+
264+ let span = match ( constness, parent) {
265+ ( BoundConstness :: Never , toti) => {
266+ // only `(const)` or `const` fn are allowed in traits or impls respectively.
267+ // But for bootstrap purposes we allow the stage1 std and the stage0 std to be the same.
268+ if toti. constness ( ) . is_some ( ) && !self . features . staged_api ( ) {
269+ // FIXME(const_trait_impls): allow non-const fns
270+ self . dcx ( )
271+ . struct_span_err (
272+ sig_span. shrink_to_lo ( ) ,
273+ "non-const fn in const traits are not supported yet" ,
274+ )
275+ . with_span_suggestion (
276+ sig_span. shrink_to_lo ( ) ,
277+ "mark the function as const" ,
278+ match toti {
279+ TraitOrTraitImpl :: Trait { .. } => "(const) " ,
280+ TraitOrTraitImpl :: TraitImpl { .. } => "const " ,
281+ } ,
282+ rustc_errors:: Applicability :: MachineApplicable ,
283+ )
284+ . emit ( ) ;
285+ }
286+ return ;
287+ }
288+ // `(const) fn` in `const Trait` or `impl const Trait` is ok
289+ ( BoundConstness :: Always ( span) , _) => span,
290+ (
291+ BoundConstness :: Maybe ( span) ,
292+ TraitOrTraitImpl :: Trait { constness_span : Some ( _) , .. }
293+ | TraitOrTraitImpl :: TraitImpl { constness : Const :: Yes ( _) , .. } ,
294+ ) => {
295+ if !const_trait_impl {
296+ self . sess
297+ . create_feature_err ( errors:: ConstInTrait { span } , sym:: const_trait_impl)
298+ . emit ( ) ;
299+ }
300+ return ;
301+ }
302+ ( BoundConstness :: Maybe ( span) , _) => span,
259303 } ;
260304
261- let const_trait_impl = self . features . const_trait_impl ( ) ;
262305 let make_impl_const_sugg = if const_trait_impl
263306 && let TraitOrTraitImpl :: TraitImpl {
264307 constness : Const :: No ,
@@ -500,8 +543,9 @@ impl<'a> AstValidator<'a> {
500543 None => ( ) ,
501544 }
502545 match constness {
503- Const :: Yes ( span) => report_err ( span, "const" ) ,
504- Const :: No => ( ) ,
546+ BoundConstness :: Always ( span) => report_err ( span, "const" ) ,
547+ BoundConstness :: Maybe ( span) => report_err ( span, "~const" ) ,
548+ BoundConstness :: Never => ( ) ,
505549 }
506550 match ext {
507551 Extern :: None => ( ) ,
@@ -538,7 +582,9 @@ impl<'a> AstValidator<'a> {
538582 }
539583
540584 if let Some ( header) = fk. header ( ) {
541- if let Const :: Yes ( const_span) = header. constness {
585+ if let BoundConstness :: Always ( const_span) | BoundConstness :: Maybe ( const_span) =
586+ header. constness
587+ {
542588 let mut spans = variadic_spans. clone ( ) ;
543589 spans. push ( const_span) ;
544590 self . dcx ( ) . emit_err ( errors:: ConstAndCVariadic {
@@ -1348,7 +1394,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13481394
13491395 // Functions cannot both be `const async` or `const gen`
13501396 if let Some ( & FnHeader {
1351- constness : Const :: Yes ( const_span) ,
1397+ constness : BoundConstness :: Always ( const_span ) | BoundConstness :: Maybe ( const_span) ,
13521398 coroutine_kind : Some ( coroutine_kind) ,
13531399 ..
13541400 } ) = fk. header ( )
@@ -1399,14 +1445,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13991445 } ) ;
14001446 }
14011447
1402- let tilde_const_allowed =
1403- matches ! ( fk . header ( ) , Some ( FnHeader { constness : ast :: Const :: Yes ( _ ) , .. } ) )
1404- || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) )
1405- && self
1406- . outer_trait_or_trait_impl
1407- . as_ref ( )
1408- . and_then ( TraitOrTraitImpl :: constness)
1409- . is_some ( ) ;
1448+ let tilde_const_allowed = matches ! ( fk . header ( ) , Some ( FnHeader { constness : ast :: BoundConstness :: Always ( _ ) | ast :: BoundConstness :: Maybe ( _ ) , .. } ) )
1449+ // FIXME(const_trait_impls): remove this, we don't want to allow `~const` trait bounds in non-const methods
1450+ || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) )
1451+ && self
1452+ . outer_trait_or_trait_impl
1453+ . as_ref ( )
1454+ . and_then ( TraitOrTraitImpl :: constness)
1455+ . is_some ( ) ;
14101456
14111457 let disallowed = ( !tilde_const_allowed) . then ( || match fk {
14121458 FnKind :: Fn ( _, _, f) => TildeConstReason :: Function { ident : f. ident . span } ,
@@ -1475,7 +1521,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14751521 if let Some ( parent) = & self . outer_trait_or_trait_impl {
14761522 self . visibility_not_permitted ( & item. vis , errors:: VisibilityNotPermittedNote :: TraitImpl ) ;
14771523 if let AssocItemKind :: Fn ( box Fn { sig, .. } ) = & item. kind {
1478- self . check_trait_fn_not_const ( sig. header . constness , parent) ;
1524+ self . check_trait_fn_not_const ( sig. header . constness , sig . span , parent) ;
14791525 }
14801526 }
14811527
@@ -1490,7 +1536,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14901536 AssocItemKind :: Fn ( func)
14911537 if parent_is_const
14921538 || ctxt == AssocCtxt :: Trait
1493- || matches ! ( func. sig. header. constness, Const :: Yes ( _ ) ) =>
1539+ || ! matches ! ( func. sig. header. constness, ast :: BoundConstness :: Never ) =>
14941540 {
14951541 self . visit_attrs_vis_ident ( & item. attrs , & item. vis , & func. ident ) ;
14961542 let kind = FnKind :: Fn ( FnCtxt :: Assoc ( ctxt) , & item. vis , & * func) ;
0 commit comments