@@ -57,7 +57,9 @@ struct AstValidator<'a> {
5757 in_trait_impl : bool ,
5858
5959 /// 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 > ,
6163
6264 has_proc_macro_decls : bool ,
6365
@@ -85,14 +87,17 @@ impl<'a> AstValidator<'a> {
8587 let old = mem:: replace ( & mut self . in_trait_impl , is_in) ;
8688 let old_const = mem:: replace (
8789 & 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+ } ,
8994 ) ;
9095 f ( self ) ;
9196 self . in_trait_impl = old;
9297 self . in_const_trait_or_impl = old_const;
9398 }
9499
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 ) ) {
96101 let old = mem:: replace ( & mut self . in_const_trait_or_impl , is_const) ;
97102 f ( self ) ;
98103 self . in_const_trait_or_impl = old;
@@ -292,9 +297,18 @@ impl<'a> AstValidator<'a> {
292297 }
293298
294299 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+ } ) ;
298312 }
299313
300314 fn check_fn_decl ( & self , fn_decl : & FnDecl , self_semantic : SelfSemantic ) {
@@ -963,7 +977,8 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
963977 }
964978 }
965979 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 ) ;
967982 self . with_in_trait ( is_const_trait, |this| {
968983 if * is_auto == IsAuto :: Yes {
969984 // Auto traits cannot have generics, super traits nor contain items.
@@ -977,8 +992,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
977992 // context for the supertraits.
978993 this. visit_vis ( & item. vis ) ;
979994 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 ) ) ;
982998 this. with_tilde_const ( disallowed, |this| {
983999 this. visit_generics ( generics) ;
9841000 walk_list ! ( this, visit_param_bound, bounds, BoundKind :: SuperTraits )
@@ -1340,9 +1356,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
13401356 } ) ;
13411357 }
13421358
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( ) ) ;
13461363
13471364 let disallowed = ( !tilde_const_allowed) . then ( || DisallowTildeConstContext :: Fn ( fk) ) ;
13481365 self . with_tilde_const ( disallowed, |this| visit:: walk_fn ( this, fk) ) ;
@@ -1414,7 +1431,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14141431
14151432 match & item. kind {
14161433 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 ( )
14181435 || ctxt == AssocCtxt :: Trait
14191436 || matches ! ( sig. header. constness, Const :: Yes ( _) ) =>
14201437 {
@@ -1548,7 +1565,7 @@ pub fn check_crate(
15481565 features,
15491566 extern_mod : None ,
15501567 in_trait_impl : false ,
1551- in_const_trait_or_impl : false ,
1568+ in_const_trait_or_impl : None ,
15521569 has_proc_macro_decls : false ,
15531570 outer_impl_trait : None ,
15541571 disallow_tilde_const : Some ( DisallowTildeConstContext :: Item ) ,
0 commit comments