@@ -24,6 +24,7 @@ use syntax::{span_err, struct_span_err, walk_list};
24
24
25
25
use rustc_error_codes:: * ;
26
26
27
+ /// A syntactic context that disallows certain kinds of bounds (e.g., `?Trait` or `?const Trait`).
27
28
#[ derive( Clone , Copy ) ]
28
29
enum BoundContext {
29
30
ImplTrait ,
@@ -50,10 +51,11 @@ struct AstValidator<'a> {
50
51
/// e.g., `impl Iterator<Item = impl Debug>`.
51
52
outer_impl_trait : Option < Span > ,
52
53
53
- /// Tracks the context in which a bound can appear .
54
+ /// Keeps track of the `BoundContext` as we recurse .
54
55
///
55
- /// This is used to forbid `?const Trait` bounds in certain contexts.
56
- bound_context_stack : Vec < Option < BoundContext > > ,
56
+ /// This is used to forbid `?const Trait` bounds in, e.g.,
57
+ /// `impl Iterator<Item = Box<dyn ?const Trait>`.
58
+ bound_context : Option < BoundContext > ,
57
59
58
60
/// Used to ban `impl Trait` in path projections like `<impl Iterator>::Item`
59
61
/// or `Foo::Bar<impl Trait>`
@@ -80,21 +82,19 @@ impl<'a> AstValidator<'a> {
80
82
}
81
83
82
84
fn with_impl_trait ( & mut self , outer : Option < Span > , f : impl FnOnce ( & mut Self ) ) {
83
- self . bound_context_stack . push ( outer. map ( |_| BoundContext :: ImplTrait ) ) ;
84
85
let old = mem:: replace ( & mut self . outer_impl_trait , outer) ;
85
- f ( self ) ;
86
+ if outer. is_some ( ) {
87
+ self . with_bound_context ( BoundContext :: ImplTrait , |this| f ( this) ) ;
88
+ } else {
89
+ f ( self )
90
+ }
86
91
self . outer_impl_trait = old;
87
- self . bound_context_stack . pop ( ) ;
88
92
}
89
93
90
- fn with_bound_context ( & mut self , ctx : Option < BoundContext > , f : impl FnOnce ( & mut Self ) ) {
91
- self . bound_context_stack . push ( ctx) ;
94
+ fn with_bound_context ( & mut self , ctx : BoundContext , f : impl FnOnce ( & mut Self ) ) {
95
+ let old = self . bound_context . replace ( ctx) ;
92
96
f ( self ) ;
93
- self . bound_context_stack . pop ( ) ;
94
- }
95
-
96
- fn innermost_bound_context ( & mut self ) -> Option < BoundContext > {
97
- self . bound_context_stack . iter ( ) . rev ( ) . find ( |x| x. is_some ( ) ) . copied ( ) . flatten ( )
97
+ self . bound_context = old;
98
98
}
99
99
100
100
fn visit_assoc_ty_constraint_from_generic_args ( & mut self , constraint : & ' a AssocTyConstraint ) {
@@ -119,9 +119,7 @@ impl<'a> AstValidator<'a> {
119
119
self . with_impl_trait ( Some ( t. span ) , |this| visit:: walk_ty ( this, t) )
120
120
}
121
121
TyKind :: TraitObject ( ..) => {
122
- self . with_bound_context ( Some ( BoundContext :: TraitObject ) , |this| {
123
- visit:: walk_ty ( this, t)
124
- } ) ;
122
+ self . with_bound_context ( BoundContext :: TraitObject , |this| visit:: walk_ty ( this, t) ) ;
125
123
}
126
124
TyKind :: Path ( ref qself, ref path) => {
127
125
// We allow these:
@@ -231,8 +229,7 @@ impl<'a> AstValidator<'a> {
231
229
}
232
230
}
233
231
234
- // FIXME(ecstaticmorse): Instead, use the `bound_context_stack` to check this in
235
- // `visit_param_bound`.
232
+ // FIXME(ecstaticmorse): Instead, use `bound_context` to check this in `visit_param_bound`.
236
233
fn no_questions_in_bounds ( & self , bounds : & GenericBounds , where_ : & str , is_trait : bool ) {
237
234
for bound in bounds {
238
235
if let GenericBound :: Trait ( ref poly, TraitBoundModifier :: Maybe ) = * bound {
@@ -725,7 +722,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
725
722
self . visit_vis ( & item. vis ) ;
726
723
self . visit_ident ( item. ident ) ;
727
724
self . visit_generics ( generics) ;
728
- self . with_bound_context ( Some ( BoundContext :: TraitBounds ) , |this| {
725
+ self . with_bound_context ( BoundContext :: TraitBounds , |this| {
729
726
walk_list ! ( this, visit_param_bound, bounds) ;
730
727
} ) ;
731
728
walk_list ! ( self , visit_trait_item, trait_items) ;
@@ -884,7 +881,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
884
881
. span_err ( bound. span ( ) , "`?const` and `?` are mutually exclusive" ) ;
885
882
}
886
883
887
- if let Some ( ctx) = self . innermost_bound_context ( ) {
884
+ if let Some ( ctx) = self . bound_context {
888
885
let msg = format ! ( "`?const` is not permitted in {}" , ctx. description( ) ) ;
889
886
self . err_handler ( ) . span_err ( bound. span ( ) , & msg) ;
890
887
}
@@ -1006,7 +1003,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut lint::LintBuffe
1006
1003
session,
1007
1004
has_proc_macro_decls : false ,
1008
1005
outer_impl_trait : None ,
1009
- bound_context_stack : Vec :: new ( ) ,
1006
+ bound_context : None ,
1010
1007
is_impl_trait_banned : false ,
1011
1008
is_assoc_ty_bound_banned : false ,
1012
1009
lint_buffer : lints,
0 commit comments