@@ -38,6 +38,13 @@ enum SelfSemantic {
3838 No ,
3939}
4040
41+ /// What is the context that prevents using `~const`?
42+ enum DisallowTildeConstContext < ' a > {
43+ TraitObject ,
44+ ImplTrait ,
45+ Fn ( FnKind < ' a > ) ,
46+ }
47+
4148struct AstValidator < ' a > {
4249 session : & ' a Session ,
4350
@@ -56,7 +63,7 @@ struct AstValidator<'a> {
5663 /// e.g., `impl Iterator<Item = impl Debug>`.
5764 outer_impl_trait : Option < Span > ,
5865
59- is_tilde_const_allowed : bool ,
66+ disallow_tilde_const : Option < DisallowTildeConstContext < ' a > > ,
6067
6168 /// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
6269 /// or `Foo::Bar<impl Trait>`
@@ -93,18 +100,26 @@ impl<'a> AstValidator<'a> {
93100 self . is_impl_trait_banned = old;
94101 }
95102
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) ;
98109 f ( self ) ;
99- self . is_tilde_const_allowed = old;
110+ self . disallow_tilde_const = old;
100111 }
101112
102113 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)
104115 }
105116
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)
108123 }
109124
110125 fn with_let_management (
@@ -172,7 +187,7 @@ impl<'a> AstValidator<'a> {
172187 fn with_impl_trait ( & mut self , outer : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
173188 let old = mem:: replace ( & mut self . outer_impl_trait , outer) ;
174189 if outer. is_some ( ) {
175- self . with_banned_tilde_const ( f) ;
190+ self . with_banned_tilde_const ( DisallowTildeConstContext :: ImplTrait , f) ;
176191 } else {
177192 f ( self ) ;
178193 }
@@ -197,7 +212,10 @@ impl<'a> AstValidator<'a> {
197212 TyKind :: ImplTrait ( ..) => {
198213 self . with_impl_trait ( Some ( t. span ) , |this| visit:: walk_ty ( this, t) )
199214 }
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+ } ) ,
201219 TyKind :: Path ( ref qself, ref path) => {
202220 // We allow these:
203221 // - `Option<impl Trait>`
@@ -1411,13 +1429,15 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
14111429 ) ;
14121430 err. emit ( ) ;
14131431 }
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 ( ) ;
14211441 }
14221442 ( _, TraitBoundModifier :: MaybeConstMaybe ) => {
14231443 self . err_handler ( )
@@ -1523,10 +1543,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
15231543 } ) ;
15241544 }
15251545
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) ) ;
15281551
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) ) ;
15301553 }
15311554
15321555 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) ->
17701793 in_const_trait_impl : false ,
17711794 has_proc_macro_decls : false ,
17721795 outer_impl_trait : None ,
1773- is_tilde_const_allowed : false ,
1796+ disallow_tilde_const : None ,
17741797 is_impl_trait_banned : false ,
17751798 is_assoc_ty_bound_banned : false ,
17761799 forbidden_let_reason : Some ( ForbiddenLetReason :: GenericForbidden ) ,
0 commit comments