@@ -11,6 +11,8 @@ use rustc_span::symbol::sym;
11
11
use rustc_span:: Span ;
12
12
use rustc_target:: spec:: abi;
13
13
14
+ use crate :: errors:: ForbiddenLifetimeBound ;
15
+
14
16
macro_rules! gate_feature_fn {
15
17
( $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr, $help: expr) => { {
16
18
let ( visitor, has_feature, span, name, explain, help) =
@@ -136,6 +138,34 @@ impl<'a> PostExpansionVisitor<'a> {
136
138
}
137
139
ImplTraitVisitor { vis : self } . visit_ty ( ty) ;
138
140
}
141
+
142
+ fn check_late_bound_lifetime_defs ( & self , params : & [ ast:: GenericParam ] ) {
143
+ // Check only lifetime parameters are present and that the lifetime
144
+ // parameters that are present have no bounds.
145
+ let non_lt_param_spans: Vec < _ > = params
146
+ . iter ( )
147
+ . filter_map ( |param| match param. kind {
148
+ ast:: GenericParamKind :: Lifetime { .. } => None ,
149
+ _ => Some ( param. ident . span ) ,
150
+ } )
151
+ . collect ( ) ;
152
+ // FIXME: gate_feature_post doesn't really handle multispans...
153
+ if !non_lt_param_spans. is_empty ( ) && !self . features . non_lifetime_binders {
154
+ feature_err (
155
+ & self . sess . parse_sess ,
156
+ sym:: non_lifetime_binders,
157
+ non_lt_param_spans,
158
+ rustc_errors:: fluent:: ast_passes_forbidden_non_lifetime_param,
159
+ )
160
+ . emit ( ) ;
161
+ }
162
+ for param in params {
163
+ if !param. bounds . is_empty ( ) {
164
+ let spans: Vec < _ > = param. bounds . iter ( ) . map ( |b| b. span ( ) ) . collect ( ) ;
165
+ self . sess . emit_err ( ForbiddenLifetimeBound { spans } ) ;
166
+ }
167
+ }
168
+ }
139
169
}
140
170
141
171
impl < ' a > Visitor < ' a > for PostExpansionVisitor < ' a > {
@@ -147,7 +177,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
147
177
..
148
178
} ) = attr_info
149
179
{
150
- gate_feature_fn ! ( self , has_feature, attr. span, * name, descr) ;
180
+ gate_feature_fn ! ( self , has_feature, attr. span, * name, * descr) ;
151
181
}
152
182
// Check unstable flavors of the `#[doc]` attribute.
153
183
if attr. has_name ( sym:: doc) {
@@ -306,6 +336,7 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
306
336
ast:: TyKind :: BareFn ( bare_fn_ty) => {
307
337
// Function pointers cannot be `const`
308
338
self . check_extern ( bare_fn_ty. ext , ast:: Const :: No ) ;
339
+ self . check_late_bound_lifetime_defs ( & bare_fn_ty. generic_params ) ;
309
340
}
310
341
ast:: TyKind :: Never => {
311
342
gate_feature_post ! ( & self , never_type, ty. span, "the `!` type is experimental" ) ;
@@ -318,6 +349,19 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
318
349
visit:: walk_ty ( self , ty)
319
350
}
320
351
352
+ fn visit_generics ( & mut self , g : & ' a ast:: Generics ) {
353
+ for predicate in & g. where_clause . predicates {
354
+ match predicate {
355
+ ast:: WherePredicate :: BoundPredicate ( bound_pred) => {
356
+ // A type binding, eg `for<'c> Foo: Send+Clone+'c`
357
+ self . check_late_bound_lifetime_defs ( & bound_pred. bound_generic_params ) ;
358
+ }
359
+ _ => { }
360
+ }
361
+ }
362
+ visit:: walk_generics ( self , g) ;
363
+ }
364
+
321
365
fn visit_fn_ret_ty ( & mut self , ret_ty : & ' a ast:: FnRetTy ) {
322
366
if let ast:: FnRetTy :: Ty ( output_ty) = ret_ty {
323
367
if let ast:: TyKind :: Never = output_ty. kind {
@@ -437,12 +481,21 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
437
481
visit:: walk_pat ( self , pattern)
438
482
}
439
483
484
+ fn visit_poly_trait_ref ( & mut self , t : & ' a ast:: PolyTraitRef ) {
485
+ self . check_late_bound_lifetime_defs ( & t. bound_generic_params ) ;
486
+ visit:: walk_poly_trait_ref ( self , t) ;
487
+ }
488
+
440
489
fn visit_fn ( & mut self , fn_kind : FnKind < ' a > , span : Span , _: NodeId ) {
441
490
if let Some ( header) = fn_kind. header ( ) {
442
491
// Stability of const fn methods are covered in `visit_assoc_item` below.
443
492
self . check_extern ( header. ext , header. constness ) ;
444
493
}
445
494
495
+ if let FnKind :: Closure ( ast:: ClosureBinder :: For { generic_params, .. } , ..) = fn_kind {
496
+ self . check_late_bound_lifetime_defs ( generic_params) ;
497
+ }
498
+
446
499
if fn_kind. ctxt ( ) != Some ( FnCtxt :: Foreign ) && fn_kind. decl ( ) . c_variadic ( ) {
447
500
gate_feature_post ! ( & self , c_variadic, span, "C-variadic functions are unstable" ) ;
448
501
}
0 commit comments