@@ -253,12 +253,65 @@ 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` is ok
289+ (
290+ BoundConstness :: Always ( span) ,
291+ TraitOrTraitImpl :: TraitImpl { constness : Const :: Yes ( _) , .. } ,
292+ ) => {
293+ if !const_trait_impl {
294+ self . sess
295+ . create_feature_err ( errors:: ConstInTrait { span } , sym:: const_trait_impl)
296+ . emit ( ) ;
297+ }
298+ return ;
299+ }
300+ ( BoundConstness :: Always ( span) , _) => span,
301+ (
302+ BoundConstness :: Maybe ( span) ,
303+ TraitOrTraitImpl :: Trait { constness_span : Some ( _) , .. } ,
304+ ) => {
305+ if !const_trait_impl {
306+ self . sess
307+ . create_feature_err ( errors:: ConstInTrait { span } , sym:: const_trait_impl)
308+ . emit ( ) ;
309+ }
310+ return ;
311+ }
312+ ( BoundConstness :: Maybe ( span) , _) => span,
259313 } ;
260314
261- let const_trait_impl = self . features . const_trait_impl ( ) ;
262315 let make_impl_const_sugg = if const_trait_impl
263316 && let TraitOrTraitImpl :: TraitImpl {
264317 constness : Const :: No ,
@@ -500,8 +553,9 @@ impl<'a> AstValidator<'a> {
500553 None => ( ) ,
501554 }
502555 match constness {
503- Const :: Yes ( span) => report_err ( span, "const" ) ,
504- Const :: No => ( ) ,
556+ BoundConstness :: Always ( span) => report_err ( span, "const" ) ,
557+ BoundConstness :: Maybe ( span) => report_err ( span, "~const" ) ,
558+ BoundConstness :: Never => ( ) ,
505559 }
506560 match ext {
507561 Extern :: None => ( ) ,
@@ -538,7 +592,9 @@ impl<'a> AstValidator<'a> {
538592 }
539593
540594 if let Some ( header) = fk. header ( ) {
541- if let Const :: Yes ( const_span) = header. constness {
595+ if let BoundConstness :: Always ( const_span) | BoundConstness :: Maybe ( const_span) =
596+ header. constness
597+ {
542598 let mut spans = variadic_spans. clone ( ) ;
543599 spans. push ( const_span) ;
544600 self . dcx ( ) . emit_err ( errors:: ConstAndCVariadic {
@@ -1347,7 +1403,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13471403
13481404 // Functions cannot both be `const async` or `const gen`
13491405 if let Some ( & FnHeader {
1350- constness : Const :: Yes ( const_span) ,
1406+ constness : BoundConstness :: Always ( const_span ) | BoundConstness :: Maybe ( const_span) ,
13511407 coroutine_kind : Some ( coroutine_kind) ,
13521408 ..
13531409 } ) = fk. header ( )
@@ -1398,14 +1454,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13981454 } ) ;
13991455 }
14001456
1401- let tilde_const_allowed =
1402- matches ! ( fk . header ( ) , Some ( FnHeader { constness : ast :: Const :: Yes ( _ ) , .. } ) )
1403- || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) )
1404- && self
1405- . outer_trait_or_trait_impl
1406- . as_ref ( )
1407- . and_then ( TraitOrTraitImpl :: constness)
1408- . is_some ( ) ;
1457+ let tilde_const_allowed = matches ! ( fk . header ( ) , Some ( FnHeader { constness : ast :: BoundConstness :: Always ( _ ) | ast :: BoundConstness :: Maybe ( _ ) , .. } ) )
1458+ // FIXME(const_trait_impls): remove this, we don't want to allow `~const` trait bounds in non-const methods
1459+ || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) )
1460+ && self
1461+ . outer_trait_or_trait_impl
1462+ . as_ref ( )
1463+ . and_then ( TraitOrTraitImpl :: constness)
1464+ . is_some ( ) ;
14091465
14101466 let disallowed = ( !tilde_const_allowed) . then ( || match fk {
14111467 FnKind :: Fn ( _, _, f) => TildeConstReason :: Function { ident : f. ident . span } ,
@@ -1474,7 +1530,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14741530 if let Some ( parent) = & self . outer_trait_or_trait_impl {
14751531 self . visibility_not_permitted ( & item. vis , errors:: VisibilityNotPermittedNote :: TraitImpl ) ;
14761532 if let AssocItemKind :: Fn ( box Fn { sig, .. } ) = & item. kind {
1477- self . check_trait_fn_not_const ( sig. header . constness , parent) ;
1533+ self . check_trait_fn_not_const ( sig. header . constness , sig . span , parent) ;
14781534 }
14791535 }
14801536
@@ -1489,7 +1545,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14891545 AssocItemKind :: Fn ( func)
14901546 if parent_is_const
14911547 || ctxt == AssocCtxt :: Trait
1492- || matches ! ( func. sig. header. constness, Const :: Yes ( _ ) ) =>
1548+ || ! matches ! ( func. sig. header. constness, ast :: BoundConstness :: Never ) =>
14931549 {
14941550 self . visit_attrs_vis_ident ( & item. attrs , & item. vis , & func. ident ) ;
14951551 let kind = FnKind :: Fn ( FnCtxt :: Assoc ( ctxt) , & item. vis , & * func) ;
0 commit comments