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