@@ -40,6 +40,9 @@ enum SelfSemantic {
40
40
enum DisallowTildeConstContext < ' a > {
41
41
TraitObject ,
42
42
Fn ( FnKind < ' a > ) ,
43
+ Trait ( Span ) ,
44
+ Impl ( Span ) ,
45
+ Item ,
43
46
}
44
47
45
48
struct AstValidator < ' a > {
@@ -110,10 +113,6 @@ impl<'a> AstValidator<'a> {
110
113
self . disallow_tilde_const = old;
111
114
}
112
115
113
- fn with_tilde_const_allowed ( & mut self , f : impl FnOnce ( & mut Self ) ) {
114
- self . with_tilde_const ( None , f)
115
- }
116
-
117
116
fn with_banned_tilde_const (
118
117
& mut self ,
119
118
ctx : DisallowTildeConstContext < ' a > ,
@@ -822,11 +821,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
822
821
823
822
this. visit_vis ( & item. vis ) ;
824
823
this. visit_ident ( item. ident ) ;
825
- if let Const :: Yes ( _) = constness {
826
- this. with_tilde_const_allowed ( |this| this. visit_generics ( generics) ) ;
827
- } else {
828
- this. visit_generics ( generics) ;
829
- }
824
+ let disallowed = matches ! ( constness, Const :: No )
825
+ . then ( || DisallowTildeConstContext :: Impl ( item. span ) ) ;
826
+ this. with_tilde_const ( disallowed, |this| this. visit_generics ( generics) ) ;
830
827
this. visit_trait_ref ( t) ;
831
828
this. visit_ty ( self_ty) ;
832
829
@@ -926,7 +923,14 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
926
923
self . extern_mod = old_item;
927
924
return ; // Avoid visiting again.
928
925
}
929
- ItemKind :: Enum ( def, _) => {
926
+ ItemKind :: Enum ( def, generics) => {
927
+ self . visit_vis ( & item. vis ) ;
928
+ self . visit_ident ( item. ident ) ;
929
+
930
+ self . with_banned_tilde_const ( DisallowTildeConstContext :: Item , |this| {
931
+ this. visit_generics ( generics)
932
+ } ) ;
933
+
930
934
for variant in & def. variants {
931
935
self . visibility_not_permitted (
932
936
& variant. vis ,
@@ -939,6 +943,9 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
939
943
) ;
940
944
}
941
945
}
946
+ walk_list ! ( self , visit_variant, & def. variants) ;
947
+ walk_list ! ( self , visit_attribute, & item. attrs) ;
948
+ return ; // Avoid visiting again
942
949
}
943
950
ItemKind :: Trait ( box Trait { is_auto, generics, bounds, items, .. } ) => {
944
951
let is_const_trait = attr:: contains_name ( & item. attrs , sym:: const_trait) ;
@@ -955,8 +962,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
955
962
// context for the supertraits.
956
963
this. visit_vis ( & item. vis ) ;
957
964
this. visit_ident ( item. ident ) ;
958
- this. visit_generics ( generics) ;
959
- this. with_tilde_const_allowed ( |this| {
965
+ let disallowed =
966
+ ( !is_const_trait) . then ( || DisallowTildeConstContext :: Trait ( item. span ) ) ;
967
+ this. with_tilde_const ( disallowed, |this| {
968
+ this. visit_generics ( generics) ;
960
969
walk_list ! ( this, visit_param_bound, bounds, BoundKind :: SuperTraits )
961
970
} ) ;
962
971
walk_list ! ( this, visit_assoc_item, items, AssocCtxt :: Trait ) ;
@@ -975,23 +984,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
975
984
self . check_mod_file_item_asciionly ( item. ident ) ;
976
985
}
977
986
}
978
- ItemKind :: Struct ( vdata, generics) => match vdata {
979
- // Duplicating the `Visitor` logic allows catching all cases
980
- // of `Anonymous(Struct, Union)` outside of a field struct or union.
981
- //
982
- // Inside `visit_ty` the validator catches every `Anonymous(Struct, Union)` it
983
- // encounters, and only on `ItemKind::Struct` and `ItemKind::Union`
984
- // it uses `visit_ty_common`, which doesn't contain that specific check.
985
- VariantData :: Struct ( fields , .. ) => {
986
- self . visit_vis ( & item . vis ) ;
987
- self . visit_ident ( item . ident ) ;
988
- self . visit_generics ( generics ) ;
989
- walk_list ! ( self , visit_struct_field_def, fields) ;
990
- walk_list ! ( self , visit_attribute , & item . attrs ) ;
991
- return ;
987
+ ItemKind :: Struct ( vdata, generics) => {
988
+ self . visit_vis ( & item . vis ) ;
989
+ self . visit_ident ( item . ident ) ;
990
+ self . with_banned_tilde_const ( DisallowTildeConstContext :: Item , |this| {
991
+ this . visit_generics ( generics )
992
+ } ) ;
993
+ walk_list ! ( self , visit_attribute , & item . attrs ) ;
994
+
995
+ match vdata {
996
+ // Permit `Anon{Struct,Union}` as field type.
997
+ VariantData :: Struct ( fields , .. ) => {
998
+ walk_list ! ( self , visit_struct_field_def, fields)
999
+ }
1000
+ _ => self . visit_variant_data ( vdata ) ,
992
1001
}
993
- _ => { }
994
- } ,
1002
+ return ; // Avoid visiting again-
1003
+ }
995
1004
ItemKind :: Union ( vdata, generics) => {
996
1005
if vdata. fields ( ) . is_empty ( ) {
997
1006
self . err_handler ( ) . emit_err ( errors:: FieldlessUnion { span : item. span } ) ;
@@ -1000,20 +1009,38 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1000
1009
VariantData :: Struct ( fields, ..) => {
1001
1010
self . visit_vis ( & item. vis ) ;
1002
1011
self . visit_ident ( item. ident ) ;
1003
- self . visit_generics ( generics) ;
1012
+ self . with_banned_tilde_const ( DisallowTildeConstContext :: Item , |this| {
1013
+ this. visit_generics ( generics)
1014
+ } ) ;
1015
+ // Permit `Anon{Struct,Union}` as field type.
1004
1016
walk_list ! ( self , visit_struct_field_def, fields) ;
1005
1017
walk_list ! ( self , visit_attribute, & item. attrs) ;
1006
1018
return ;
1007
1019
}
1008
1020
_ => { }
1009
1021
}
1010
1022
}
1011
- ItemKind :: Const ( box ConstItem { defaultness, expr : None , .. } ) => {
1012
- self . check_defaultness ( item. span , * defaultness) ;
1013
- self . session . emit_err ( errors:: ConstWithoutBody {
1014
- span : item. span ,
1015
- replace_span : self . ending_semi_or_hi ( item. span ) ,
1023
+ ItemKind :: Const ( box ConstItem { defaultness, generics, ty, expr } ) => {
1024
+ self . visit_vis ( & item. vis ) ;
1025
+ self . visit_ident ( item. ident ) ;
1026
+ // FIXME(#117791): Also reject `default` if `expr` is `Some`.
1027
+ if expr. is_none ( ) {
1028
+ self . check_defaultness ( item. span , * defaultness) ;
1029
+ }
1030
+ self . with_banned_tilde_const ( DisallowTildeConstContext :: Item , |this| {
1031
+ this. visit_generics ( generics)
1016
1032
} ) ;
1033
+ self . visit_ty ( ty) ;
1034
+ if let Some ( expr) = expr {
1035
+ self . visit_expr ( expr) ;
1036
+ } else {
1037
+ self . session . emit_err ( errors:: ConstWithoutBody {
1038
+ span : item. span ,
1039
+ replace_span : self . ending_semi_or_hi ( item. span ) ,
1040
+ } ) ;
1041
+ }
1042
+ walk_list ! ( self , visit_attribute, & item. attrs) ;
1043
+ return ; // Avoid visiting again.
1017
1044
}
1018
1045
ItemKind :: Static ( box StaticItem { expr : None , .. } ) => {
1019
1046
self . session . emit_err ( errors:: StaticWithoutBody {
@@ -1022,9 +1049,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1022
1049
} ) ;
1023
1050
}
1024
1051
ItemKind :: TyAlias (
1025
- ty_alias @ box TyAlias { defaultness, bounds, where_clauses, ty, .. } ,
1052
+ ty_alias @ box TyAlias { defaultness, generics , bounds, where_clauses, ty, .. } ,
1026
1053
) => {
1027
1054
self . check_defaultness ( item. span , * defaultness) ;
1055
+ self . with_banned_tilde_const ( DisallowTildeConstContext :: Item , |this| {
1056
+ this. visit_generics ( generics)
1057
+ } ) ;
1028
1058
if ty. is_none ( ) {
1029
1059
self . session . emit_err ( errors:: TyAliasWithoutBody {
1030
1060
span : item. span ,
@@ -1189,15 +1219,18 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1189
1219
if let Some ( reason) = & self . disallow_tilde_const =>
1190
1220
{
1191
1221
let reason = match reason {
1192
- DisallowTildeConstContext :: TraitObject => {
1193
- errors:: TildeConstReason :: TraitObject
1194
- }
1195
1222
DisallowTildeConstContext :: Fn ( FnKind :: Closure ( ..) ) => {
1196
1223
errors:: TildeConstReason :: Closure
1197
1224
}
1198
1225
DisallowTildeConstContext :: Fn ( FnKind :: Fn ( _, ident, ..) ) => {
1199
1226
errors:: TildeConstReason :: Function { ident : ident. span }
1200
1227
}
1228
+ & DisallowTildeConstContext :: Trait ( span) => errors:: TildeConstReason :: Trait { span } ,
1229
+ & DisallowTildeConstContext :: Impl ( span) => errors:: TildeConstReason :: Impl { span } ,
1230
+ DisallowTildeConstContext :: TraitObject => {
1231
+ errors:: TildeConstReason :: TraitObject
1232
+ }
1233
+ DisallowTildeConstContext :: Item => errors:: TildeConstReason :: Item ,
1201
1234
} ;
1202
1235
self . err_handler ( )
1203
1236
. emit_err ( errors:: TildeConstDisallowed { span : bound. span ( ) , reason } ) ;
@@ -1305,7 +1338,6 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1305
1338
|| matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) if self . in_const_trait_or_impl) ;
1306
1339
1307
1340
let disallowed = ( !tilde_const_allowed) . then ( || DisallowTildeConstContext :: Fn ( fk) ) ;
1308
-
1309
1341
self . with_tilde_const ( disallowed, |this| visit:: walk_fn ( this, fk) ) ;
1310
1342
}
1311
1343
@@ -1374,15 +1406,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1374
1406
}
1375
1407
1376
1408
match & item. kind {
1377
- AssocItemKind :: Type ( box TyAlias { generics, bounds, ty, .. } )
1378
- if ctxt == AssocCtxt :: Trait =>
1379
- {
1409
+ AssocItemKind :: Type ( box TyAlias { generics, bounds, ty, .. } ) => {
1380
1410
self . visit_vis ( & item. vis ) ;
1381
1411
self . visit_ident ( item. ident ) ;
1382
1412
walk_list ! ( self , visit_attribute, & item. attrs) ;
1383
- self . with_tilde_const_allowed ( |this| {
1413
+ self . with_banned_tilde_const ( DisallowTildeConstContext :: Item , |this| {
1384
1414
this. visit_generics ( generics) ;
1385
- walk_list ! ( this, visit_param_bound, bounds, BoundKind :: Bound ) ;
1415
+ if ctxt == AssocCtxt :: Trait {
1416
+ walk_list ! ( this, visit_param_bound, bounds, BoundKind :: Bound ) ;
1417
+ }
1386
1418
} ) ;
1387
1419
walk_list ! ( self , visit_ty, ty) ;
1388
1420
}
@@ -1403,6 +1435,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1403
1435
) ;
1404
1436
self . visit_fn ( kind, item. span , item. id ) ;
1405
1437
}
1438
+ AssocItemKind :: Const ( box ConstItem { generics, ty, expr, .. } ) => {
1439
+ self . visit_vis ( & item. vis ) ;
1440
+ self . visit_ident ( item. ident ) ;
1441
+ walk_list ! ( self , visit_attribute, & item. attrs) ;
1442
+ self . with_banned_tilde_const ( DisallowTildeConstContext :: Item , |this| {
1443
+ this. visit_generics ( generics) ;
1444
+ } ) ;
1445
+ self . visit_ty ( ty) ;
1446
+ walk_list ! ( self , visit_expr, expr) ;
1447
+ }
1406
1448
_ => self
1407
1449
. with_in_trait_impl ( false , None , |this| visit:: walk_assoc_item ( this, item, ctxt) ) ,
1408
1450
}
0 commit comments