Address code review feedback
This commit is contained in:
parent
26f9954971
commit
50ef8006eb
10 changed files with 53 additions and 36 deletions
|
@ -873,8 +873,9 @@ pub fn noop_visit_closure_binder<T: MutVisitor>(binder: &mut ClosureBinder, vis:
|
||||||
|
|
||||||
pub fn noop_visit_coro_kind<T: MutVisitor>(coro_kind: &mut CoroutineKind, vis: &mut T) {
|
pub fn noop_visit_coro_kind<T: MutVisitor>(coro_kind: &mut CoroutineKind, vis: &mut T) {
|
||||||
match coro_kind {
|
match coro_kind {
|
||||||
CoroutineKind::Async { span: _, closure_id, return_impl_trait_id }
|
CoroutineKind::Async { span, closure_id, return_impl_trait_id }
|
||||||
| CoroutineKind::Gen { span: _, closure_id, return_impl_trait_id } => {
|
| CoroutineKind::Gen { span, closure_id, return_impl_trait_id } => {
|
||||||
|
vis.visit_span(span);
|
||||||
vis.visit_id(closure_id);
|
vis.visit_id(closure_id);
|
||||||
vis.visit_id(return_impl_trait_id);
|
vis.visit_id(return_impl_trait_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1922,7 +1922,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
span,
|
span,
|
||||||
opaque_ty_span,
|
opaque_ty_span,
|
||||||
|this| {
|
|this| {
|
||||||
let future_bound = this.lower_coroutine_fn_output_type_to_future_bound(
|
let bound = this.lower_coroutine_fn_output_type_to_bound(
|
||||||
output,
|
output,
|
||||||
coro,
|
coro,
|
||||||
span,
|
span,
|
||||||
|
@ -1931,7 +1931,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
fn_kind,
|
fn_kind,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
arena_vec![this; future_bound]
|
arena_vec![this; bound]
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1940,7 +1940,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms `-> T` into `Future<Output = T>`.
|
/// Transforms `-> T` into `Future<Output = T>`.
|
||||||
fn lower_coroutine_fn_output_type_to_future_bound(
|
fn lower_coroutine_fn_output_type_to_bound(
|
||||||
&mut self,
|
&mut self,
|
||||||
output: &FnRetTy,
|
output: &FnRetTy,
|
||||||
coro: CoroutineKind,
|
coro: CoroutineKind,
|
||||||
|
@ -1958,21 +1958,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
|
FnRetTy::Default(ret_ty_span) => self.arena.alloc(self.ty_tup(*ret_ty_span, &[])),
|
||||||
};
|
};
|
||||||
|
|
||||||
// "<Output|Item = T>"
|
// "<$assoc_ty_name = T>"
|
||||||
let (symbol, lang_item) = match coro {
|
let (assoc_ty_name, trait_lang_item) = match coro {
|
||||||
CoroutineKind::Async { .. } => (hir::FN_OUTPUT_NAME, hir::LangItem::Future),
|
CoroutineKind::Async { .. } => (hir::FN_OUTPUT_NAME, hir::LangItem::Future),
|
||||||
CoroutineKind::Gen { .. } => (hir::ITERATOR_ITEM_NAME, hir::LangItem::Iterator),
|
CoroutineKind::Gen { .. } => (hir::ITERATOR_ITEM_NAME, hir::LangItem::Iterator),
|
||||||
};
|
};
|
||||||
|
|
||||||
let future_args = self.arena.alloc(hir::GenericArgs {
|
let future_args = self.arena.alloc(hir::GenericArgs {
|
||||||
args: &[],
|
args: &[],
|
||||||
bindings: arena_vec![self; self.assoc_ty_binding(symbol, span, output_ty)],
|
bindings: arena_vec![self; self.assoc_ty_binding(assoc_ty_name, span, output_ty)],
|
||||||
parenthesized: hir::GenericArgsParentheses::No,
|
parenthesized: hir::GenericArgsParentheses::No,
|
||||||
span_ext: DUMMY_SP,
|
span_ext: DUMMY_SP,
|
||||||
});
|
});
|
||||||
|
|
||||||
hir::GenericBound::LangItemTrait(
|
hir::GenericBound::LangItemTrait(
|
||||||
lang_item,
|
trait_lang_item,
|
||||||
self.lower_span(span),
|
self.lower_span(span),
|
||||||
self.next_id(),
|
self.next_id(),
|
||||||
future_args,
|
future_args,
|
||||||
|
|
|
@ -401,14 +401,14 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// An associated type binding `$symbol = $ty`.
|
/// An associated type binding `$assoc_ty_name = $ty`.
|
||||||
pub(crate) fn assoc_ty_binding(
|
pub(crate) fn assoc_ty_binding(
|
||||||
&mut self,
|
&mut self,
|
||||||
symbol: rustc_span::Symbol,
|
assoc_ty_name: rustc_span::Symbol,
|
||||||
span: Span,
|
span: Span,
|
||||||
ty: &'hir hir::Ty<'hir>,
|
ty: &'hir hir::Ty<'hir>,
|
||||||
) -> hir::TypeBinding<'hir> {
|
) -> hir::TypeBinding<'hir> {
|
||||||
let ident = Ident::with_dummy_span(symbol);
|
let ident = Ident::with_dummy_span(assoc_ty_name);
|
||||||
let kind = hir::TypeBindingKind::Equality { term: ty.into() };
|
let kind = hir::TypeBindingKind::Equality { term: ty.into() };
|
||||||
let args = arena_vec![self;];
|
let args = arena_vec![self;];
|
||||||
let bindings = arena_vec![self;];
|
let bindings = arena_vec![self;];
|
||||||
|
|
|
@ -1279,7 +1279,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
|
||||||
..
|
..
|
||||||
}) = fk.header()
|
}) = fk.header()
|
||||||
{
|
{
|
||||||
// FIXME(eholk): Report a different error for `const gen`
|
// FIXME(gen_blocks): Report a different error for `const gen`
|
||||||
self.err_handler().emit_err(errors::ConstAndAsync {
|
self.err_handler().emit_err(errors::ConstAndAsync {
|
||||||
spans: vec![cspan, aspan],
|
spans: vec![cspan, aspan],
|
||||||
cspan,
|
cspan,
|
||||||
|
|
|
@ -545,6 +545,10 @@ fn check_test_signature(
|
||||||
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }));
|
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "async" }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Some(ast::CoroutineKind::Gen { span, .. }) = f.sig.header.coro_kind {
|
||||||
|
return Err(sd.emit_err(errors::TestBadFn { span: i.span, cause: span, kind: "gen" }));
|
||||||
|
}
|
||||||
|
|
||||||
// If the termination trait is active, the compiler will check that the output
|
// If the termination trait is active, the compiler will check that the output
|
||||||
// type implements the `Termination` trait as `libtest` enforces that.
|
// type implements the `Termination` trait as `libtest` enforces that.
|
||||||
let has_output = match &f.sig.decl.output {
|
let has_output = match &f.sig.decl.output {
|
||||||
|
|
|
@ -2544,7 +2544,7 @@ impl<'a> Parser<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(eholk): add keyword recovery logic for genness
|
// FIXME(gen_blocks): add keyword recovery logic for genness
|
||||||
|
|
||||||
if wrong_kw.is_some()
|
if wrong_kw.is_some()
|
||||||
&& self.may_recover()
|
&& self.may_recover()
|
||||||
|
|
|
@ -612,7 +612,7 @@ impl<'a> Parser<'a> {
|
||||||
if let Some(ast::CoroutineKind::Async { span, .. }) = coro_kind {
|
if let Some(ast::CoroutineKind::Async { span, .. }) = coro_kind {
|
||||||
self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
|
self.sess.emit_err(FnPointerCannotBeAsync { span: whole_span, qualifier: span });
|
||||||
}
|
}
|
||||||
// FIXME(eholk): emit a similar error for `gen fn()`
|
// FIXME(gen_blocks): emit a similar error for `gen fn()`
|
||||||
let decl_span = span_start.to(self.token.span);
|
let decl_span = span_start.to(self.token.span);
|
||||||
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
|
Ok(TyKind::BareFn(P(BareFnTy { ext, unsafety, generic_params: params, decl, decl_span })))
|
||||||
}
|
}
|
||||||
|
|
|
@ -916,10 +916,10 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
||||||
&sig.decl.output,
|
&sig.decl.output,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((async_node_id, _)) =
|
if let Some((coro_node_id, _)) =
|
||||||
sig.header.coro_kind.map(|coro_kind| coro_kind.return_id())
|
sig.header.coro_kind.map(|coro_kind| coro_kind.return_id())
|
||||||
{
|
{
|
||||||
this.record_lifetime_params_for_impl_trait(async_node_id);
|
this.record_lifetime_params_for_impl_trait(coro_node_id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -942,13 +942,13 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
|
|
||||||
let declaration = &sig.decl;
|
let declaration = &sig.decl;
|
||||||
let async_node_id =
|
let coro_node_id =
|
||||||
sig.header.coro_kind.map(|coro_kind| coro_kind.return_id());
|
sig.header.coro_kind.map(|coro_kind| coro_kind.return_id());
|
||||||
|
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousCreateParameter {
|
LifetimeRibKind::AnonymousCreateParameter {
|
||||||
binder: fn_id,
|
binder: fn_id,
|
||||||
report_in_path: async_node_id.is_some(),
|
report_in_path: coro_node_id.is_some(),
|
||||||
},
|
},
|
||||||
|this| {
|
|this| {
|
||||||
this.resolve_fn_signature(
|
this.resolve_fn_signature(
|
||||||
|
@ -961,7 +961,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
|
||||||
&declaration.output,
|
&declaration.output,
|
||||||
);
|
);
|
||||||
|
|
||||||
if let Some((async_node_id, _)) = async_node_id {
|
if let Some((async_node_id, _)) = coro_node_id {
|
||||||
this.record_lifetime_params_for_impl_trait(async_node_id);
|
this.record_lifetime_params_for_impl_trait(async_node_id);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -4291,8 +4291,10 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
|
||||||
// `async |x| ...` gets desugared to `|x| async {...}`, so we need to
|
// `async |x| ...` gets desugared to `|x| async {...}`, so we need to
|
||||||
// resolve the arguments within the proper scopes so that usages of them inside the
|
// resolve the arguments within the proper scopes so that usages of them inside the
|
||||||
// closure are detected as upvars rather than normal closure arg usages.
|
// closure are detected as upvars rather than normal closure arg usages.
|
||||||
|
//
|
||||||
|
// Similarly, `gen |x| ...` gets desugared to `|x| gen {...}`, so we handle that too.
|
||||||
ExprKind::Closure(box ast::Closure {
|
ExprKind::Closure(box ast::Closure {
|
||||||
coro_kind: Some(CoroutineKind::Async { .. }),
|
coro_kind: Some(_),
|
||||||
ref fn_decl,
|
ref fn_decl,
|
||||||
ref body,
|
ref body,
|
||||||
..
|
..
|
||||||
|
|
|
@ -263,12 +263,10 @@ fn rewrite_closure_fn_decl(
|
||||||
} else {
|
} else {
|
||||||
""
|
""
|
||||||
};
|
};
|
||||||
let (is_async, is_gen) = if let Some(coro_kind) = coro_kind {
|
let coro = match coro_kind {
|
||||||
let is_async = if coro_kind.is_async() { "async " } else { "" };
|
Some(ast::CoroutineKind::Async { .. }) => "async ",
|
||||||
let is_gen = if coro_kind.is_gen() { "gen " } else { "" };
|
Some(ast::CoroutineKind::Gen { .. }) => "gen ",
|
||||||
(is_async, is_gen)
|
None => "",
|
||||||
} else {
|
|
||||||
("", "")
|
|
||||||
};
|
};
|
||||||
let mover = if matches!(capture, ast::CaptureBy::Value { .. }) {
|
let mover = if matches!(capture, ast::CaptureBy::Value { .. }) {
|
||||||
"move "
|
"move "
|
||||||
|
@ -278,14 +276,7 @@ fn rewrite_closure_fn_decl(
|
||||||
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
// 4 = "|| {".len(), which is overconservative when the closure consists of
|
||||||
// a single expression.
|
// a single expression.
|
||||||
let nested_shape = shape
|
let nested_shape = shape
|
||||||
.shrink_left(
|
.shrink_left(binder.len() + const_.len() + immovable.len() + coro.len() + mover.len())?
|
||||||
binder.len()
|
|
||||||
+ const_.len()
|
|
||||||
+ immovable.len()
|
|
||||||
+ is_async.len()
|
|
||||||
+ is_gen.len()
|
|
||||||
+ mover.len(),
|
|
||||||
)?
|
|
||||||
.sub_width(4)?;
|
.sub_width(4)?;
|
||||||
|
|
||||||
// 1 = |
|
// 1 = |
|
||||||
|
@ -323,7 +314,7 @@ fn rewrite_closure_fn_decl(
|
||||||
.tactic(tactic)
|
.tactic(tactic)
|
||||||
.preserve_newline(true);
|
.preserve_newline(true);
|
||||||
let list_str = write_list(&item_vec, &fmt)?;
|
let list_str = write_list(&item_vec, &fmt)?;
|
||||||
let mut prefix = format!("{binder}{const_}{immovable}{is_async}{is_gen}{mover}|{list_str}|");
|
let mut prefix = format!("{binder}{const_}{immovable}{coro}{mover}|{list_str}|");
|
||||||
|
|
||||||
if !ret_str.is_empty() {
|
if !ret_str.is_empty() {
|
||||||
if prefix.contains('\n') {
|
if prefix.contains('\n') {
|
||||||
|
|
19
tests/ui/coroutine/gen_fn_lifetime_capture.rs
Normal file
19
tests/ui/coroutine/gen_fn_lifetime_capture.rs
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
// edition: 2024
|
||||||
|
// compile-flags: -Zunstable-options
|
||||||
|
// check-pass
|
||||||
|
#![feature(gen_blocks)]
|
||||||
|
|
||||||
|
// make sure gen fn captures lifetimes in its signature
|
||||||
|
|
||||||
|
gen fn foo<'a, 'b>(x: &'a i32, y: &'b i32, z: &'b i32) -> &'b i32 {
|
||||||
|
yield y;
|
||||||
|
yield z;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let z = 3;
|
||||||
|
let mut iter = foo(&1, &2, &z);
|
||||||
|
assert_eq!(iter.next(), Some(&2));
|
||||||
|
assert_eq!(iter.next(), Some(&3));
|
||||||
|
assert_eq!(iter.next(), None);
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue