@@ -253,12 +253,65 @@ 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` 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,
259
313
} ;
260
314
261
- let const_trait_impl = self . features . const_trait_impl ( ) ;
262
315
let make_impl_const_sugg = if const_trait_impl
263
316
&& let TraitOrTraitImpl :: TraitImpl {
264
317
constness : Const :: No ,
@@ -500,8 +553,9 @@ impl<'a> AstValidator<'a> {
500
553
None => ( ) ,
501
554
}
502
555
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 => ( ) ,
505
559
}
506
560
match ext {
507
561
Extern :: None => ( ) ,
@@ -538,7 +592,9 @@ impl<'a> AstValidator<'a> {
538
592
}
539
593
540
594
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
+ {
542
598
let mut spans = variadic_spans. clone ( ) ;
543
599
spans. push ( const_span) ;
544
600
self . dcx ( ) . emit_err ( errors:: ConstAndCVariadic {
@@ -1347,7 +1403,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1347
1403
1348
1404
// Functions cannot both be `const async` or `const gen`
1349
1405
if let Some ( & FnHeader {
1350
- constness : Const :: Yes ( const_span) ,
1406
+ constness : BoundConstness :: Always ( const_span ) | BoundConstness :: Maybe ( const_span) ,
1351
1407
coroutine_kind : Some ( coroutine_kind) ,
1352
1408
..
1353
1409
} ) = fk. header ( )
@@ -1398,14 +1454,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1398
1454
} ) ;
1399
1455
}
1400
1456
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 ( ) ;
1409
1465
1410
1466
let disallowed = ( !tilde_const_allowed) . then ( || match fk {
1411
1467
FnKind :: Fn ( _, _, f) => TildeConstReason :: Function { ident : f. ident . span } ,
@@ -1474,7 +1530,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1474
1530
if let Some ( parent) = & self . outer_trait_or_trait_impl {
1475
1531
self . visibility_not_permitted ( & item. vis , errors:: VisibilityNotPermittedNote :: TraitImpl ) ;
1476
1532
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) ;
1478
1534
}
1479
1535
}
1480
1536
@@ -1489,7 +1545,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1489
1545
AssocItemKind :: Fn ( func)
1490
1546
if parent_is_const
1491
1547
|| ctxt == AssocCtxt :: Trait
1492
- || matches ! ( func. sig. header. constness, Const :: Yes ( _ ) ) =>
1548
+ || ! matches ! ( func. sig. header. constness, ast :: BoundConstness :: Never ) =>
1493
1549
{
1494
1550
self . visit_attrs_vis_ident ( & item. attrs , & item. vis , & func. ident ) ;
1495
1551
let kind = FnKind :: Fn ( FnCtxt :: Assoc ( ctxt) , & item. vis , & * func) ;
0 commit comments