diff --git a/src/librustc/hir/lowering/item.rs b/src/librustc/hir/lowering/item.rs index 7b774812a24f2..dd95d99d4e1d6 100644 --- a/src/librustc/hir/lowering/item.rs +++ b/src/librustc/hir/lowering/item.rs @@ -60,10 +60,12 @@ impl<'tcx, 'interner> Visitor<'tcx> for ItemLowerer<'tcx, 'interner> { fn visit_item(&mut self, item: &'tcx Item) { let mut item_hir_id = None; self.lctx.with_hir_id_owner(item.id, |lctx| { - if let Some(hir_item) = lctx.lower_item(item) { - item_hir_id = Some(hir_item.hir_id); - lctx.insert_item(hir_item); - } + lctx.without_in_scope_lifetime_defs(|lctx| { + if let Some(hir_item) = lctx.lower_item(item) { + item_hir_id = Some(hir_item.hir_id); + lctx.insert_item(hir_item); + } + }) }); if let Some(hir_id) = item_hir_id { @@ -134,6 +136,28 @@ impl LoweringContext<'_> { res } + // Clears (and restores) the `in_scope_lifetimes` field. Used when + // visiting nested items, which never inherit in-scope lifetimes + // from their surrounding environment. + fn without_in_scope_lifetime_defs( + &mut self, + f: impl FnOnce(&mut LoweringContext<'_>) -> T, + ) -> T { + let old_in_scope_lifetimes = std::mem::replace(&mut self.in_scope_lifetimes, vec![]); + + // this vector is only used when walking over impl headers, + // input types, and the like, and should not be non-empty in + // between items + assert!(self.lifetimes_to_define.is_empty()); + + let res = f(self); + + assert!(self.in_scope_lifetimes.is_empty()); + self.in_scope_lifetimes = old_in_scope_lifetimes; + + res + } + pub(super) fn lower_mod(&mut self, m: &Mod) -> hir::Mod { hir::Mod { inner: m.inner, diff --git a/src/test/ui/async-await/nested-in-impl.rs b/src/test/ui/async-await/nested-in-impl.rs new file mode 100644 index 0000000000000..3c82160595f1d --- /dev/null +++ b/src/test/ui/async-await/nested-in-impl.rs @@ -0,0 +1,17 @@ +// Test that async fn works when nested inside of +// impls with lifetime parameters. +// +// check-pass +// edition:2018 + +#![feature(async_await)] + +struct Foo<'a>(&'a ()); + +impl<'a> Foo<'a> { + fn test() { + async fn test() {} + } +} + +fn main() { } diff --git a/src/test/ui/in-band-lifetimes/nested-items.rs b/src/test/ui/in-band-lifetimes/nested-items.rs new file mode 100644 index 0000000000000..7de20712fba94 --- /dev/null +++ b/src/test/ui/in-band-lifetimes/nested-items.rs @@ -0,0 +1,20 @@ +// Test that the `'a` from the impl doesn't +// prevent us from creating a `'a` parameter +// on the `blah` function. +// +// check-pass + +#![feature(in_band_lifetimes)] + +struct Foo<'a> { + x: &'a u32 + +} + +impl Foo<'a> { + fn method(&self) { + fn blah(f: Foo<'a>) { } + } +} + +fn main() { }