From f66de50f8a0b98f539f9882115cb1d1aa4c8e182 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 29 Apr 2022 18:48:48 +0200 Subject: [PATCH 1/2] Use the correct lifetime binder for elided lifetimes in path. --- compiler/rustc_resolve/src/late.rs | 25 +++++++++++-------- .../elided-lifetime-in-path-in-impl-Fn.rs | 19 ++++++++++++++ 2 files changed, 33 insertions(+), 11 deletions(-) create mode 100644 src/test/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 9ea66c0b59d9f..31f30f39c87f3 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1319,7 +1319,8 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { | PathSource::Struct | PathSource::TupleStruct(..) => false, }; - let mut error = false; + let mut error = true; + let mut res = LifetimeRes::Error; for rib in self.lifetime_ribs.iter().rev() { match rib.kind { // In create-parameter mode we error here because we don't want to support @@ -1329,7 +1330,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // impl Foo for std::cell::Ref // note lack of '_ // async fn foo(_: std::cell::Ref) { ... } LifetimeRibKind::AnonymousCreateParameter(_) => { - error = true; break; } // `PassThrough` is the normal case. @@ -1338,19 +1338,22 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // `PathSegment`, for which there is no associated `'_` or `&T` with no explicit // lifetime. Instead, we simply create an implicit lifetime, which will be checked // later, at which point a suitable error will be emitted. - LifetimeRibKind::AnonymousPassThrough(..) - | LifetimeRibKind::AnonymousReportError - | LifetimeRibKind::Item => break, + LifetimeRibKind::AnonymousPassThrough(binder) => { + error = false; + res = LifetimeRes::Anonymous { binder, elided: true }; + break; + } + LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => { + // FIXME(cjgillot) This resolution is wrong, but this does not matter + // since these cases are erroneous anyway. + res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true }; + error = false; + break; + } _ => {} } } - let res = if error { - LifetimeRes::Error - } else { - LifetimeRes::Anonymous { binder: segment_id, elided: true } - }; - let node_ids = self.r.next_node_ids(expected_lifetimes); self.record_lifetime_res( segment_id, diff --git a/src/test/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs b/src/test/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs new file mode 100644 index 0000000000000..9c9965d8fb8b5 --- /dev/null +++ b/src/test/ui/lifetimes/elided-lifetime-in-path-in-impl-Fn.rs @@ -0,0 +1,19 @@ +// check-pass + +struct Foo<'a>(&'a ()); + +fn with_fn() -> fn(Foo) { + |_| () +} + +fn with_impl_fn() -> impl Fn(Foo) { + |_| () +} + +fn with_where_fn() +where + T: Fn(Foo), +{ +} + +fn main() {} From 6e349c7f075d6791eec4c90aa3f2865dfd594da7 Mon Sep 17 00:00:00 2001 From: Camille GILLOT Date: Fri, 29 Apr 2022 22:26:22 +0200 Subject: [PATCH 2/2] Remove `error` variable. --- compiler/rustc_resolve/src/late.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 31f30f39c87f3..21b888c25c25f 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1319,7 +1319,6 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { | PathSource::Struct | PathSource::TupleStruct(..) => false, }; - let mut error = true; let mut res = LifetimeRes::Error; for rib in self.lifetime_ribs.iter().rev() { match rib.kind { @@ -1339,15 +1338,14 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // lifetime. Instead, we simply create an implicit lifetime, which will be checked // later, at which point a suitable error will be emitted. LifetimeRibKind::AnonymousPassThrough(binder) => { - error = false; res = LifetimeRes::Anonymous { binder, elided: true }; break; } LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => { // FIXME(cjgillot) This resolution is wrong, but this does not matter - // since these cases are erroneous anyway. + // since these cases are erroneous anyway. Lifetime resolution should + // emit a "missing lifetime specifier" diagnostic. res = LifetimeRes::Anonymous { binder: DUMMY_NODE_ID, elided: true }; - error = false; break; } _ => {} @@ -1377,7 +1375,7 @@ impl<'a: 'ast, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> { // originating from macros, since the segment's span might be from a macro arg. segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span) }; - if error { + if let LifetimeRes::Error = res { let sess = self.r.session; let mut err = rustc_errors::struct_span_err!( sess,