rustc: don't visit lifetime parameters through visit_lifetime.
This commit is contained in:
parent
a1433f2f88
commit
5c76b64546
@ -580,8 +580,8 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty) {
|
|||||||
walk_list!(visitor, visit_ty, tuple_element_types);
|
walk_list!(visitor, visit_ty, tuple_element_types);
|
||||||
}
|
}
|
||||||
TyBareFn(ref function_declaration) => {
|
TyBareFn(ref function_declaration) => {
|
||||||
visitor.visit_fn_decl(&function_declaration.decl);
|
|
||||||
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
|
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
|
||||||
|
visitor.visit_fn_decl(&function_declaration.decl);
|
||||||
}
|
}
|
||||||
TyPath(ref qpath) => {
|
TyPath(ref qpath) => {
|
||||||
visitor.visit_qpath(qpath, typ.id, typ.span);
|
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
|
|||||||
pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) {
|
pub fn walk_generic_param<'v, V: Visitor<'v>>(visitor: &mut V, param: &'v GenericParam) {
|
||||||
match *param {
|
match *param {
|
||||||
GenericParam::Lifetime(ref ld) => {
|
GenericParam::Lifetime(ref ld) => {
|
||||||
visitor.visit_lifetime(&ld.lifetime);
|
visitor.visit_id(ld.lifetime.id);
|
||||||
|
match ld.lifetime.name {
|
||||||
|
LifetimeName::Name(name) => {
|
||||||
|
visitor.visit_name(ld.lifetime.span, name);
|
||||||
|
}
|
||||||
|
LifetimeName::Fresh(_) |
|
||||||
|
LifetimeName::Static |
|
||||||
|
LifetimeName::Implicit |
|
||||||
|
LifetimeName::Underscore => {}
|
||||||
|
}
|
||||||
walk_list!(visitor, visit_lifetime, &ld.bounds);
|
walk_list!(visitor, visit_lifetime, &ld.bounds);
|
||||||
}
|
}
|
||||||
GenericParam::Type(ref ty_param) => {
|
GenericParam::Type(ref ty_param) => {
|
||||||
|
@ -1214,7 +1214,13 @@ impl<'a> LoweringContext<'a> {
|
|||||||
if let &hir::Ty_::TyBareFn(_) = &t.node {
|
if let &hir::Ty_::TyBareFn(_) = &t.node {
|
||||||
let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
|
let old_collect_elided_lifetimes = self.collect_elided_lifetimes;
|
||||||
self.collect_elided_lifetimes = false;
|
self.collect_elided_lifetimes = false;
|
||||||
|
|
||||||
|
// Record the "stack height" of `for<'a>` lifetime bindings
|
||||||
|
// to be able to later fully undo their introduction.
|
||||||
|
let old_len = self.currently_bound_lifetimes.len();
|
||||||
hir::intravisit::walk_ty(self, t);
|
hir::intravisit::walk_ty(self, t);
|
||||||
|
self.currently_bound_lifetimes.truncate(old_len);
|
||||||
|
|
||||||
self.collect_elided_lifetimes = old_collect_elided_lifetimes;
|
self.collect_elided_lifetimes = old_collect_elided_lifetimes;
|
||||||
} else {
|
} else {
|
||||||
hir::intravisit::walk_ty(self, t);
|
hir::intravisit::walk_ty(self, t);
|
||||||
@ -1223,28 +1229,25 @@ impl<'a> LoweringContext<'a> {
|
|||||||
|
|
||||||
fn visit_poly_trait_ref(
|
fn visit_poly_trait_ref(
|
||||||
&mut self,
|
&mut self,
|
||||||
polytr: &'v hir::PolyTraitRef,
|
trait_ref: &'v hir::PolyTraitRef,
|
||||||
_: hir::TraitBoundModifier,
|
modifier: hir::TraitBoundModifier,
|
||||||
) {
|
) {
|
||||||
|
// Record the "stack height" of `for<'a>` lifetime bindings
|
||||||
|
// to be able to later fully undo their introduction.
|
||||||
let old_len = self.currently_bound_lifetimes.len();
|
let old_len = self.currently_bound_lifetimes.len();
|
||||||
|
hir::intravisit::walk_poly_trait_ref(self, trait_ref, modifier);
|
||||||
|
self.currently_bound_lifetimes.truncate(old_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn visit_generic_param(&mut self, param: &'v hir::GenericParam) {
|
||||||
// Record the introduction of 'a in `for<'a> ...`
|
// Record the introduction of 'a in `for<'a> ...`
|
||||||
for param in &polytr.bound_generic_params {
|
if let hir::GenericParam::Lifetime(ref lt_def) = *param {
|
||||||
if let hir::GenericParam::Lifetime(ref lt_def) = *param {
|
// Introduce lifetimes one at a time so that we can handle
|
||||||
// Introduce lifetimes one at a time so that we can handle
|
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
|
||||||
// cases like `fn foo<'d>() -> impl for<'a, 'b: 'a, 'c: 'b + 'd>`
|
self.currently_bound_lifetimes.push(lt_def.lifetime.name);
|
||||||
self.currently_bound_lifetimes.push(lt_def.lifetime.name);
|
|
||||||
|
|
||||||
// Visit the lifetime bounds
|
|
||||||
for lt_bound in <_def.bounds {
|
|
||||||
self.visit_lifetime(<_bound);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
hir::intravisit::walk_trait_ref(self, &polytr.trait_ref);
|
hir::intravisit::walk_generic_param(self, param);
|
||||||
|
|
||||||
self.currently_bound_lifetimes.truncate(old_len);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
|
fn visit_lifetime(&mut self, lifetime: &'v hir::Lifetime) {
|
||||||
|
@ -346,12 +346,16 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_generics(&mut self, generics: &'hir Generics) {
|
fn visit_generic_param(&mut self, param: &'hir GenericParam) {
|
||||||
for ty_param in generics.ty_params() {
|
match *param {
|
||||||
self.insert(ty_param.id, NodeTyParam(ty_param));
|
GenericParam::Lifetime(ref ld) => {
|
||||||
|
self.insert(ld.lifetime.id, NodeLifetime(&ld.lifetime));
|
||||||
|
}
|
||||||
|
GenericParam::Type(ref ty_param) => {
|
||||||
|
self.insert(ty_param.id, NodeTyParam(ty_param));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
intravisit::walk_generic_param(self, param);
|
||||||
intravisit::walk_generics(self, generics);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
|
fn visit_trait_item(&mut self, ti: &'hir TraitItem) {
|
||||||
|
@ -1928,10 +1928,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn visit_generic_param(&mut self, param: &hir::GenericParam) {
|
fn visit_generic_param(&mut self, param: &hir::GenericParam) {
|
||||||
if let hir::GenericParam::Lifetime(ref lifetime_def) = *param {
|
if let hir::GenericParam::Lifetime(_) = *param {
|
||||||
for l in &lifetime_def.bounds {
|
// FIXME(eddyb) Do we want this? It only makes a difference
|
||||||
self.visit_lifetime(l);
|
// if this `for<'a>` lifetime parameter is never used.
|
||||||
}
|
self.have_bound_regions = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
intravisit::walk_generic_param(self, param);
|
intravisit::walk_generic_param(self, param);
|
||||||
@ -2144,28 +2144,26 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||||||
|
|
||||||
fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) {
|
fn check_lifetime_params(&mut self, old_scope: ScopeRef, params: &'tcx [hir::GenericParam]) {
|
||||||
for (i, lifetime_i) in params.lifetimes().enumerate() {
|
for (i, lifetime_i) in params.lifetimes().enumerate() {
|
||||||
for lifetime in params.lifetimes() {
|
match lifetime_i.lifetime.name {
|
||||||
match lifetime.lifetime.name {
|
hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
|
||||||
hir::LifetimeName::Static | hir::LifetimeName::Underscore => {
|
let lifetime = lifetime_i.lifetime;
|
||||||
let lifetime = lifetime.lifetime;
|
let name = lifetime.name.name();
|
||||||
let name = lifetime.name.name();
|
let mut err = struct_span_err!(
|
||||||
let mut err = struct_span_err!(
|
self.tcx.sess,
|
||||||
self.tcx.sess,
|
lifetime.span,
|
||||||
lifetime.span,
|
E0262,
|
||||||
E0262,
|
"invalid lifetime parameter name: `{}`",
|
||||||
"invalid lifetime parameter name: `{}`",
|
name
|
||||||
name
|
);
|
||||||
);
|
err.span_label(
|
||||||
err.span_label(
|
lifetime.span,
|
||||||
lifetime.span,
|
format!("{} is a reserved lifetime name", name),
|
||||||
format!("{} is a reserved lifetime name", name),
|
);
|
||||||
);
|
err.emit();
|
||||||
err.emit();
|
|
||||||
}
|
|
||||||
hir::LifetimeName::Fresh(_)
|
|
||||||
| hir::LifetimeName::Implicit
|
|
||||||
| hir::LifetimeName::Name(_) => {}
|
|
||||||
}
|
}
|
||||||
|
hir::LifetimeName::Fresh(_)
|
||||||
|
| hir::LifetimeName::Implicit
|
||||||
|
| hir::LifetimeName::Name(_) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
// It is a hard error to shadow a lifetime within the same scope.
|
// It is a hard error to shadow a lifetime within the same scope.
|
||||||
@ -2347,31 +2345,18 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
|
|||||||
| Region::LateBound(_, def_id, _)
|
| Region::LateBound(_, def_id, _)
|
||||||
| Region::EarlyBound(_, def_id, _) => {
|
| Region::EarlyBound(_, def_id, _) => {
|
||||||
// A lifetime declared by the user.
|
// A lifetime declared by the user.
|
||||||
let def_local_id = self.tcx.hir.as_local_node_id(def_id).unwrap();
|
let track_lifetime_uses = self.track_lifetime_uses();
|
||||||
if def_local_id == lifetime_ref.id {
|
debug!(
|
||||||
// This is weird. Because the HIR defines a
|
"insert_lifetime: track_lifetime_uses={}",
|
||||||
// lifetime *definition* as wrapping a Lifetime,
|
track_lifetime_uses
|
||||||
// we wind up invoking this method also for the
|
);
|
||||||
// definitions in some cases (notably
|
if track_lifetime_uses && !self.lifetime_uses.contains_key(&def_id) {
|
||||||
// higher-ranked types). This means that a
|
debug!("insert_lifetime: first use of {:?}", def_id);
|
||||||
// lifetime with one use (e.g., `for<'a> fn(&'a
|
self.lifetime_uses
|
||||||
// u32)`) wind up being counted as two uses. To
|
.insert(def_id, LifetimeUseSet::One(lifetime_ref));
|
||||||
// avoid that, we just ignore the lifetime that
|
|
||||||
// corresponds to the definition.
|
|
||||||
} else {
|
} else {
|
||||||
let track_lifetime_uses = self.track_lifetime_uses();
|
debug!("insert_lifetime: many uses of {:?}", def_id);
|
||||||
debug!(
|
self.lifetime_uses.insert(def_id, LifetimeUseSet::Many);
|
||||||
"insert_lifetime: track_lifetime_uses={}",
|
|
||||||
track_lifetime_uses
|
|
||||||
);
|
|
||||||
if track_lifetime_uses && !self.lifetime_uses.contains_key(&def_id) {
|
|
||||||
debug!("insert_lifetime: first use of {:?}", def_id);
|
|
||||||
self.lifetime_uses
|
|
||||||
.insert(def_id, LifetimeUseSet::One(lifetime_ref));
|
|
||||||
} else {
|
|
||||||
debug!("insert_lifetime: many uses of {:?}", def_id);
|
|
||||||
self.lifetime_uses.insert(def_id, LifetimeUseSet::Many);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2424,31 +2409,20 @@ fn insert_late_bound_lifetimes(
|
|||||||
let mut appears_in_where_clause = AllCollector {
|
let mut appears_in_where_clause = AllCollector {
|
||||||
regions: FxHashSet(),
|
regions: FxHashSet(),
|
||||||
};
|
};
|
||||||
|
appears_in_where_clause.visit_generics(generics);
|
||||||
|
|
||||||
for param in &generics.params {
|
for param in &generics.params {
|
||||||
match *param {
|
match *param {
|
||||||
hir::GenericParam::Lifetime(ref lifetime_def) => {
|
hir::GenericParam::Lifetime(ref lifetime_def) => {
|
||||||
if !lifetime_def.bounds.is_empty() {
|
if !lifetime_def.bounds.is_empty() {
|
||||||
// `'a: 'b` means both `'a` and `'b` are referenced
|
// `'a: 'b` means both `'a` and `'b` are referenced
|
||||||
appears_in_where_clause.visit_generic_param(param);
|
appears_in_where_clause.regions.insert(lifetime_def.lifetime.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hir::GenericParam::Type(ref ty_param) => {
|
hir::GenericParam::Type(_) => {}
|
||||||
walk_list!(
|
|
||||||
&mut appears_in_where_clause,
|
|
||||||
visit_ty_param_bound,
|
|
||||||
&ty_param.bounds
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
walk_list!(
|
|
||||||
&mut appears_in_where_clause,
|
|
||||||
visit_where_predicate,
|
|
||||||
&generics.where_clause.predicates
|
|
||||||
);
|
|
||||||
|
|
||||||
debug!(
|
debug!(
|
||||||
"insert_late_bound_lifetimes: appears_in_where_clause={:?}",
|
"insert_late_bound_lifetimes: appears_in_where_clause={:?}",
|
||||||
appears_in_where_clause.regions
|
appears_in_where_clause.regions
|
||||||
|
@ -441,6 +441,13 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
|||||||
visit::walk_generics(self, g)
|
visit::walk_generics(self, g)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn visit_generic_param(&mut self, param: &'a GenericParam) {
|
||||||
|
if let GenericParam::Lifetime(ref ld) = *param {
|
||||||
|
self.check_lifetime(ld.lifetime.ident);
|
||||||
|
}
|
||||||
|
visit::walk_generic_param(self, param);
|
||||||
|
}
|
||||||
|
|
||||||
fn visit_pat(&mut self, pat: &'a Pat) {
|
fn visit_pat(&mut self, pat: &'a Pat) {
|
||||||
match pat.node {
|
match pat.node {
|
||||||
PatKind::Lit(ref expr) => {
|
PatKind::Lit(ref expr) => {
|
||||||
|
@ -318,8 +318,8 @@ pub fn walk_ty<'a, V: Visitor<'a>>(visitor: &mut V, typ: &'a Ty) {
|
|||||||
walk_list!(visitor, visit_ty, tuple_element_types);
|
walk_list!(visitor, visit_ty, tuple_element_types);
|
||||||
}
|
}
|
||||||
TyKind::BareFn(ref function_declaration) => {
|
TyKind::BareFn(ref function_declaration) => {
|
||||||
walk_fn_decl(visitor, &function_declaration.decl);
|
|
||||||
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
|
walk_list!(visitor, visit_generic_param, &function_declaration.generic_params);
|
||||||
|
walk_fn_decl(visitor, &function_declaration.decl);
|
||||||
}
|
}
|
||||||
TyKind::Path(ref maybe_qself, ref path) => {
|
TyKind::Path(ref maybe_qself, ref path) => {
|
||||||
if let Some(ref qself) = *maybe_qself {
|
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
|
|||||||
pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
|
pub fn walk_generic_param<'a, V: Visitor<'a>>(visitor: &mut V, param: &'a GenericParam) {
|
||||||
match *param {
|
match *param {
|
||||||
GenericParam::Lifetime(ref l) => {
|
GenericParam::Lifetime(ref l) => {
|
||||||
visitor.visit_lifetime(&l.lifetime);
|
visitor.visit_ident(l.lifetime.ident);
|
||||||
walk_list!(visitor, visit_lifetime, &l.bounds);
|
walk_list!(visitor, visit_lifetime, &l.bounds);
|
||||||
walk_list!(visitor, visit_attribute, &*l.attrs);
|
walk_list!(visitor, visit_attribute, &*l.attrs);
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@ impl<'a> Meh<'a> for u8 {}
|
|||||||
|
|
||||||
fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
|
fn meh() -> Box<for<'_> Meh<'_>> //~ ERROR invalid lifetime parameter name: `'_`
|
||||||
//~^ ERROR missing lifetime specifier
|
//~^ ERROR missing lifetime specifier
|
||||||
//~^^ ERROR missing lifetime specifier
|
|
||||||
{
|
{
|
||||||
Box::new(5u8)
|
Box::new(5u8)
|
||||||
}
|
}
|
||||||
|
17
src/test/run-pass/issue-51185.rs
Normal file
17
src/test/run-pass/issue-51185.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
|
||||||
|
// file at the top-level directory of this distribution and at
|
||||||
|
// http://rust-lang.org/COPYRIGHT.
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
||||||
|
// option. This file may not be copied, modified, or distributed
|
||||||
|
// except according to those terms.
|
||||||
|
|
||||||
|
fn foo() -> impl Into<for<'a> fn(&'a ())> {
|
||||||
|
(|_| {}) as for<'a> fn(&'a ())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
foo().into()(&());
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user