@@ -33,24 +33,6 @@ enum SelfSemantic {
33
33
No ,
34
34
}
35
35
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
-
54
36
struct AstValidator < ' a > {
55
37
session : & ' a Session ,
56
38
@@ -60,18 +42,16 @@ struct AstValidator<'a> {
60
42
/// Are we inside a trait impl?
61
43
in_trait_impl : bool ,
62
44
45
+ in_const_trait_impl : bool ,
46
+
63
47
has_proc_macro_decls : bool ,
64
48
65
49
/// Used to ban nested `impl Trait`, e.g., `impl Into<impl Debug>`.
66
50
/// Nested `impl Trait` _is_ allowed in associated type position,
67
51
/// e.g., `impl Iterator<Item = impl Debug>`.
68
52
outer_impl_trait : Option < Span > ,
69
53
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 ,
75
55
76
56
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
77
57
/// or `Foo::Bar<impl Trait>`
@@ -88,10 +68,18 @@ struct AstValidator<'a> {
88
68
}
89
69
90
70
impl < ' 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
+ ) {
92
77
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 ( _) ) ) ) ;
93
80
f ( self ) ;
94
81
self . in_trait_impl = old;
82
+ self . in_const_trait_impl = old_const;
95
83
}
96
84
97
85
fn with_banned_impl_trait ( & mut self , f : impl FnOnce ( & mut Self ) ) {
@@ -100,6 +88,18 @@ impl<'a> AstValidator<'a> {
100
88
self . is_impl_trait_banned = old;
101
89
}
102
90
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
+
103
103
fn with_let_allowed ( & mut self , allowed : bool , f : impl FnOnce ( & mut Self , bool ) ) {
104
104
let old = mem:: replace ( & mut self . is_let_allowed , allowed) ;
105
105
f ( self , old) ;
@@ -130,19 +130,13 @@ impl<'a> AstValidator<'a> {
130
130
fn with_impl_trait ( & mut self , outer : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
131
131
let old = mem:: replace ( & mut self . outer_impl_trait , outer) ;
132
132
if outer. is_some ( ) {
133
- self . with_bound_context ( BoundContext :: ImplTrait , |this| f ( this ) ) ;
133
+ self . with_banned_tilde_const ( f ) ;
134
134
} else {
135
- f ( self )
135
+ f ( self ) ;
136
136
}
137
137
self . outer_impl_trait = old;
138
138
}
139
139
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
-
146
140
fn visit_assoc_ty_constraint_from_generic_args ( & mut self , constraint : & ' a AssocTyConstraint ) {
147
141
match constraint. kind {
148
142
AssocTyConstraintKind :: Equality { .. } => { }
@@ -164,9 +158,7 @@ impl<'a> AstValidator<'a> {
164
158
TyKind :: ImplTrait ( ..) => {
165
159
self . with_impl_trait ( Some ( t. span ) , |this| visit:: walk_ty ( this, t) )
166
160
}
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) ) ,
170
162
TyKind :: Path ( ref qself, ref path) => {
171
163
// We allow these:
172
164
// - `Option<impl Trait>`
@@ -1083,13 +1075,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1083
1075
unsafety,
1084
1076
polarity,
1085
1077
defaultness : _,
1086
- constness : _ ,
1087
- generics : _ ,
1078
+ constness,
1079
+ ref generics ,
1088
1080
of_trait : Some ( ref t) ,
1089
1081
ref self_ty,
1090
- items : _ ,
1082
+ ref items ,
1091
1083
} ) => {
1092
- self . with_in_trait_impl ( true , |this| {
1084
+ self . with_in_trait_impl ( true , Some ( constness ) , |this| {
1093
1085
this. invalid_visibility ( & item. vis , None ) ;
1094
1086
if let TyKind :: Err = self_ty. kind {
1095
1087
this. err_handler ( )
@@ -1112,7 +1104,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1112
1104
. emit ( ) ;
1113
1105
}
1114
1106
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 ) ;
1116
1118
} ) ;
1117
1119
return ; // Avoid visiting again.
1118
1120
}
@@ -1157,13 +1159,24 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1157
1159
. emit ( ) ;
1158
1160
}
1159
1161
}
1160
- ItemKind :: Fn ( box FnKind ( def, _ , _ , ref body) ) => {
1162
+ ItemKind :: Fn ( box FnKind ( def, ref sig , ref generics , ref body) ) => {
1161
1163
self . check_defaultness ( item. span , def) ;
1162
1164
1163
1165
if body. is_none ( ) {
1164
1166
let msg = "free function without a body" ;
1165
1167
self . error_item_without_body ( item. span , "function" , msg, " { <body> }" ) ;
1166
1168
}
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.
1167
1180
}
1168
1181
ItemKind :: ForeignMod ( ForeignMod { unsafety, .. } ) => {
1169
1182
let old_item = mem:: replace ( & mut self . extern_mod , Some ( item) ) ;
@@ -1206,9 +1219,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1206
1219
self . visit_vis ( & item. vis ) ;
1207
1220
self . visit_ident ( item. ident ) ;
1208
1221
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) ) ;
1212
1223
walk_list ! ( self , visit_assoc_item, trait_items, AssocCtxt :: Trait ) ;
1213
1224
walk_list ! ( self , visit_attribute, & item. attrs) ;
1214
1225
return ;
@@ -1281,7 +1292,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1281
1292
_ => { }
1282
1293
}
1283
1294
1284
- visit:: walk_item ( self , item)
1295
+ visit:: walk_item ( self , item) ;
1285
1296
}
1286
1297
1287
1298
fn visit_foreign_item ( & mut self , fi : & ' a ForeignItem ) {
@@ -1428,15 +1439,17 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1428
1439
fn visit_param_bound ( & mut self , bound : & ' a GenericBound ) {
1429
1440
match bound {
1430
1441
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 ( ) ;
1434
1447
}
1435
1448
}
1436
1449
1437
1450
GenericBound :: Trait ( _, TraitBoundModifier :: MaybeConstMaybe ) => {
1438
1451
self . err_handler ( )
1439
- . span_err ( bound. span ( ) , "`? const` and `?` are mutually exclusive" ) ;
1452
+ . span_err ( bound. span ( ) , "`~ const` and `?` are mutually exclusive" ) ;
1440
1453
}
1441
1454
1442
1455
_ => { }
@@ -1589,7 +1602,32 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1589
1602
self . check_item_named ( item. ident , "const" ) ;
1590
1603
}
1591
1604
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
+ }
1593
1631
}
1594
1632
}
1595
1633
@@ -1683,9 +1721,10 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
1683
1721
session,
1684
1722
extern_mod : None ,
1685
1723
in_trait_impl : false ,
1724
+ in_const_trait_impl : false ,
1686
1725
has_proc_macro_decls : false ,
1687
1726
outer_impl_trait : None ,
1688
- bound_context : None ,
1727
+ is_tilde_const_allowed : false ,
1689
1728
is_impl_trait_banned : false ,
1690
1729
is_assoc_ty_bound_banned : false ,
1691
1730
is_let_allowed : false ,
0 commit comments