@@ -253,12 +253,55 @@ impl<'a> AstValidator<'a> {
253
253
}
254
254
}
255
255
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,
259
303
} ;
260
304
261
- let const_trait_impl = self . features . const_trait_impl ( ) ;
262
305
let make_impl_const_sugg = if const_trait_impl
263
306
&& let TraitOrTraitImpl :: TraitImpl {
264
307
constness : Const :: No ,
@@ -500,8 +543,9 @@ impl<'a> AstValidator<'a> {
500
543
None => ( ) ,
501
544
}
502
545
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 => ( ) ,
505
549
}
506
550
match ext {
507
551
Extern :: None => ( ) ,
@@ -538,7 +582,9 @@ impl<'a> AstValidator<'a> {
538
582
}
539
583
540
584
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
+ {
542
588
let mut spans = variadic_spans. clone ( ) ;
543
589
spans. push ( const_span) ;
544
590
self . dcx ( ) . emit_err ( errors:: ConstAndCVariadic {
@@ -1347,7 +1393,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1347
1393
1348
1394
// Functions cannot both be `const async` or `const gen`
1349
1395
if let Some ( & FnHeader {
1350
- constness : Const :: Yes ( const_span) ,
1396
+ constness : BoundConstness :: Always ( const_span ) | BoundConstness :: Maybe ( const_span) ,
1351
1397
coroutine_kind : Some ( coroutine_kind) ,
1352
1398
..
1353
1399
} ) = fk. header ( )
@@ -1398,14 +1444,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1398
1444
} ) ;
1399
1445
}
1400
1446
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 ( ) ;
1447
+ let tilde_const_allowed = matches ! ( fk . header ( ) , Some ( FnHeader { constness : ast :: BoundConstness :: Always ( _ ) | ast :: BoundConstness :: Maybe ( _ ) , .. } ) )
1448
+ // FIXME(const_trait_impls): remove this, we don't want to allow `~const` trait bounds in non-const methods
1449
+ || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) )
1450
+ && self
1451
+ . outer_trait_or_trait_impl
1452
+ . as_ref ( )
1453
+ . and_then ( TraitOrTraitImpl :: constness)
1454
+ . is_some ( ) ;
1409
1455
1410
1456
let disallowed = ( !tilde_const_allowed) . then ( || match fk {
1411
1457
FnKind :: Fn ( _, _, f) => TildeConstReason :: Function { ident : f. ident . span } ,
@@ -1474,7 +1520,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1474
1520
if let Some ( parent) = & self . outer_trait_or_trait_impl {
1475
1521
self . visibility_not_permitted ( & item. vis , errors:: VisibilityNotPermittedNote :: TraitImpl ) ;
1476
1522
if let AssocItemKind :: Fn ( box Fn { sig, .. } ) = & item. kind {
1477
- self . check_trait_fn_not_const ( sig. header . constness , parent) ;
1523
+ self . check_trait_fn_not_const ( sig. header . constness , sig . span , parent) ;
1478
1524
}
1479
1525
}
1480
1526
@@ -1489,7 +1535,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1489
1535
AssocItemKind :: Fn ( func)
1490
1536
if parent_is_const
1491
1537
|| ctxt == AssocCtxt :: Trait
1492
- || matches ! ( func. sig. header. constness, Const :: Yes ( _ ) ) =>
1538
+ || ! matches ! ( func. sig. header. constness, ast :: BoundConstness :: Never ) =>
1493
1539
{
1494
1540
self . visit_attrs_vis_ident ( & item. attrs , & item. vis , & func. ident ) ;
1495
1541
let kind = FnKind :: Fn ( FnCtxt :: Assoc ( ctxt) , & item. vis , & * func) ;
0 commit comments