@@ -47,15 +47,17 @@ enum SelfSemantic {
4747 No ,
4848}
4949
50- enum TraitOrTraitImpl {
50+ enum TraitOrImpl {
5151 Trait { span : Span , constness : Const } ,
5252 TraitImpl { constness : Const , polarity : ImplPolarity , trait_ref_span : Span } ,
53+ Impl { constness : Const } ,
5354}
5455
55- impl TraitOrTraitImpl {
56+ impl TraitOrImpl {
5657 fn constness ( & self ) -> Option < Span > {
5758 match self {
5859 Self :: Trait { constness : Const :: Yes ( span) , .. }
60+ | Self :: Impl { constness : Const :: Yes ( span) , .. }
5961 | Self :: TraitImpl { constness : Const :: Yes ( span) , .. } => Some ( * span) ,
6062 _ => None ,
6163 }
@@ -69,7 +71,7 @@ struct AstValidator<'a> {
6971 /// The span of the `extern` in an `extern { ... }` block, if any.
7072 extern_mod_span : Option < Span > ,
7173
72- outer_trait_or_trait_impl : Option < TraitOrTraitImpl > ,
74+ outer_trait_or_trait_impl : Option < TraitOrImpl > ,
7375
7476 has_proc_macro_decls : bool ,
7577
@@ -92,28 +94,12 @@ struct AstValidator<'a> {
9294}
9395
9496impl < ' a > AstValidator < ' a > {
95- fn with_in_trait_impl (
97+ fn with_in_trait_or_impl (
9698 & mut self ,
97- trait_ : Option < ( Const , ImplPolarity , & ' a TraitRef ) > ,
99+ in_trait_or_impl : Option < TraitOrImpl > ,
98100 f : impl FnOnce ( & mut Self ) ,
99101 ) {
100- let old = mem:: replace (
101- & mut self . outer_trait_or_trait_impl ,
102- trait_. map ( |( constness, polarity, trait_ref) | TraitOrTraitImpl :: TraitImpl {
103- constness,
104- polarity,
105- trait_ref_span : trait_ref. path . span ,
106- } ) ,
107- ) ;
108- f ( self ) ;
109- self . outer_trait_or_trait_impl = old;
110- }
111-
112- fn with_in_trait ( & mut self , span : Span , constness : Const , f : impl FnOnce ( & mut Self ) ) {
113- let old = mem:: replace (
114- & mut self . outer_trait_or_trait_impl ,
115- Some ( TraitOrTraitImpl :: Trait { span, constness } ) ,
116- ) ;
102+ let old = mem:: replace ( & mut self . outer_trait_or_trait_impl , in_trait_or_impl) ;
117103 f ( self ) ;
118104 self . outer_trait_or_trait_impl = old;
119105 }
@@ -246,14 +232,26 @@ impl<'a> AstValidator<'a> {
246232 }
247233 }
248234
249- fn check_trait_fn_not_const ( & self , constness : Const , parent : & TraitOrTraitImpl ) {
235+ fn check_impl_fn_not_const ( & self , constness : Const , parent_constness : Const ) {
236+ let Const :: Yes ( span) = constness else {
237+ return ;
238+ } ;
239+
240+ let Const :: Yes ( parent_constness) = parent_constness else {
241+ return ;
242+ } ;
243+
244+ self . dcx ( ) . emit_err ( errors:: ImplFnConst { span, parent_constness } ) ;
245+ }
246+
247+ fn check_trait_fn_not_const ( & self , constness : Const , parent : & TraitOrImpl ) {
250248 let Const :: Yes ( span) = constness else {
251249 return ;
252250 } ;
253251
254252 let const_trait_impl = self . features . const_trait_impl ( ) ;
255253 let make_impl_const_sugg = if const_trait_impl
256- && let TraitOrTraitImpl :: TraitImpl {
254+ && let TraitOrImpl :: TraitImpl {
257255 constness : Const :: No ,
258256 polarity : ImplPolarity :: Positive ,
259257 trait_ref_span,
@@ -266,7 +264,7 @@ impl<'a> AstValidator<'a> {
266264 } ;
267265
268266 let make_trait_const_sugg = if const_trait_impl
269- && let TraitOrTraitImpl :: Trait { span, constness : ast:: Const :: No } = parent
267+ && let TraitOrImpl :: Trait { span, constness : ast:: Const :: No } = parent
270268 {
271269 Some ( span. shrink_to_lo ( ) )
272270 } else {
@@ -276,7 +274,7 @@ impl<'a> AstValidator<'a> {
276274 let parent_constness = parent. constness ( ) ;
277275 self . dcx ( ) . emit_err ( errors:: TraitFnConst {
278276 span,
279- in_impl : matches ! ( parent, TraitOrTraitImpl :: TraitImpl { .. } ) ,
277+ in_impl : matches ! ( parent, TraitOrImpl :: TraitImpl { .. } ) ,
280278 const_context_label : parent_constness,
281279 remove_const_sugg : (
282280 self . sess . source_map ( ) . span_extend_while_whitespace ( span) ,
@@ -292,7 +290,7 @@ impl<'a> AstValidator<'a> {
292290 } ) ;
293291 }
294292
295- fn check_async_fn_in_const_trait_or_impl ( & self , sig : & FnSig , parent : & TraitOrTraitImpl ) {
293+ fn check_async_fn_in_const_trait_or_impl ( & self , sig : & FnSig , parent : & TraitOrImpl ) {
296294 let Some ( const_keyword) = parent. constness ( ) else { return } ;
297295
298296 let Some ( CoroutineKind :: Async { span : async_keyword, .. } ) = sig. header . coroutine_kind
@@ -302,7 +300,7 @@ impl<'a> AstValidator<'a> {
302300
303301 self . dcx ( ) . emit_err ( errors:: AsyncFnInConstTraitOrTraitImpl {
304302 async_keyword,
305- in_impl : matches ! ( parent, TraitOrTraitImpl :: TraitImpl { .. } ) ,
303+ in_impl : matches ! ( parent, TraitOrImpl :: TraitImpl { .. } ) ,
306304 const_keyword,
307305 } ) ;
308306 }
@@ -1011,14 +1009,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10111009 match & item. kind {
10121010 ItemKind :: Impl ( Impl {
10131011 generics,
1012+ constness,
10141013 of_trait :
1015- Some ( box TraitImplHeader {
1016- safety,
1017- polarity,
1018- defaultness : _,
1019- constness,
1020- trait_ref : t,
1021- } ) ,
1014+ Some ( box TraitImplHeader { safety, polarity, defaultness : _, trait_ref : t } ) ,
10221015 self_ty,
10231016 items,
10241017 } ) => {
@@ -1046,24 +1039,46 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10461039 self . visit_trait_ref ( t) ;
10471040 self . visit_ty ( self_ty) ;
10481041
1049- self . with_in_trait_impl ( Some ( ( * constness, * polarity, t) ) , |this| {
1050- walk_list ! ( this, visit_assoc_item, items, AssocCtxt :: Impl { of_trait: true } ) ;
1051- } ) ;
1042+ self . with_in_trait_or_impl (
1043+ Some ( TraitOrImpl :: TraitImpl {
1044+ constness : * constness,
1045+ polarity : * polarity,
1046+ trait_ref_span : t. path . span ,
1047+ } ) ,
1048+ |this| {
1049+ walk_list ! (
1050+ this,
1051+ visit_assoc_item,
1052+ items,
1053+ AssocCtxt :: Impl { of_trait: true }
1054+ ) ;
1055+ } ,
1056+ ) ;
10521057 }
1053- ItemKind :: Impl ( Impl { generics, of_trait : None , self_ty, items } ) => {
1058+ ItemKind :: Impl ( Impl { generics, of_trait : None , self_ty, items, constness } ) => {
10541059 self . visit_attrs_vis ( & item. attrs , & item. vis ) ;
10551060 self . visibility_not_permitted (
10561061 & item. vis ,
10571062 errors:: VisibilityNotPermittedNote :: IndividualImplItems ,
10581063 ) ;
10591064
1060- self . with_tilde_const ( Some ( TildeConstReason :: Impl { span : item. span } ) , |this| {
1061- this. visit_generics ( generics)
1062- } ) ;
1065+ let disallowed = matches ! ( constness, ast:: Const :: No )
1066+ . then ( || TildeConstReason :: Impl { span : item. span } ) ;
1067+
1068+ self . with_tilde_const ( disallowed, |this| this. visit_generics ( generics) ) ;
1069+
10631070 self . visit_ty ( self_ty) ;
1064- self . with_in_trait_impl ( None , |this| {
1065- walk_list ! ( this, visit_assoc_item, items, AssocCtxt :: Impl { of_trait: false } ) ;
1066- } ) ;
1071+ self . with_in_trait_or_impl (
1072+ Some ( TraitOrImpl :: Impl { constness : * constness } ) ,
1073+ |this| {
1074+ walk_list ! (
1075+ this,
1076+ visit_assoc_item,
1077+ items,
1078+ AssocCtxt :: Impl { of_trait: false }
1079+ ) ;
1080+ } ,
1081+ ) ;
10671082 }
10681083 ItemKind :: Fn (
10691084 func @ box Fn {
@@ -1188,9 +1203,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11881203 this. visit_generics ( generics) ;
11891204 walk_list ! ( this, visit_param_bound, bounds, BoundKind :: SuperTraits )
11901205 } ) ;
1191- self . with_in_trait ( item. span , constness, |this| {
1192- walk_list ! ( this, visit_assoc_item, items, AssocCtxt :: Trait ) ;
1193- } ) ;
1206+ self . with_in_trait_or_impl (
1207+ Some ( TraitOrImpl :: Trait { span : item. span , constness } ) ,
1208+ |this| {
1209+ walk_list ! ( this, visit_assoc_item, items, AssocCtxt :: Trait ) ;
1210+ } ,
1211+ ) ;
11941212 }
11951213 ItemKind :: TraitAlias ( box TraitAlias { constness, generics, bounds, .. } ) => {
11961214 let disallowed = matches ! ( constness, ast:: Const :: No )
@@ -1558,7 +1576,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15581576 && self
15591577 . outer_trait_or_trait_impl
15601578 . as_ref ( )
1561- . and_then ( TraitOrTraitImpl :: constness)
1579+ . and_then ( TraitOrImpl :: constness)
15621580 . is_some ( ) ;
15631581
15641582 let disallowed = ( !tilde_const_allowed) . then ( || match fk {
@@ -1625,20 +1643,31 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
16251643 ) ;
16261644 }
16271645
1628- if let Some ( parent) = & self . outer_trait_or_trait_impl {
1629- self . visibility_not_permitted ( & item. vis , errors:: VisibilityNotPermittedNote :: TraitImpl ) ;
1630- if let AssocItemKind :: Fn ( box Fn { sig, .. } ) = & item. kind {
1631- self . check_trait_fn_not_const ( sig. header . constness , parent) ;
1632- self . check_async_fn_in_const_trait_or_impl ( sig, parent) ;
1646+ match & self . outer_trait_or_trait_impl {
1647+ Some ( parent @ ( TraitOrImpl :: Trait { .. } | TraitOrImpl :: TraitImpl { .. } ) ) => {
1648+ self . visibility_not_permitted (
1649+ & item. vis ,
1650+ errors:: VisibilityNotPermittedNote :: TraitImpl ,
1651+ ) ;
1652+ if let AssocItemKind :: Fn ( box Fn { sig, .. } ) = & item. kind {
1653+ self . check_trait_fn_not_const ( sig. header . constness , parent) ;
1654+ self . check_async_fn_in_const_trait_or_impl ( sig, parent) ;
1655+ }
1656+ }
1657+ Some ( TraitOrImpl :: Impl { constness } ) => {
1658+ if let AssocItemKind :: Fn ( box Fn { sig, .. } ) = & item. kind {
1659+ self . check_impl_fn_not_const ( sig. header . constness , * constness) ;
1660+ }
16331661 }
1662+ None => { }
16341663 }
16351664
16361665 if let AssocItemKind :: Const ( ci) = & item. kind {
16371666 self . check_item_named ( ci. ident , "const" ) ;
16381667 }
16391668
16401669 let parent_is_const =
1641- self . outer_trait_or_trait_impl . as_ref ( ) . and_then ( TraitOrTraitImpl :: constness) . is_some ( ) ;
1670+ self . outer_trait_or_trait_impl . as_ref ( ) . and_then ( TraitOrImpl :: constness) . is_some ( ) ;
16421671
16431672 match & item. kind {
16441673 AssocItemKind :: Fn ( func)
@@ -1652,19 +1681,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
16521681 }
16531682 AssocItemKind :: Type ( _) => {
16541683 let disallowed = ( !parent_is_const) . then ( || match self . outer_trait_or_trait_impl {
1655- Some ( TraitOrTraitImpl :: Trait { .. } ) => {
1684+ Some ( TraitOrImpl :: Trait { .. } ) => {
16561685 TildeConstReason :: TraitAssocTy { span : item. span }
16571686 }
1658- Some ( TraitOrTraitImpl :: TraitImpl { .. } ) => {
1687+ Some ( TraitOrImpl :: TraitImpl { .. } ) => {
16591688 TildeConstReason :: TraitImplAssocTy { span : item. span }
16601689 }
1661- None => TildeConstReason :: InherentAssocTy { span : item. span } ,
1690+ Some ( TraitOrImpl :: Impl { .. } ) | None => {
1691+ TildeConstReason :: InherentAssocTy { span : item. span }
1692+ }
16621693 } ) ;
16631694 self . with_tilde_const ( disallowed, |this| {
1664- this. with_in_trait_impl ( None , |this| visit:: walk_assoc_item ( this, item, ctxt) )
1695+ this. with_in_trait_or_impl ( None , |this| {
1696+ visit:: walk_assoc_item ( this, item, ctxt)
1697+ } )
16651698 } )
16661699 }
1667- _ => self . with_in_trait_impl ( None , |this| visit:: walk_assoc_item ( this, item, ctxt) ) ,
1700+ _ => self . with_in_trait_or_impl ( None , |this| visit:: walk_assoc_item ( this, item, ctxt) ) ,
16681701 }
16691702 }
16701703
0 commit comments