@@ -38,6 +38,13 @@ enum SelfSemantic {
38
38
No ,
39
39
}
40
40
41
+ /// What is the context that prevents using `~const`?
42
+ enum DisallowTildeConstContext < ' a > {
43
+ TraitObject ,
44
+ ImplTrait ,
45
+ Fn ( FnKind < ' a > ) ,
46
+ }
47
+
41
48
struct AstValidator < ' a > {
42
49
session : & ' a Session ,
43
50
@@ -56,7 +63,7 @@ struct AstValidator<'a> {
56
63
/// e.g., `impl Iterator<Item = impl Debug>`.
57
64
outer_impl_trait : Option < Span > ,
58
65
59
- is_tilde_const_allowed : bool ,
66
+ disallow_tilde_const : Option < DisallowTildeConstContext < ' a > > ,
60
67
61
68
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
62
69
/// or `Foo::Bar<impl Trait>`
@@ -93,18 +100,26 @@ impl<'a> AstValidator<'a> {
93
100
self . is_impl_trait_banned = old;
94
101
}
95
102
96
- fn with_tilde_const ( & mut self , allowed : bool , f : impl FnOnce ( & mut Self ) ) {
97
- let old = mem:: replace ( & mut self . is_tilde_const_allowed , allowed) ;
103
+ fn with_tilde_const (
104
+ & mut self ,
105
+ disallowed : Option < DisallowTildeConstContext < ' a > > ,
106
+ f : impl FnOnce ( & mut Self ) ,
107
+ ) {
108
+ let old = mem:: replace ( & mut self . disallow_tilde_const , disallowed) ;
98
109
f ( self ) ;
99
- self . is_tilde_const_allowed = old;
110
+ self . disallow_tilde_const = old;
100
111
}
101
112
102
113
fn with_tilde_const_allowed ( & mut self , f : impl FnOnce ( & mut Self ) ) {
103
- self . with_tilde_const ( true , f)
114
+ self . with_tilde_const ( None , f)
104
115
}
105
116
106
- fn with_banned_tilde_const ( & mut self , f : impl FnOnce ( & mut Self ) ) {
107
- self . with_tilde_const ( false , f)
117
+ fn with_banned_tilde_const (
118
+ & mut self ,
119
+ ctx : DisallowTildeConstContext < ' a > ,
120
+ f : impl FnOnce ( & mut Self ) ,
121
+ ) {
122
+ self . with_tilde_const ( Some ( ctx) , f)
108
123
}
109
124
110
125
fn with_let_management (
@@ -172,7 +187,7 @@ impl<'a> AstValidator<'a> {
172
187
fn with_impl_trait ( & mut self , outer : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
173
188
let old = mem:: replace ( & mut self . outer_impl_trait , outer) ;
174
189
if outer. is_some ( ) {
175
- self . with_banned_tilde_const ( f) ;
190
+ self . with_banned_tilde_const ( DisallowTildeConstContext :: ImplTrait , f) ;
176
191
} else {
177
192
f ( self ) ;
178
193
}
@@ -197,7 +212,10 @@ impl<'a> AstValidator<'a> {
197
212
TyKind :: ImplTrait ( ..) => {
198
213
self . with_impl_trait ( Some ( t. span ) , |this| visit:: walk_ty ( this, t) )
199
214
}
200
- TyKind :: TraitObject ( ..) => self . with_banned_tilde_const ( |this| visit:: walk_ty ( this, t) ) ,
215
+ TyKind :: TraitObject ( ..) => self
216
+ . with_banned_tilde_const ( DisallowTildeConstContext :: TraitObject , |this| {
217
+ visit:: walk_ty ( this, t)
218
+ } ) ,
201
219
TyKind :: Path ( ref qself, ref path) => {
202
220
// We allow these:
203
221
// - `Option<impl Trait>`
@@ -1411,13 +1429,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1411
1429
) ;
1412
1430
err. emit ( ) ;
1413
1431
}
1414
- ( _, TraitBoundModifier :: MaybeConst ) => {
1415
- if !self . is_tilde_const_allowed {
1416
- self . err_handler ( )
1417
- . struct_span_err ( bound. span ( ) , "`~const` is not allowed here" )
1418
- . note ( "only allowed on bounds on functions, traits' associated types and functions, const impls and its associated functions" )
1419
- . emit ( ) ;
1420
- }
1432
+ ( _, TraitBoundModifier :: MaybeConst ) if let Some ( reason) = & self . disallow_tilde_const => {
1433
+ let mut err = self . err_handler ( ) . struct_span_err ( bound. span ( ) , "`~const` is not allowed here" ) ;
1434
+ match reason {
1435
+ DisallowTildeConstContext :: TraitObject => err. note ( "trait objects cannot have `~const` trait bounds" ) ,
1436
+ DisallowTildeConstContext :: ImplTrait => err. note ( "`impl Trait`s cannot have `~const` trait bounds" ) ,
1437
+ DisallowTildeConstContext :: Fn ( FnKind :: Closure ( ..) ) => err. note ( "closures cannot have `~const` trait bounds" ) ,
1438
+ DisallowTildeConstContext :: Fn ( FnKind :: Fn ( _, ident, ..) ) => err. span_note ( ident. span , "this function is not `const`, so it cannot have `~const` trait bounds" ) ,
1439
+ } ;
1440
+ err. emit ( ) ;
1421
1441
}
1422
1442
( _, TraitBoundModifier :: MaybeConstMaybe ) => {
1423
1443
self . err_handler ( )
@@ -1523,10 +1543,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1523
1543
} ) ;
1524
1544
}
1525
1545
1526
- let tilde_const_allowed = matches ! ( fk. header( ) , Some ( FnHeader { .. } ) )
1527
- || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) ) ;
1546
+ let tilde_const_allowed =
1547
+ matches ! ( fk. header( ) , Some ( FnHeader { constness: ast:: Const :: Yes ( _) , .. } ) )
1548
+ || matches ! ( fk. ctxt( ) , Some ( FnCtxt :: Assoc ( _) ) ) ;
1549
+
1550
+ let disallowed = ( !tilde_const_allowed) . then ( || DisallowTildeConstContext :: Fn ( fk) ) ;
1528
1551
1529
- self . with_tilde_const ( tilde_const_allowed , |this| visit:: walk_fn ( this, fk) ) ;
1552
+ self . with_tilde_const ( disallowed , |this| visit:: walk_fn ( this, fk) ) ;
1530
1553
}
1531
1554
1532
1555
fn visit_assoc_item ( & mut self , item : & ' a AssocItem , ctxt : AssocCtxt ) {
@@ -1770,7 +1793,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
1770
1793
in_const_trait_impl : false ,
1771
1794
has_proc_macro_decls : false ,
1772
1795
outer_impl_trait : None ,
1773
- is_tilde_const_allowed : false ,
1796
+ disallow_tilde_const : None ,
1774
1797
is_impl_trait_banned : false ,
1775
1798
is_assoc_ty_bound_banned : false ,
1776
1799
forbidden_let_reason : Some ( ForbiddenLetReason :: GenericForbidden ) ,
0 commit comments