summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2018-05-30 20:34:23 +0000
committerbors <bors@rust-lang.org>2018-05-30 20:34:23 +0000
commit5d0631a6438cf30cac236b7176371663e35c8d07 (patch)
tree967fe0282e0a8383a02341435ccec59b7dd157e1
parentAuto merge of #51100 - estebank:as-ref, r=oli-obk (diff)
parentrustc: don't visit lifetime parameters through visit_lifetime. (diff)
downloadgrust-5d0631a6438cf30cac236b7176371663e35c8d07.tar.gz
grust-5d0631a6438cf30cac236b7176371663e35c8d07.tar.bz2
grust-5d0631a6438cf30cac236b7176371663e35c8d07.tar.xz
Auto merge of #51215 - eddyb:visit-for-a-lifetime, r=nikomatsakis
rustc: don't visit lifetime parameters through visit_lifetime. Ideally we'd also not use the `Lifetime` struct for parameters, but I'll leave that to @varkor (#48149). Fixes #51185 (discovered while auditing all the `visit_lifetime` implementations). r? @nikomatsakis
-rw-r--r--src/librustc/hir/intravisit.rs13
-rw-r--r--src/librustc/hir/lowering.rs35
-rw-r--r--src/librustc/hir/map/collector.rs14
-rw-r--r--src/librustc/middle/resolve_lifetime.rs100
-rw-r--r--src/librustc_passes/ast_validation.rs7
-rw-r--r--src/libsyntax/fold.rs74
-rw-r--r--src/libsyntax/visit.rs4
-rw-r--r--src/test/compile-fail/underscore-lifetime-binders.rs1
-rw-r--r--src/test/run-pass/issue-51185.rs17
9 files changed, 122 insertions, 143 deletions
diff --git a/src/librustc/hir/intravisit.rs b/src/librustc/hir/intravisit.rs
index 5a49ee30d9..5471568d0a 100644
--- a/src/librustc/hir/intravisit.rs
+++ b/src/librustc/hir/intravisit.rs
@@ -580,8 +580,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
580 walk_list!(visitor, visit_ty, tuple_element_types); 580 walk_list!(visitor, visit_ty, tuple_element_types);
581 } 581 }
582 TyBareFn(ref function_declaration) => { 582 TyBareFn(ref function_declaration) => {
583 visitor.visit_fn_decl(&function_declaration.decl);
584 walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); 583 walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
584 visitor.visit_fn_decl(&function_declaration.decl);
585 } 585 }
586 TyPath(ref qpath) => { 586 TyPath(ref qpath) => {
587 visitor.visit_qpath(qpath, typ.id, typ.span); 587 visitor.visit_qpath(qpath, typ.id, typ.span);
@@ -733,7 +733,16 @@ pub fn walk_ty_param_bound<'v, V: Visitor<'v>>(visitor: &mut V, bound: &'v TyPar
733pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) { 733pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) {
734 match *param { 734 match *param {
735 GenericParam::Lifetime(ref ld) => { 735 GenericParam::Lifetime(ref ld) => {
736 visitor.visit_lifetime(&ld.lifetime); 736 visitor.visit_id(ld.lifetime.id);
737 match ld.lifetime.name {
738 LifetimeName::Name(name) => {
739 visitor.visit_name(ld.lifetime.span, name);
740 }
741 LifetimeName::Fresh(_) |
742 LifetimeName::Static |
743 LifetimeName::Implicit |
744 LifetimeName::Underscore => {}
745 }
737 walk_list!(visitor, visit_lifetime, &ld.bounds); 746 walk_list!(visitor, visit_lifetime, &ld.bounds);
738 } 747 }
739 GenericParam::Type(ref ty_param) => { 748 GenericParam::Type(ref ty_param) => {
diff --git a/src/librustc/hir/lowering.rs b/src/librustc/hir/lowering.rs
index f24a803bac..af269078b6 100644
--- a/src/librustc/hir/lowering.rs
+++ b/src/librustc/hir/lowering.rs
@@ -1214,7 +1214,13 @@ impl<'a> LoweringContext<'a> {
1214 if let &hir::Ty_::TyBareFn(_) = &t.node { 1214 if let &hir::Ty_::TyBareFn(_) = &t.node {
1215 let old_collect_elided_lifetimes = self.collect_elided_lifetimes; 1215 let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
1216 self.collect_elided_lifetimes = false; 1216 self.collect_elided_lifetimes = false;
1217
1218 // Record the "stack height" of `for<'a>` lifetime bindings
1219 // to be able to later fully undo their introduction.
1220 let old_len = self.currently_bound_lifetimes.len();
1217 hir::intravisit::walk_ty(self, t); 1221 hir::intravisit::walk_ty(self, t);
1222 self.currently_bound_lifetimes.truncate(old_len);
1223
1218 self.collect_elided_lifetimes = old_collect_elided_lifetimes; 1224 self.collect_elided_lifetimes = old_collect_elided_lifetimes;
1219 } else { 1225 } else {
1220 hir::intravisit::walk_ty(self, t); 1226 hir::intravisit::walk_ty(self, t);
@@ -1223,28 +1229,25 @@ impl<'a> LoweringContext<'a> {
1223 1229
1224 fn visit_poly_trait_ref( 1230 fn visit_poly_trait_ref(
1225 &mut self, 1231 &mut self,
1226 polytr: &'v hir::PolyTraitRef, 1232 trait_ref: &'v hir::PolyTraitRef,
1227 _: hir::TraitBoundModifier, 1233 modifier: hir::TraitBoundModifier,
1228 ) { 1234 ) {
1235 // Record the "stack height" of `for<'a>` lifetime bindings
1236 // to be able to later fully undo their introduction.
1229 let old_len = self.currently_bound_lifetimes.len(); 1237 let old_len = self.currently_bound_lifetimes.len();
1238 hir::intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
1239 self.currently_bound_lifetimes.truncate(old_len);
1240 }
1230 1241
1242 fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
1231 // Record the introduction of 'a in `for<'a> ...` 1243 // Record the introduction of 'a in `for<'a> ...`
1232 for param in &polytr.bound_generic_params { 1244 if let hir::GenericParam::Lifetime(ref lt_def) = *param {
1233 if let hir::GenericParam::Lifetime(ref lt_def) = *param { 1245 // Introduce lifetimes one at a time so that we can handle
1234 // Introduce lifetimes one at a time so that we can handle 1246 // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
1235 // cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>` 1247 self.currently_bound_lifetimes.push(lt_def.lifetime.name);
1236 self.currently_bound_lifetimes.push(lt_def.lifetime.name);
1237
1238 // Visit the lifetime bounds
1239 for lt_bound in &lt_def.bounds {
1240 self.visit_lifetime(&lt_bound);
1241 }
1242 }
1243 } 1248 }
1244 1249
1245 hir::intravisit::walk_trait_ref(self, &polytr.trait_ref); 1250 hir::intravisit::walk_generic_param(self, param);
1246
1247 self.currently_bound_lifetimes.truncate(old_len);
1248 } 1251 }
1249 1252
1250 fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) { 1253 fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
diff --git a/src/librustc/hir/map/collector.rs b/src/librustc/hir/map/collector.rs
index 8f28dfab1e..13df1ced60 100644
--- a/src/librustc/hir/map/collector.rs
+++ b/src/librustc/hir/map/collector.rs
@@ -346,12 +346,16 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
346 }); 346 });
347 } 347 }
348 348
349 fn visit_generics(&mut self, generics: &'hir Generics) { 349 fn visit_generic_param(&mut self, param: &'hir GenericParam) {
350 for ty_param in generics.ty_params() { 350 match *param {
351 self.insert(ty_param.id, NodeTyParam(ty_param)); 351 GenericParam::Lifetime(ref ld) => {
352 self.insert(ld.lifetime.id, NodeLifetime(&ld.lifetime));
353 }
354 GenericParam::Type(ref ty_param) => {
355 self.insert(ty_param.id, NodeTyParam(ty_param));
356 }
352 } 357 }
353 358 intravisit::walk_generic_param(self, param);
354 intravisit::walk_generics(self, generics);
355 } 359 }
356 360
357 fn visit_trait_item(&mut self, ti: &'hir TraitItem) { 361 fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
diff --git a/src/librustc/middle/resolve_lifetime.rs b/src/librustc/middle/resolve_lifetime.rs
index 53d51d9429..c82597813e 100644
--- a/src/librustc/middle/resolve_lifetime.rs
+++ b/src/librustc/middle/resolve_lifetime.rs
@@ -1928,10 +1928,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
1928 } 1928 }
1929 1929
1930 fn visit_generic_param(&mut self, param: &hir::GenericParam) { 1930 fn visit_generic_param(&mut self, param: &hir::GenericParam) {
1931 if let hir::GenericParam::Lifetime(ref lifetime_def) = *param { 1931 if let hir::GenericParam::Lifetime(_) = *param {
1932 for l in &lifetime_def.bounds { 1932 // FIXME(eddyb) Do we want this? It only makes a difference
1933 self.visit_lifetime(l); 1933 // if this `for<'a>` lifetime parameter is never used.
1934 } 1934 self.have_bound_regions = true;
1935 } 1935 }
1936 1936
1937 intravisit::walk_generic_param(self, param); 1937 intravisit::walk_generic_param(self, param);
@@ -2144,28 +2144,26 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2144 2144
2145 fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) { 2145 fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) {
2146 for (i, lifetime_i) in params.lifetimes().enumerate() { 2146 for (i, lifetime_i) in params.lifetimes().enumerate() {
2147 for lifetime in params.lifetimes() { 2147 match lifetime_i.lifetime.name {
2148 match lifetime.lifetime.name { 2148 hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
2149 hir::LifetimeName::Static | hir::LifetimeName::Underscore => { 2149 let lifetime = lifetime_i.lifetime;
2150 let lifetime = lifetime.lifetime; 2150 let name = lifetime.name.name();
2151 let name = lifetime.name.name(); 2151 let mut err = struct_span_err!(
2152 let mut err = struct_span_err!( 2152 self.tcx.sess,
2153 self.tcx.sess, 2153 lifetime.span,
2154 lifetime.span, 2154 E0262,
2155 E0262, 2155 "invalid lifetime parameter name: `{}`",
2156 "invalid lifetime parameter name: `{}`", 2156 name
2157 name 2157 );
2158 ); 2158 err.span_label(
2159 err.span_label( 2159 lifetime.span,
2160 lifetime.span, 2160 format!("{} is a reserved lifetime name", name),
2161 format!("{} is a reserved lifetime name", name), 2161 );
2162 ); 2162 err.emit();
2163 err.emit();
2164 }
2165 hir::LifetimeName::Fresh(_)
2166 | hir::LifetimeName::Implicit
2167 | hir::LifetimeName::Name(_) => {}
2168 } 2163 }
2164 hir::LifetimeName::Fresh(_)
2165 | hir::LifetimeName::Implicit
2166 | hir::LifetimeName::Name(_) => {}
2169 } 2167 }
2170 2168
2171 // It is a hard error to shadow a lifetime within the same scope. 2169 // It is a hard error to shadow a lifetime within the same scope.
@@ -2347,31 +2345,18 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
2347 | Region::LateBound(_, def_id, _) 2345 | Region::LateBound(_, def_id, _)
2348 | Region::EarlyBound(_, def_id, _) => { 2346 | Region::EarlyBound(_, def_id, _) => {
2349 // A lifetime declared by the user. 2347 // A lifetime declared by the user.
2350 let def_local_id = self.tcx.hir.as_local_node_id(def_id).unwrap(); 2348 let track_lifetime_uses = self.track_lifetime_uses();
2351 if def_local_id == lifetime_ref.id { 2349 debug!(
2352 // This is weird. Because the HIR defines a 2350 "insert_lifetime: track_lifetime_uses={}",
2353 // lifetime *definition* as wrapping a Lifetime, 2351 track_lifetime_uses
2354 // we wind up invoking this method also for the 2352 );
2355 // definitions in some cases (notably 2353 if track_lifetime_uses && !self.lifetime_uses.contains_key(&def_id) {
2356 // higher-ranked types). This means that a 2354 debug!("insert_lifetime: first use of {:?}", def_id);
2357 // lifetime with one use (e.g., `for<'a> fn(&'a 2355 self.lifetime_uses
2358 // u32)`) wind up being counted as two uses. To 2356 .insert(def_id, LifetimeUseSet::One(lifetime_ref));
2359 // avoid that, we just ignore the lifetime that
2360 // corresponds to the definition.
2361 } else { 2357 } else {
2362 let track_lifetime_uses = self.track_lifetime_uses(); 2358 debug!("insert_lifetime: many uses of {:?}", def_id);
2363 debug!( 2359 self.lifetime_uses.insert(def_id, LifetimeUseSet::Many);
2364 "insert_lifetime: track_lifetime_uses={}",
2365 track_lifetime_uses
2366 );
2367 if track_lifetime_uses && !self.lifetime_uses.contains_key(&def_id) {
2368 debug!("insert_lifetime: first use of {:?}", def_id);
2369 self.lifetime_uses
2370 .insert(def_id, LifetimeUseSet::One(lifetime_ref));
2371 } else {
2372 debug!("insert_lifetime: many uses of {:?}", def_id);
2373 self.lifetime_uses.insert(def_id, LifetimeUseSet::Many);
2374 }
2375 } 2360 }
2376 } 2361 }
2377 } 2362 }
@@ -2424,31 +2409,20 @@ fn insert_late_bound_lifetimes(
2424 let mut appears_in_where_clause = AllCollector { 2409 let mut appears_in_where_clause = AllCollector {
2425 regions: FxHashSet(), 2410 regions: FxHashSet(),
2426 }; 2411 };
2412 appears_in_where_clause.visit_generics(generics);
2427 2413
2428 for param in &generics.params { 2414 for param in &generics.params {
2429 match *param { 2415 match *param {
2430 hir::GenericParam::Lifetime(ref lifetime_def) => { 2416 hir::GenericParam::Lifetime(ref lifetime_def) => {
2431 if !lifetime_def.bounds.is_empty() { 2417 if !lifetime_def.bounds.is_empty() {
2432 // `'a: 'b` means both `'a` and `'b` are referenced 2418 // `'a: 'b` means both `'a` and `'b` are referenced
2433 appears_in_where_clause.visit_generic_param(param); 2419 appears_in_where_clause.regions.insert(lifetime_def.lifetime.name);
2434 } 2420 }
2435 } 2421 }
2436 hir::GenericParam::Type(ref ty_param) => { 2422 hir::GenericParam::Type(_) => {}
2437 walk_list!(
2438 &mut appears_in_where_clause,
2439 visit_ty_param_bound,
2440 &ty_param.bounds
2441 );
2442 }
2443 } 2423 }
2444 } 2424 }
2445 2425
2446 walk_list!(
2447 &mut appears_in_where_clause,
2448 visit_where_predicate,
2449 &generics.where_clause.predicates
2450 );
2451
2452 debug!( 2426 debug!(
2453 "insert_late_bound_lifetimes: appears_in_where_clause={:?}", 2427 "insert_late_bound_lifetimes: appears_in_where_clause={:?}",
2454 appears_in_where_clause.regions 2428 appears_in_where_clause.regions
diff --git a/src/librustc_passes/ast_validation.rs b/src/librustc_passes/ast_validation.rs
index abbd399a94..39e0a53925 100644
--- a/src/librustc_passes/ast_validation.rs
+++ b/src/librustc_passes/ast_validation.rs
@@ -441,6 +441,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
441 visit::walk_generics(self, g) 441 visit::walk_generics(self, g)
442 } 442 }
443 443
444 fn visit_generic_param(&mut self, param: &'a GenericParam) {
445 if let GenericParam::Lifetime(ref ld) = *param {
446 self.check_lifetime(ld.lifetime.ident);
447 }
448 visit::walk_generic_param(self, param);
449 }
450
444 fn visit_pat(&mut self, pat: &'a Pat) { 451 fn visit_pat(&mut self, pat: &'a Pat) {
445 match pat.node { 452 match pat.node {
446 PatKind::Lit(ref expr) => { 453 PatKind::Lit(ref expr) => {
diff --git a/src/libsyntax/fold.rs b/src/libsyntax/fold.rs
index ecb4332379..2f209b347a 100644
--- a/src/libsyntax/fold.rs
+++ b/src/libsyntax/fold.rs
@@ -205,14 +205,6 @@ pub trait Folder : Sized {
205 noop_fold_label(label, self) 205 noop_fold_label(label, self)
206 } 206 }
207 207
208 fn fold_lifetime(&mut self, l: Lifetime) -> Lifetime {
209 noop_fold_lifetime(l, self)
210 }
211
212 fn fold_lifetime_def(&mut self, l: LifetimeDef) -> LifetimeDef {
213 noop_fold_lifetime_def(l, self)
214 }
215
216 fn fold_attribute(&mut self, at: Attribute) -> Option<Attribute> { 208 fn fold_attribute(&mut self, at: Attribute) -> Option<Attribute> {
217 noop_fold_attribute(at, self) 209 noop_fold_attribute(at, self)
218 } 210 }
@@ -237,14 +229,6 @@ pub trait Folder : Sized {
237 noop_fold_variant_data(vdata, self) 229 noop_fold_variant_data(vdata, self)
238 } 230 }
239 231
240 fn fold_lifetimes(&mut self, lts: Vec<Lifetime>) -> Vec<Lifetime> {
241 noop_fold_lifetimes(lts, self)
242 }
243
244 fn fold_lifetime_defs(&mut self, lts: Vec<LifetimeDef>) -> Vec<LifetimeDef> {
245 noop_fold_lifetime_defs(lts, self)
246 }
247
248 fn fold_ty_param(&mut self, tp: TyParam) -> TyParam { 232 fn fold_ty_param(&mut self, tp: TyParam) -> TyParam {
249 noop_fold_ty_param(tp, self) 233 noop_fold_ty_param(tp, self)
250 } 234 }
@@ -273,10 +257,6 @@ pub trait Folder : Sized {
273 noop_fold_interpolated(nt, self) 257 noop_fold_interpolated(nt, self)
274 } 258 }
275 259
276 fn fold_opt_lifetime(&mut self, o_lt: Option<Lifetime>) -> Option<Lifetime> {
277 noop_fold_opt_lifetime(o_lt, self)
278 }
279
280 fn fold_opt_bounds(&mut self, b: Option<TyParamBounds>) 260 fn fold_opt_bounds(&mut self, b: Option<TyParamBounds>)
281 -> Option<TyParamBounds> { 261 -> Option<TyParamBounds> {
282 noop_fold_opt_bounds(b, self) 262 noop_fold_opt_bounds(b, self)
@@ -376,7 +356,7 @@ pub fn noop_fold_ty<T: Folder>(t: P<Ty>, fld: &mut T) -> P<Ty> {
376 TyKind::Slice(ty) => TyKind::Slice(fld.fold_ty(ty)), 356 TyKind::Slice(ty) => TyKind::Slice(fld.fold_ty(ty)),
377 TyKind::Ptr(mt) => TyKind::Ptr(fld.fold_mt(mt)), 357 TyKind::Ptr(mt) => TyKind::Ptr(fld.fold_mt(mt)),
378 TyKind::Rptr(region, mt) => { 358 TyKind::Rptr(region, mt) => {
379 TyKind::Rptr(fld.fold_opt_lifetime(region), fld.fold_mt(mt)) 359 TyKind::Rptr(region.map(|lt| noop_fold_lifetime(lt, fld)), fld.fold_mt(mt))
380 } 360 }
381 TyKind::BareFn(f) => { 361 TyKind::BareFn(f) => {
382 TyKind::BareFn(f.map(|BareFnTy {generic_params, unsafety, abi, decl}| BareFnTy { 362 TyKind::BareFn(f.map(|BareFnTy {generic_params, unsafety, abi, decl}| BareFnTy {
@@ -478,7 +458,7 @@ pub fn noop_fold_angle_bracketed_parameter_data<T: Folder>(data: AngleBracketedP
478 -> AngleBracketedParameterData 458 -> AngleBracketedParameterData
479{ 459{
480 let AngleBracketedParameterData { lifetimes, types, bindings, span } = data; 460 let AngleBracketedParameterData { lifetimes, types, bindings, span } = data;
481 AngleBracketedParameterData { lifetimes: fld.fold_lifetimes(lifetimes), 461 AngleBracketedParameterData { lifetimes: lifetimes.move_map(|l| noop_fold_lifetime(l, fld)),
482 types: types.move_map(|ty| fld.fold_ty(ty)), 462 types: types.move_map(|ty| fld.fold_ty(ty)),
483 bindings: bindings.move_map(|b| fld.fold_ty_binding(b)), 463 bindings: bindings.move_map(|b| fld.fold_ty_binding(b)),
484 span: fld.new_span(span) } 464 span: fld.new_span(span) }
@@ -680,7 +660,7 @@ pub fn noop_fold_ty_param_bound<T>(tpb: TyParamBound, fld: &mut T)
680 where T: Folder { 660 where T: Folder {
681 match tpb { 661 match tpb {
682 TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier), 662 TraitTyParamBound(ty, modifier) => TraitTyParamBound(fld.fold_poly_trait_ref(ty), modifier),
683 RegionTyParamBound(lifetime) => RegionTyParamBound(fld.fold_lifetime(lifetime)), 663 RegionTyParamBound(lifetime) => RegionTyParamBound(noop_fold_lifetime(lifetime, fld)),
684 } 664 }
685} 665}
686 666
@@ -701,7 +681,20 @@ pub fn noop_fold_ty_param<T: Folder>(tp: TyParam, fld: &mut T) -> TyParam {
701 681
702pub fn noop_fold_generic_param<T: Folder>(param: GenericParam, fld: &mut T) -> GenericParam { 682pub fn noop_fold_generic_param<T: Folder>(param: GenericParam, fld: &mut T) -> GenericParam {
703 match param { 683 match param {
704 GenericParam::Lifetime(l) => GenericParam::Lifetime(fld.fold_lifetime_def(l)), 684 GenericParam::Lifetime(l) => {
685 let attrs: Vec<_> = l.attrs.into();
686 GenericParam::Lifetime(LifetimeDef {
687 attrs: attrs.into_iter()
688 .flat_map(|x| fld.fold_attribute(x).into_iter())
689 .collect::<Vec<_>>()
690 .into(),
691 lifetime: Lifetime {
692 id: fld.new_id(l.lifetime.id),
693 ident: fld.fold_ident(l.lifetime.ident),
694 },
695 bounds: l.bounds.move_map(|l| noop_fold_lifetime(l, fld)),
696 })
697 }
705 GenericParam::Type(t) => GenericParam::Type(fld.fold_ty_param(t)), 698 GenericParam::Type(t) => GenericParam::Type(fld.fold_ty_param(t)),
706 } 699 }
707} 700}
@@ -719,40 +712,13 @@ pub fn noop_fold_label<T: Folder>(label: Label, fld: &mut T) -> Label {
719 } 712 }
720} 713}
721 714
722pub fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime { 715fn noop_fold_lifetime<T: Folder>(l: Lifetime, fld: &mut T) -> Lifetime {
723 Lifetime { 716 Lifetime {
724 id: fld.new_id(l.id), 717 id: fld.new_id(l.id),
725 ident: fld.fold_ident(l.ident), 718 ident: fld.fold_ident(l.ident),
726 } 719 }
727} 720}
728 721
729pub fn noop_fold_lifetime_def<T: Folder>(l: LifetimeDef, fld: &mut T)
730 -> LifetimeDef {
731 let attrs: Vec<_> = l.attrs.into();
732 LifetimeDef {
733 attrs: attrs.into_iter()
734 .flat_map(|x| fld.fold_attribute(x).into_iter())
735 .collect::<Vec<_>>()
736 .into(),
737 lifetime: fld.fold_lifetime(l.lifetime),
738 bounds: fld.fold_lifetimes(l.bounds),
739 }
740}
741
742pub fn noop_fold_lifetimes<T: Folder>(lts: Vec<Lifetime>, fld: &mut T) -> Vec<Lifetime> {
743 lts.move_map(|l| fld.fold_lifetime(l))
744}
745
746pub fn noop_fold_lifetime_defs<T: Folder>(lts: Vec<LifetimeDef>, fld: &mut T)
747 -> Vec<LifetimeDef> {
748 lts.move_map(|l| fld.fold_lifetime_def(l))
749}
750
751pub fn noop_fold_opt_lifetime<T: Folder>(o_lt: Option<Lifetime>, fld: &mut T)
752 -> Option<Lifetime> {
753 o_lt.map(|lt| fld.fold_lifetime(lt))
754}
755
756pub fn noop_fold_generics<T: Folder>(Generics { params, where_clause, span }: Generics, 722pub fn noop_fold_generics<T: Folder>(Generics { params, where_clause, span }: Generics,
757 fld: &mut T) -> Generics { 723 fld: &mut T) -> Generics {
758 Generics { 724 Generics {
@@ -796,8 +762,8 @@ pub fn noop_fold_where_predicate<T: Folder>(
796 span}) => { 762 span}) => {
797 ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate { 763 ast::WherePredicate::RegionPredicate(ast::WhereRegionPredicate {
798 span: fld.new_span(span), 764 span: fld.new_span(span),
799 lifetime: fld.fold_lifetime(lifetime), 765 lifetime: noop_fold_lifetime(lifetime, fld),
800 bounds: bounds.move_map(|bound| fld.fold_lifetime(bound)) 766 bounds: bounds.move_map(|bound| noop_fold_lifetime(bound, fld))
801 }) 767 })
802 } 768 }
803 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id, 769 ast::WherePredicate::EqPredicate(ast::WhereEqPredicate{id,
diff --git a/src/libsyntax/visit.rs b/src/libsyntax/visit.rs
index fdf8e52bbd..dca0e2f634 100644
--- a/src/libsyntax/visit.rs
+++ b/src/libsyntax/visit.rs
@@ -318,8 +318,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
318 walk_list!(visitor, visit_ty, tuple_element_types); 318 walk_list!(visitor, visit_ty, tuple_element_types);
319 } 319 }
320 TyKind::BareFn(ref function_declaration) => { 320 TyKind::BareFn(ref function_declaration) => {
321 walk_fn_decl(visitor, &function_declaration.decl);
322 walk_list!(visitor, visit_generic_param, &function_declaration.generic_params); 321 walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
322 walk_fn_decl(visitor, &function_declaration.decl);
323 } 323 }
324 TyKind::Path(ref maybe_qself, ref path) => { 324 TyKind::Path(ref maybe_qself, ref path) => {
325 if let Some(ref qself) = *maybe_qself { 325 if let Some(ref qself) = *maybe_qself {
@@ -485,7 +485,7 @@ pub fn walk_ty_param_bound<'a, V: Visitor<'a>>(visitor: &mut V, bound: &'a TyPar
485pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) { 485pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
486 match *param { 486 match *param {
487 GenericParam::Lifetime(ref l) => { 487 GenericParam::Lifetime(ref l) => {
488 visitor.visit_lifetime(&l.lifetime); 488 visitor.visit_ident(l.lifetime.ident);
489 walk_list!(visitor, visit_lifetime, &l.bounds); 489 walk_list!(visitor, visit_lifetime, &l.bounds);
490 walk_list!(visitor, visit_attribute, &*l.attrs); 490 walk_list!(visitor, visit_attribute, &*l.attrs);
491 } 491 }
diff --git a/src/test/compile-fail/underscore-lifetime-binders.rs b/src/test/compile-fail/underscore-lifetime-binders.rs
index eb00ab5f67..6a6698957d 100644
--- a/src/test/compile-fail/underscore-lifetime-binders.rs
+++ b/src/test/compile-fail/underscore-lifetime-binders.rs
@@ -23,7 +23,6 @@ impl<'a> Meh<'a> for u8 {}
23 23
24fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_` 24fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
25//~^ ERROR missing lifetime specifier 25//~^ ERROR missing lifetime specifier
26//~^^ ERROR missing lifetime specifier
27{ 26{
28 Box::new(5u8) 27 Box::new(5u8)
29} 28}
diff --git a/src/test/run-pass/issue-51185.rs b/src/test/run-pass/issue-51185.rs
new file mode 100644
index 0000000000..8e286ad141
--- /dev/null
+++ b/src/test/run-pass/issue-51185.rs
@@ -0,0 +1,17 @@
1// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
2// file at the top-level directory of this distribution and at
3// http://rust-lang.org/COPYRIGHT.
4//
5// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8// option. This file may not be copied, modified, or distributed
9// except according to those terms.
10
11fn foo() -> impl Into<for<'a> fn(&'a ())> {
12 (|_| {}) as for<'a> fn(&'a ())
13}
14
15fn main() {
16 foo().into()(&());
17}