@@ -57,7 +57,8 @@ struct AstValidator<'a> {
57
57
in_trait_impl : bool ,
58
58
59
59
/// Are we inside a const trait defn or impl?
60
- in_const_trait_or_impl : bool ,
60
+ // FIXME(fmease): docs, var name
61
+ in_const_trait_or_impl : Option < Span > ,
61
62
62
63
has_proc_macro_decls : bool ,
63
64
@@ -85,14 +86,17 @@ impl<'a> AstValidator<'a> {
85
86
let old = mem:: replace ( & mut self . in_trait_impl , is_in) ;
86
87
let old_const = mem:: replace (
87
88
& mut self . in_const_trait_or_impl ,
88
- matches ! ( constness, Some ( Const :: Yes ( _) ) ) ,
89
+ match constness {
90
+ Some ( Const :: Yes ( span) ) => Some ( span) ,
91
+ _ => None ,
92
+ } ,
89
93
) ;
90
94
f ( self ) ;
91
95
self . in_trait_impl = old;
92
96
self . in_const_trait_or_impl = old_const;
93
97
}
94
98
95
- fn with_in_trait ( & mut self , is_const : bool , f : impl FnOnce ( & mut Self ) ) {
99
+ fn with_in_trait ( & mut self , is_const : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
96
100
let old = mem:: replace ( & mut self . in_const_trait_or_impl , is_const) ;
97
101
f ( self ) ;
98
102
self . in_const_trait_or_impl = old;
@@ -292,9 +296,18 @@ impl<'a> AstValidator<'a> {
292
296
}
293
297
294
298
fn check_trait_fn_not_const ( & self , constness : Const ) {
295
- if let Const :: Yes ( span) = constness {
296
- self . dcx ( ) . emit_err ( errors:: TraitFnConst { span, in_impl : self . in_trait_impl } ) ;
297
- }
299
+ let Const :: Yes ( span) = constness else {
300
+ return ;
301
+ } ;
302
+
303
+ // FIXME(const_trait_impl): If the trait or impl is not const and feature `const_trait_impl`
304
+ // is enabled, provide a structured suggestion to make the trait (impl) const.
305
+ self . dcx ( ) . emit_err ( errors:: TraitFnConst {
306
+ span,
307
+ in_impl : self . in_trait_impl ,
308
+ const_context_label : self . in_const_trait_or_impl ,
309
+ remove_const_sugg : self . in_const_trait_or_impl . map ( |_| span) ,
310
+ } ) ;
298
311
}
299
312
300
313
fn check_fn_decl ( & self , fn_decl : & FnDecl , self_semantic : SelfSemantic ) {
@@ -963,7 +976,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
963
976
}
964
977
}
965
978
ItemKind :: Trait ( box Trait { is_auto, generics, bounds, items, .. } ) => {
966
- let is_const_trait = attr:: contains_name ( & item. attrs , sym:: const_trait) ;
979
+ let is_const_trait =
980
+ attr:: find_by_name ( & item. attrs , sym:: const_trait) . map ( |attr| attr. span ) ;
967
981
self . with_in_trait ( is_const_trait, |this| {
968
982
if * is_auto == IsAuto :: Yes {
969
983
// Auto traits cannot have generics, super traits nor contain items.
@@ -977,8 +991,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
977
991
// context for the supertraits.
978
992
this. visit_vis ( & item. vis ) ;
979
993
this. visit_ident ( item. ident ) ;
980
- let disallowed =
981
- ( !is_const_trait) . then ( || DisallowTildeConstContext :: Trait ( item. span ) ) ;
994
+ let disallowed = is_const_trait
995
+ . is_none ( )
996
+ . then ( || DisallowTildeConstContext :: Trait ( item. span ) ) ;
982
997
this. with_tilde_const ( disallowed, |this| {
983
998
this. visit_generics ( generics) ;
984
999
walk_list ! ( this, visit_param_bound, bounds, BoundKind :: SuperTraits )
@@ -1340,9 +1355,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1340
1355
} ) ;
1341
1356
}
1342
1357
1343
- let tilde_const_allowed =
1344
- matches ! ( fk. header( ) , Some ( FnHeader { constness: ast:: Const :: Yes ( _) , .. } ) )
1345
- || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) if self . in_const_trait_or_impl) ;
1358
+ let tilde_const_allowed = matches ! (
1359
+ fk. header( ) ,
1360
+ Some ( FnHeader { constness: ast:: Const :: Yes ( _) , .. } )
1361
+ ) || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) if self . in_const_trait_or_impl. is_some( ) ) ;
1346
1362
1347
1363
let disallowed = ( !tilde_const_allowed) . then ( || DisallowTildeConstContext :: Fn ( fk) ) ;
1348
1364
self . with_tilde_const ( disallowed, |this| visit:: walk_fn ( this, fk) ) ;
@@ -1414,7 +1430,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1414
1430
1415
1431
match & item. kind {
1416
1432
AssocItemKind :: Fn ( box Fn { sig, generics, body, .. } )
1417
- if self . in_const_trait_or_impl
1433
+ if self . in_const_trait_or_impl . is_some ( )
1418
1434
|| ctxt == AssocCtxt :: Trait
1419
1435
|| matches ! ( sig. header. constness, Const :: Yes ( _) ) =>
1420
1436
{
@@ -1548,7 +1564,7 @@ pub fn check_crate(
1548
1564
features,
1549
1565
extern_mod : None ,
1550
1566
in_trait_impl : false ,
1551
- in_const_trait_or_impl : false ,
1567
+ in_const_trait_or_impl : None ,
1552
1568
has_proc_macro_decls : false ,
1553
1569
outer_impl_trait : None ,
1554
1570
disallow_tilde_const : Some ( DisallowTildeConstContext :: Item ) ,
0 commit comments