@@ -46,27 +46,33 @@ enum DisallowTildeConstContext<'a> {
46
46
Item ,
47
47
}
48
48
49
+ enum TraitOrImpl < ' a > {
50
+ Trait { span : Span , constness : Option < Span > } ,
51
+ Impl { trait_ : Option < ( Const , ImplPolarity , & ' a TraitRef ) > } ,
52
+ }
53
+
54
+ impl < ' a > TraitOrImpl < ' a > {
55
+ fn constness ( & self ) -> Option < Span > {
56
+ match self {
57
+ Self :: Trait { constness : Some ( span) , .. }
58
+ | Self :: Impl { trait_ : Some ( ( Const :: Yes ( span) , ..) ) } => Some ( * span) ,
59
+ _ => None ,
60
+ }
61
+ }
62
+
63
+ fn is_trait_or_trait_impl ( & self ) -> bool {
64
+ matches ! ( self , Self :: Trait { .. } | Self :: Impl { trait_: Some ( _) } )
65
+ }
66
+ }
67
+
49
68
struct AstValidator < ' a > {
50
69
session : & ' a Session ,
51
70
features : & ' a Features ,
52
71
53
72
/// The span of the `extern` in an `extern { ... }` block, if any.
54
73
extern_mod : Option < & ' a Item > ,
55
74
56
- /// Are we inside a trait impl?
57
- ///
58
- /// If so, this is the trait ref together with its polarity.
59
- in_trait_impl : Option < ( ImplPolarity , & ' a TraitRef ) > ,
60
-
61
- /// Are we inside a const trait defn or impl?
62
- ///
63
- /// If so, this is the span of the constness.
64
- in_const_trait_or_impl : Option < Span > ,
65
-
66
- /// Are we inside a trait?
67
- ///
68
- /// If so, this is the span of the trait.
69
- in_trait : Option < Span > ,
75
+ outer_trait_or_impl : Option < TraitOrImpl < ' a > > ,
70
76
71
77
has_proc_macro_decls : bool ,
72
78
@@ -87,31 +93,24 @@ struct AstValidator<'a> {
87
93
impl < ' a > AstValidator < ' a > {
88
94
fn with_in_trait_impl (
89
95
& mut self ,
90
- trait_ref : Option < ( Const , ImplPolarity , & ' a TraitRef ) > ,
96
+ trait_ : Option < ( Const , ImplPolarity , & ' a TraitRef ) > ,
91
97
f : impl FnOnce ( & mut Self ) ,
92
98
) {
93
99
let old = mem:: replace (
94
- & mut self . in_trait_impl ,
95
- trait_ref. map ( |( _, polarity, trait_ref) | ( polarity, trait_ref) ) ,
96
- ) ;
97
- let old_const = mem:: replace (
98
- & mut self . in_const_trait_or_impl ,
99
- match trait_ref {
100
- Some ( ( Const :: Yes ( span) , ..) ) => Some ( span) ,
101
- _ => None ,
102
- } ,
100
+ & mut self . outer_trait_or_impl ,
101
+ trait_. map ( |trait_| TraitOrImpl :: Impl { trait_ : Some ( trait_) } ) ,
103
102
) ;
104
103
f ( self ) ;
105
- self . in_trait_impl = old;
106
- self . in_const_trait_or_impl = old_const;
104
+ self . outer_trait_or_impl = old;
107
105
}
108
106
109
- fn with_in_trait ( & mut self , span : Span , is_const : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
110
- let old = mem:: replace ( & mut self . in_const_trait_or_impl , is_const) ;
111
- let old_trait = mem:: replace ( & mut self . in_trait , Some ( span) ) ;
107
+ fn with_in_trait ( & mut self , span : Span , constness : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
108
+ let old = mem:: replace (
109
+ & mut self . outer_trait_or_impl ,
110
+ Some ( TraitOrImpl :: Trait { span, constness } ) ,
111
+ ) ;
112
112
f ( self ) ;
113
- self . in_const_trait_or_impl = old;
114
- self . in_trait = old_trait;
113
+ self . outer_trait_or_impl = old;
115
114
}
116
115
117
116
fn with_banned_impl_trait ( & mut self , f : impl FnOnce ( & mut Self ) ) {
@@ -307,36 +306,36 @@ impl<'a> AstValidator<'a> {
307
306
}
308
307
}
309
308
310
- fn check_trait_fn_not_const ( & self , constness : Const ) {
309
+ fn check_trait_fn_not_const ( & self , constness : Const , trait_or_impl : & TraitOrImpl < ' a > ) {
311
310
let Const :: Yes ( span) = constness else {
312
311
return ;
313
312
} ;
314
313
315
- let make_impl_const_sugg = if self . in_const_trait_or_impl . is_none ( )
316
- && let Some ( ( ImplPolarity :: Positive , trait_ref ) ) = self . in_trait_impl
317
- && self . features . const_trait_impl
314
+ let make_impl_const_sugg = if self . features . const_trait_impl
315
+ && let TraitOrImpl :: Impl { trait_ : Some ( trait_ ) } = trait_or_impl
316
+ && let ( Const :: No , ImplPolarity :: Positive , trait_ref ) = trait_
318
317
{
319
318
Some ( trait_ref. path . span . shrink_to_lo ( ) )
320
319
} else {
321
320
None
322
321
} ;
323
322
324
- let make_trait_const_sugg = if self . in_const_trait_or_impl . is_none ( )
325
- && let Some ( trait_) = self . in_trait
326
- && self . features . const_trait_impl
323
+ let make_trait_const_sugg = if self . features . const_trait_impl
324
+ && let TraitOrImpl :: Trait { span, constness : None } = trait_or_impl
327
325
{
328
- Some ( trait_ . shrink_to_lo ( ) )
326
+ Some ( span . shrink_to_lo ( ) )
329
327
} else {
330
328
None
331
329
} ;
332
330
331
+ let parent_constness = trait_or_impl. constness ( ) ;
333
332
self . dcx ( ) . emit_err ( errors:: TraitFnConst {
334
333
span,
335
- in_impl : self . in_trait_impl . is_some ( ) ,
336
- const_context_label : self . in_const_trait_or_impl ,
334
+ in_impl : matches ! ( trait_or_impl , TraitOrImpl :: Impl { .. } ) ,
335
+ const_context_label : parent_constness ,
337
336
remove_const_sugg : (
338
337
self . session . source_map ( ) . span_extend_while ( span, |c| c == ' ' ) . unwrap_or ( span) ,
339
- match self . in_const_trait_or_impl {
338
+ match parent_constness {
340
339
Some ( _) => rustc_errors:: Applicability :: MachineApplicable ,
341
340
None => rustc_errors:: Applicability :: MaybeIncorrect ,
342
341
} ,
@@ -1391,10 +1390,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1391
1390
} ) ;
1392
1391
}
1393
1392
1394
- let tilde_const_allowed = matches ! (
1395
- fk. header( ) ,
1396
- Some ( FnHeader { constness : ast :: Const :: Yes ( _) , .. } )
1397
- ) || matches ! ( fk . ctxt ( ) , Some ( FnCtxt :: Assoc ( _ ) ) if self . in_const_trait_or_impl . is_some( ) ) ;
1393
+ let tilde_const_allowed =
1394
+ matches ! ( fk. header( ) , Some ( FnHeader { constness : ast :: Const :: Yes ( _ ) , .. } ) )
1395
+ || matches ! ( fk . ctxt ( ) , Some ( FnCtxt :: Assoc ( _) ) )
1396
+ && self . outer_trait_or_impl . as_ref ( ) . and_then ( TraitOrImpl :: constness ) . is_some ( ) ;
1398
1397
1399
1398
let disallowed = ( !tilde_const_allowed) . then ( || DisallowTildeConstContext :: Fn ( fk) ) ;
1400
1399
self . with_tilde_const ( disallowed, |this| visit:: walk_fn ( this, fk) ) ;
@@ -1405,7 +1404,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1405
1404
self . check_nomangle_item_asciionly ( item. ident , item. span ) ;
1406
1405
}
1407
1406
1408
- if ctxt == AssocCtxt :: Trait || self . in_trait_impl . is_none ( ) {
1407
+ if self . outer_trait_or_impl . as_ref ( ) . is_some_and ( TraitOrImpl :: is_trait_or_trait_impl ) {
1409
1408
self . check_defaultness ( item. span , item. kind . defaultness ( ) ) ;
1410
1409
}
1411
1410
@@ -1453,10 +1452,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1453
1452
) ;
1454
1453
}
1455
1454
1456
- if ctxt == AssocCtxt :: Trait || self . in_trait_impl . is_some ( ) {
1455
+ if let Some ( trait_or_impl) = & self . outer_trait_or_impl
1456
+ && trait_or_impl. is_trait_or_trait_impl ( )
1457
+ {
1457
1458
self . visibility_not_permitted ( & item. vis , errors:: VisibilityNotPermittedNote :: TraitImpl ) ;
1458
1459
if let AssocItemKind :: Fn ( box Fn { sig, .. } ) = & item. kind {
1459
- self . check_trait_fn_not_const ( sig. header . constness ) ;
1460
+ self . check_trait_fn_not_const ( sig. header . constness , trait_or_impl ) ;
1460
1461
}
1461
1462
}
1462
1463
@@ -1466,7 +1467,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
1466
1467
1467
1468
match & item. kind {
1468
1469
AssocItemKind :: Fn ( box Fn { sig, generics, body, .. } )
1469
- if self . in_const_trait_or_impl . is_some ( )
1470
+ if self . outer_trait_or_impl . as_ref ( ) . and_then ( TraitOrImpl :: constness ) . is_some ( )
1470
1471
|| ctxt == AssocCtxt :: Trait
1471
1472
|| matches ! ( sig. header. constness, Const :: Yes ( _) ) =>
1472
1473
{
@@ -1598,9 +1599,7 @@ pub fn check_crate(
1598
1599
session,
1599
1600
features,
1600
1601
extern_mod : None ,
1601
- in_trait_impl : None ,
1602
- in_const_trait_or_impl : None ,
1603
- in_trait : None ,
1602
+ outer_trait_or_impl : None ,
1604
1603
has_proc_macro_decls : false ,
1605
1604
outer_impl_trait : None ,
1606
1605
disallow_tilde_const : Some ( DisallowTildeConstContext :: Item ) ,
0 commit comments