@@ -33,24 +33,6 @@ enum SelfSemantic {
3333 No ,
3434}
3535
36- /// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
37- #[ derive( Clone , Copy ) ]
38- enum BoundContext {
39- ImplTrait ,
40- TraitBounds ,
41- TraitObject ,
42- }
43-
44- impl BoundContext {
45- fn description ( & self ) -> & ' static str {
46- match self {
47- Self :: ImplTrait => "`impl Trait`" ,
48- Self :: TraitBounds => "supertraits" ,
49- Self :: TraitObject => "trait objects" ,
50- }
51- }
52- }
53-
5436struct AstValidator < ' a > {
5537 session : & ' a Session ,
5638
@@ -60,18 +42,16 @@ struct AstValidator<'a> {
6042 /// Are we inside a trait impl?
6143 in_trait_impl : bool ,
6244
45+ in_const_trait_impl : bool ,
46+
6347 has_proc_macro_decls : bool ,
6448
6549 /// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
6650 /// Nested `impl Trait` _is_ allowed in associated type position,
6751 /// e.g., `impl Iterator<Item = impl Debug>`.
6852 outer_impl_trait : Option < Span > ,
6953
70- /// Keeps track of the `BoundContext` as we recurse.
71- ///
72- /// This is used to forbid `?const Trait` bounds in, e.g.,
73- /// `impl Iterator<Item = Box<dyn ?const Trait>`.
74- bound_context : Option < BoundContext > ,
54+ is_tilde_const_allowed : bool ,
7555
7656 /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
7757 /// or `Foo::Bar<impl Trait>`
@@ -88,10 +68,18 @@ struct AstValidator<'a> {
8868}
8969
9070impl < ' a > AstValidator < ' a > {
91- fn with_in_trait_impl ( & mut self , is_in : bool , f : impl FnOnce ( & mut Self ) ) {
71+ fn with_in_trait_impl (
72+ & mut self ,
73+ is_in : bool ,
74+ constness : Option < Const > ,
75+ f : impl FnOnce ( & mut Self ) ,
76+ ) {
9277 let old = mem:: replace ( & mut self . in_trait_impl , is_in) ;
78+ let old_const =
79+ mem:: replace ( & mut self . in_const_trait_impl , matches ! ( constness, Some ( Const :: Yes ( _) ) ) ) ;
9380 f ( self ) ;
9481 self . in_trait_impl = old;
82+ self . in_const_trait_impl = old_const;
9583 }
9684
9785 fn with_banned_impl_trait ( & mut self , f : impl FnOnce ( & mut Self ) ) {
@@ -100,6 +88,18 @@ impl<'a> AstValidator<'a> {
10088 self . is_impl_trait_banned = old;
10189 }
10290
91+ fn with_tilde_const_allowed ( & mut self , f : impl FnOnce ( & mut Self ) ) {
92+ let old = mem:: replace ( & mut self . is_tilde_const_allowed , true ) ;
93+ f ( self ) ;
94+ self . is_tilde_const_allowed = old;
95+ }
96+
97+ fn with_banned_tilde_const ( & mut self , f : impl FnOnce ( & mut Self ) ) {
98+ let old = mem:: replace ( & mut self . is_tilde_const_allowed , false ) ;
99+ f ( self ) ;
100+ self . is_tilde_const_allowed = old;
101+ }
102+
103103 fn with_let_allowed ( & mut self , allowed : bool , f : impl FnOnce ( & mut Self , bool ) ) {
104104 let old = mem:: replace ( & mut self . is_let_allowed , allowed) ;
105105 f ( self , old) ;
@@ -130,19 +130,13 @@ impl<'a> AstValidator<'a> {
130130 fn with_impl_trait ( & mut self , outer : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
131131 let old = mem:: replace ( & mut self . outer_impl_trait , outer) ;
132132 if outer. is_some ( ) {
133- self . with_bound_context ( BoundContext :: ImplTrait , |this| f ( this ) ) ;
133+ self . with_banned_tilde_const ( f ) ;
134134 } else {
135- f ( self )
135+ f ( self ) ;
136136 }
137137 self . outer_impl_trait = old;
138138 }
139139
140- fn with_bound_context ( & mut self , ctx : BoundContext , f : impl FnOnce ( & mut Self ) ) {
141- let old = self . bound_context . replace ( ctx) ;
142- f ( self ) ;
143- self . bound_context = old;
144- }
145-
146140 fn visit_assoc_ty_constraint_from_generic_args ( & mut self , constraint : & ' a AssocTyConstraint ) {
147141 match constraint. kind {
148142 AssocTyConstraintKind :: Equality { .. } => { }
@@ -164,9 +158,7 @@ impl<'a> AstValidator<'a> {
164158 TyKind :: ImplTrait ( ..) => {
165159 self . with_impl_trait ( Some ( t. span ) , |this| visit:: walk_ty ( this, t) )
166160 }
167- TyKind :: TraitObject ( ..) => {
168- self . with_bound_context ( BoundContext :: TraitObject , |this| visit:: walk_ty ( this, t) ) ;
169- }
161+ TyKind :: TraitObject ( ..) => self . with_banned_tilde_const ( |this| visit:: walk_ty ( this, t) ) ,
170162 TyKind :: Path ( ref qself, ref path) => {
171163 // We allow these:
172164 // - `Option<impl Trait>`
@@ -1083,13 +1075,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
10831075 unsafety,
10841076 polarity,
10851077 defaultness : _,
1086- constness : _ ,
1087- generics : _ ,
1078+ constness,
1079+ ref generics ,
10881080 of_trait : Some ( ref t) ,
10891081 ref self_ty,
1090- items : _ ,
1082+ ref items ,
10911083 } ) => {
1092- self . with_in_trait_impl ( true , |this| {
1084+ self . with_in_trait_impl ( true , Some ( constness ) , |this| {
10931085 this. invalid_visibility ( & item. vis , None ) ;
10941086 if let TyKind :: Err = self_ty. kind {
10951087 this. err_handler ( )
@@ -1112,7 +1104,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11121104 . emit ( ) ;
11131105 }
11141106
1115- visit:: walk_item ( this, item) ;
1107+ this. visit_vis ( & item. vis ) ;
1108+ this. visit_ident ( item. ident ) ;
1109+ if let Const :: Yes ( _) = constness {
1110+ this. with_tilde_const_allowed ( |this| this. visit_generics ( generics) ) ;
1111+ } else {
1112+ this. visit_generics ( generics) ;
1113+ }
1114+ this. visit_trait_ref ( t) ;
1115+ this. visit_ty ( self_ty) ;
1116+
1117+ walk_list ! ( this, visit_assoc_item, items, AssocCtxt :: Impl ) ;
11161118 } ) ;
11171119 return ; // Avoid visiting again.
11181120 }
@@ -1157,13 +1159,24 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
11571159 . emit ( ) ;
11581160 }
11591161 }
1160- ItemKind :: Fn ( box FnKind ( def, _ , _ , ref body) ) => {
1162+ ItemKind :: Fn ( box FnKind ( def, ref sig , ref generics , ref body) ) => {
11611163 self . check_defaultness ( item. span , def) ;
11621164
11631165 if body. is_none ( ) {
11641166 let msg = "free function without a body" ;
11651167 self . error_item_without_body ( item. span , "function" , msg, " { <body> }" ) ;
11661168 }
1169+ self . visit_vis ( & item. vis ) ;
1170+ self . visit_ident ( item. ident ) ;
1171+ if let Const :: Yes ( _) = sig. header . constness {
1172+ self . with_tilde_const_allowed ( |this| this. visit_generics ( generics) ) ;
1173+ } else {
1174+ self . visit_generics ( generics) ;
1175+ }
1176+ let kind = FnKind :: Fn ( FnCtxt :: Free , item. ident , sig, & item. vis , body. as_deref ( ) ) ;
1177+ self . visit_fn ( kind, item. span , item. id ) ;
1178+ walk_list ! ( self , visit_attribute, & item. attrs) ;
1179+ return ; // Avoid visiting again.
11671180 }
11681181 ItemKind :: ForeignMod ( ForeignMod { unsafety, .. } ) => {
11691182 let old_item = mem:: replace ( & mut self . extern_mod , Some ( item) ) ;
@@ -1206,9 +1219,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12061219 self . visit_vis ( & item. vis ) ;
12071220 self . visit_ident ( item. ident ) ;
12081221 self . visit_generics ( generics) ;
1209- self . with_bound_context ( BoundContext :: TraitBounds , |this| {
1210- walk_list ! ( this, visit_param_bound, bounds) ;
1211- } ) ;
1222+ self . with_banned_tilde_const ( |this| walk_list ! ( this, visit_param_bound, bounds) ) ;
12121223 walk_list ! ( self , visit_assoc_item, trait_items, AssocCtxt :: Trait ) ;
12131224 walk_list ! ( self , visit_attribute, & item. attrs) ;
12141225 return ;
@@ -1281,7 +1292,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
12811292 _ => { }
12821293 }
12831294
1284- visit:: walk_item ( self , item)
1295+ visit:: walk_item ( self , item) ;
12851296 }
12861297
12871298 fn visit_foreign_item ( & mut self , fi : & ' a ForeignItem ) {
@@ -1428,15 +1439,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14281439 fn visit_param_bound ( & mut self , bound : & ' a GenericBound ) {
14291440 match bound {
14301441 GenericBound :: Trait ( _, TraitBoundModifier :: MaybeConst ) => {
1431- if let Some ( ctx) = self . bound_context {
1432- let msg = format ! ( "`?const` is not permitted in {}" , ctx. description( ) ) ;
1433- self . err_handler ( ) . span_err ( bound. span ( ) , & msg) ;
1442+ if !self . is_tilde_const_allowed {
1443+ self . err_handler ( )
1444+ . struct_span_err ( bound. span ( ) , "`~const` is not allowed here" )
1445+ . note ( "only allowed on bounds on traits' associated types, const fns, const impls and its associated functions" )
1446+ . emit ( ) ;
14341447 }
14351448 }
14361449
14371450 GenericBound :: Trait ( _, TraitBoundModifier :: MaybeConstMaybe ) => {
14381451 self . err_handler ( )
1439- . span_err ( bound. span ( ) , "`? const` and `?` are mutually exclusive" ) ;
1452+ . span_err ( bound. span ( ) , "`~ const` and `?` are mutually exclusive" ) ;
14401453 }
14411454
14421455 _ => { }
@@ -1589,7 +1602,32 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15891602 self . check_item_named ( item. ident , "const" ) ;
15901603 }
15911604
1592- self . with_in_trait_impl ( false , |this| visit:: walk_assoc_item ( this, item, ctxt) ) ;
1605+ match item. kind {
1606+ AssocItemKind :: TyAlias ( box TyAliasKind ( _, ref generics, ref bounds, ref ty) )
1607+ if ctxt == AssocCtxt :: Trait =>
1608+ {
1609+ self . visit_vis ( & item. vis ) ;
1610+ self . visit_ident ( item. ident ) ;
1611+ walk_list ! ( self , visit_attribute, & item. attrs) ;
1612+ self . with_tilde_const_allowed ( |this| {
1613+ this. visit_generics ( generics) ;
1614+ walk_list ! ( this, visit_param_bound, bounds) ;
1615+ } ) ;
1616+ walk_list ! ( self , visit_ty, ty) ;
1617+ }
1618+ AssocItemKind :: Fn ( box FnKind ( _, ref sig, ref generics, ref body) )
1619+ if self . in_const_trait_impl =>
1620+ {
1621+ self . visit_vis ( & item. vis ) ;
1622+ self . visit_ident ( item. ident ) ;
1623+ self . with_tilde_const_allowed ( |this| this. visit_generics ( generics) ) ;
1624+ let kind =
1625+ FnKind :: Fn ( FnCtxt :: Assoc ( ctxt) , item. ident , sig, & item. vis , body. as_deref ( ) ) ;
1626+ self . visit_fn ( kind, item. span , item. id ) ;
1627+ }
1628+ _ => self
1629+ . with_in_trait_impl ( false , None , |this| visit:: walk_assoc_item ( this, item, ctxt) ) ,
1630+ }
15931631 }
15941632}
15951633
@@ -1683,9 +1721,10 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
16831721 session,
16841722 extern_mod : None ,
16851723 in_trait_impl : false ,
1724+ in_const_trait_impl : false ,
16861725 has_proc_macro_decls : false ,
16871726 outer_impl_trait : None ,
1688- bound_context : None ,
1727+ is_tilde_const_allowed : false ,
16891728 is_impl_trait_banned : false ,
16901729 is_assoc_ty_bound_banned : false ,
16911730 is_let_allowed : false ,
0 commit comments