mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
Rollup merge of #63501 - nikomatsakis:issue-63500-async-anon-impl-lifetime, r=cramertj
use `ParamName` to track in-scope lifetimes instead of Ident Also, clear in-scope lifetimes when visiting nested items. Fixes #63500. Fixes #63225. Fixes #52532. r? @cramertj
This commit is contained in:
commit
5741e29417
@ -136,7 +136,10 @@ pub struct LoweringContext<'a> {
|
||||
/// When `is_collectin_in_band_lifetimes` is true, each lifetime is checked
|
||||
/// against this list to see if it is already in-scope, or if a definition
|
||||
/// needs to be created for it.
|
||||
in_scope_lifetimes: Vec<Ident>,
|
||||
///
|
||||
/// We always store a `modern()` version of the param-name in this
|
||||
/// vector.
|
||||
in_scope_lifetimes: Vec<ParamName>,
|
||||
|
||||
current_module: NodeId,
|
||||
|
||||
@ -822,7 +825,7 @@ impl<'a> LoweringContext<'a> {
|
||||
return;
|
||||
}
|
||||
|
||||
if self.in_scope_lifetimes.contains(&ident.modern()) {
|
||||
if self.in_scope_lifetimes.contains(&ParamName::Plain(ident.modern())) {
|
||||
return;
|
||||
}
|
||||
|
||||
@ -856,7 +859,7 @@ impl<'a> LoweringContext<'a> {
|
||||
{
|
||||
let old_len = self.in_scope_lifetimes.len();
|
||||
let lt_def_names = params.iter().filter_map(|param| match param.kind {
|
||||
GenericParamKind::Lifetime { .. } => Some(param.ident.modern()),
|
||||
GenericParamKind::Lifetime { .. } => Some(ParamName::Plain(param.ident.modern())),
|
||||
_ => None,
|
||||
});
|
||||
self.in_scope_lifetimes.extend(lt_def_names);
|
||||
@ -2271,10 +2274,14 @@ impl<'a> LoweringContext<'a> {
|
||||
let lifetime_params: Vec<(Span, ParamName)> =
|
||||
this.in_scope_lifetimes
|
||||
.iter().cloned()
|
||||
.map(|ident| (ident.span, ParamName::Plain(ident)))
|
||||
.map(|name| (name.ident().span, name))
|
||||
.chain(this.lifetimes_to_define.iter().cloned())
|
||||
.collect();
|
||||
|
||||
debug!("lower_async_fn_ret_ty: in_scope_lifetimes={:#?}", this.in_scope_lifetimes);
|
||||
debug!("lower_async_fn_ret_ty: lifetimes_to_define={:#?}", this.lifetimes_to_define);
|
||||
debug!("lower_async_fn_ret_ty: lifetime_params={:#?}", lifetime_params);
|
||||
|
||||
let generic_params =
|
||||
lifetime_params
|
||||
.iter().cloned()
|
||||
|
@ -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 {
|
||||
@ -123,7 +125,7 @@ impl LoweringContext<'_> {
|
||||
_ => &[],
|
||||
};
|
||||
let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind {
|
||||
hir::GenericParamKind::Lifetime { .. } => Some(param.name.ident().modern()),
|
||||
hir::GenericParamKind::Lifetime { .. } => Some(param.name.modern()),
|
||||
_ => None,
|
||||
});
|
||||
self.in_scope_lifetimes.extend(lt_def_names);
|
||||
@ -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<T>(
|
||||
&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,
|
||||
|
@ -0,0 +1,17 @@
|
||||
// Check that `async fn` inside of an impl with `'_`
|
||||
// in the header compiles correctly.
|
||||
//
|
||||
// Regression test for #63500.
|
||||
//
|
||||
// check-pass
|
||||
// edition:2018
|
||||
|
||||
#![feature(async_await)]
|
||||
|
||||
struct Foo<'a>(&'a u8);
|
||||
|
||||
impl Foo<'_> {
|
||||
async fn bar() {}
|
||||
}
|
||||
|
||||
fn main() { }
|
17
src/test/ui/async-await/nested-in-impl.rs
Normal file
17
src/test/ui/async-await/nested-in-impl.rs
Normal file
@ -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() { }
|
20
src/test/ui/in-band-lifetimes/nested-items.rs
Normal file
20
src/test/ui/in-band-lifetimes/nested-items.rs
Normal file
@ -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() { }
|
Loading…
Reference in New Issue
Block a user