Skip to content

Commit e4756e6

Browse files
committed
clear in-scope lifetimes for nested items in HIR lowering
This was causing us to incorrectly think the lifetimes were already declared on the scope for the nested item, when in fact they are not inherited.
1 parent a02a171 commit e4756e6

File tree

3 files changed

+65
-4
lines changed

3 files changed

+65
-4
lines changed

src/librustc/hir/lowering/item.rs

+28-4
Original file line numberDiff line numberDiff line change
@@ -60,10 +60,12 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> {
6060
fn visit_item(&mut self, item: &'tcx Item) {
6161
let mut item_hir_id = None;
6262
self.lctx.with_hir_id_owner(item.id, |lctx| {
63-
if let Some(hir_item) = lctx.lower_item(item) {
64-
item_hir_id = Some(hir_item.hir_id);
65-
lctx.insert_item(hir_item);
66-
}
63+
lctx.without_in_scope_lifetime_defs(|lctx| {
64+
if let Some(hir_item) = lctx.lower_item(item) {
65+
item_hir_id = Some(hir_item.hir_id);
66+
lctx.insert_item(hir_item);
67+
}
68+
})
6769
});
6870

6971
if let Some(hir_id) = item_hir_id {
@@ -134,6 +136,28 @@ impl LoweringContext<'_> {
134136
res
135137
}
136138

139+
// Clears (and restores) the `in_scope_lifetimes` field. Used when
140+
// visiting nested items, which never inherit in-scope lifetimes
141+
// from their surrounding environment.
142+
fn without_in_scope_lifetime_defs<T>(
143+
&mut self,
144+
f: impl FnOnce(&mut LoweringContext<'_>) -> T,
145+
) -> T {
146+
let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]);
147+
148+
// this vector is only used when walking over impl headers,
149+
// input types, and the like, and should not be non-empty in
150+
// between items
151+
assert!(self.lifetimes_to_define.is_empty());
152+
153+
let res = f(self);
154+
155+
assert!(self.in_scope_lifetimes.is_empty());
156+
self.in_scope_lifetimes = old_in_scope_lifetimes;
157+
158+
res
159+
}
160+
137161
pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod {
138162
hir::Mod {
139163
inner: m.inner,
+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
// Test that async fn works when nested inside of
2+
// impls with lifetime parameters.
3+
//
4+
// check-pass
5+
// edition:2018
6+
7+
#![feature(async_await)]
8+
9+
struct Foo<'a>(&'a ());
10+
11+
impl<'a> Foo<'a> {
12+
fn test() {
13+
async fn test() {}
14+
}
15+
}
16+
17+
fn main() { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
// Test that the `'a` from the impl doesn't
2+
// prevent us from creating a `'a` parameter
3+
// on the `blah` function.
4+
//
5+
// check-pass
6+
7+
#![feature(in_band_lifetimes)]
8+
9+
struct Foo<'a> {
10+
x: &'a u32
11+
12+
}
13+
14+
impl Foo<'a> {
15+
fn method(&self) {
16+
fn blah(f: Foo<'a>) { }
17+
}
18+
}
19+
20+
fn main() { }

0 commit comments

Comments
 (0)