Refactor visit_fn.
This commit is contained in:
parent
80c6a1f275
commit
237e267b80
2 changed files with 97 additions and 66 deletions
|
@ -746,36 +746,43 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
self.diagnostic_metadata.current_function = Some((fn_kind, sp));
|
self.diagnostic_metadata.current_function = Some((fn_kind, sp));
|
||||||
}
|
}
|
||||||
debug!("(resolving function) entering function");
|
debug!("(resolving function) entering function");
|
||||||
let declaration = fn_kind.decl();
|
|
||||||
|
|
||||||
// Create a value rib for the function.
|
// Create a value rib for the function.
|
||||||
self.with_rib(ValueNS, rib_kind, |this| {
|
self.with_rib(ValueNS, rib_kind, |this| {
|
||||||
// Create a label rib for the function.
|
// Create a label rib for the function.
|
||||||
this.with_label_rib(FnItemRibKind, |this| {
|
this.with_label_rib(FnItemRibKind, |this| {
|
||||||
let async_node_id = fn_kind.header().and_then(|h| h.asyncness.opt_return_id());
|
match fn_kind {
|
||||||
|
FnKind::Fn(_, _, sig, _, generics, body) => {
|
||||||
if let FnKind::Fn(_, _, _, _, generics, _) = fn_kind {
|
|
||||||
this.visit_generics(generics);
|
this.visit_generics(generics);
|
||||||
}
|
|
||||||
|
|
||||||
if let Some(async_node_id) = async_node_id {
|
let declaration = &sig.decl;
|
||||||
// In `async fn`, argument-position elided lifetimes
|
let async_node_id = sig.header.asyncness.opt_return_id();
|
||||||
// must be transformed into fresh generic parameters so that
|
|
||||||
// they can be applied to the opaque `impl Trait` return type.
|
// Argument-position elided lifetimes must be transformed into fresh
|
||||||
|
// generic parameters. This is especially useful for `async fn`, where
|
||||||
|
// these fresh generic parameters can be applied to the opaque `impl Trait`
|
||||||
|
// return type.
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousCreateParameter(fn_id),
|
if async_node_id.is_some() {
|
||||||
|this| {
|
LifetimeRibKind::AnonymousCreateParameter(fn_id)
|
||||||
// Add each argument to the rib.
|
} else {
|
||||||
this.resolve_params(&declaration.inputs)
|
LifetimeRibKind::AnonymousPassThrough(fn_id, false)
|
||||||
},
|
},
|
||||||
|
// Add each argument to the rib.
|
||||||
|
|this| this.resolve_params(&declaration.inputs),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Construct the list of in-scope lifetime parameters for async lowering.
|
// Construct the list of in-scope lifetime parameters for async lowering.
|
||||||
// We include all lifetime parameters, either named or "Fresh".
|
// We include all lifetime parameters, either named or "Fresh".
|
||||||
// The order of those parameters does not matter, as long as it is
|
// The order of those parameters does not matter, as long as it is
|
||||||
// deterministic.
|
// deterministic.
|
||||||
let mut extra_lifetime_params =
|
if let Some(async_node_id) = async_node_id {
|
||||||
this.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
|
let mut extra_lifetime_params = this
|
||||||
|
.r
|
||||||
|
.extra_lifetime_params_map
|
||||||
|
.get(&fn_id)
|
||||||
|
.cloned()
|
||||||
|
.unwrap_or_default();
|
||||||
for rib in this.lifetime_ribs.iter().rev() {
|
for rib in this.lifetime_ribs.iter().rev() {
|
||||||
extra_lifetime_params.extend(
|
extra_lifetime_params.extend(
|
||||||
rib.bindings
|
rib.bindings
|
||||||
|
@ -784,9 +791,9 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
);
|
);
|
||||||
match rib.kind {
|
match rib.kind {
|
||||||
LifetimeRibKind::Item => break,
|
LifetimeRibKind::Item => break,
|
||||||
LifetimeRibKind::AnonymousCreateParameter(id) => {
|
LifetimeRibKind::AnonymousCreateParameter(binder) => {
|
||||||
if let Some(earlier_fresh) =
|
if let Some(earlier_fresh) =
|
||||||
this.r.extra_lifetime_params_map.get(&id)
|
this.r.extra_lifetime_params_map.get(&binder)
|
||||||
{
|
{
|
||||||
extra_lifetime_params.extend(earlier_fresh);
|
extra_lifetime_params.extend(earlier_fresh);
|
||||||
}
|
}
|
||||||
|
@ -794,23 +801,48 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
|
this.r
|
||||||
|
.extra_lifetime_params_map
|
||||||
|
.insert(async_node_id, extra_lifetime_params);
|
||||||
|
}
|
||||||
|
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousPassThrough(async_node_id, true),
|
LifetimeRibKind::AnonymousPassThrough(
|
||||||
|
// For async fn, the return type appears inside a custom
|
||||||
|
// `impl Future` RPIT, so we override the binder's id.
|
||||||
|
async_node_id.unwrap_or(fn_id),
|
||||||
|
true,
|
||||||
|
),
|
||||||
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
||||||
);
|
);
|
||||||
} else {
|
|
||||||
// Add each argument to the rib.
|
if let Some(body) = body {
|
||||||
|
// Ignore errors in function bodies if this is rustdoc
|
||||||
|
// Be sure not to set this until the function signature has been resolved.
|
||||||
|
let previous_state = replace(&mut this.in_func_body, true);
|
||||||
|
// Resolve the function body, potentially inside the body of an async closure
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
|
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
|
||||||
|
|this| this.visit_block(body),
|
||||||
|
);
|
||||||
|
|
||||||
|
debug!("(resolving function) leaving function");
|
||||||
|
this.in_func_body = previous_state;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FnKind::Closure(declaration, body) => {
|
||||||
|
// Do not attempt to create generic lifetime parameters.
|
||||||
|
// FIXME: Revisit this decision once `for<>` bounds on closures become a
|
||||||
|
// thing.
|
||||||
|
this.with_lifetime_rib(
|
||||||
|
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
|
||||||
|
// Add each argument to the rib.
|
||||||
|this| this.resolve_params(&declaration.inputs),
|
|this| this.resolve_params(&declaration.inputs),
|
||||||
);
|
);
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousPassThrough(fn_id, true),
|
LifetimeRibKind::AnonymousPassThrough(fn_id, true),
|
||||||
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
|this| visit::walk_fn_ret_ty(this, &declaration.output),
|
||||||
);
|
);
|
||||||
};
|
|
||||||
|
|
||||||
// Ignore errors in function bodies if this is rustdoc
|
// Ignore errors in function bodies if this is rustdoc
|
||||||
// Be sure not to set this until the function signature has been resolved.
|
// Be sure not to set this until the function signature has been resolved.
|
||||||
|
@ -818,14 +850,13 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
|
||||||
// Resolve the function body, potentially inside the body of an async closure
|
// Resolve the function body, potentially inside the body of an async closure
|
||||||
this.with_lifetime_rib(
|
this.with_lifetime_rib(
|
||||||
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
|
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
|
||||||
|this| match fn_kind {
|
|this| this.visit_expr(body),
|
||||||
FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
|
|
||||||
FnKind::Closure(_, body) => this.visit_expr(body),
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
debug!("(resolving function) leaving function");
|
debug!("(resolving function) leaving function");
|
||||||
this.in_func_body = previous_state;
|
this.in_func_body = previous_state;
|
||||||
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
self.diagnostic_metadata.current_function = previous_value;
|
self.diagnostic_metadata.current_function = previous_value;
|
||||||
|
|
|
@ -11,7 +11,7 @@ LL | | }
|
||||||
|
|
|
|
||||||
= note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>`
|
= note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>`
|
||||||
found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
|
found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
|
||||||
note: the anonymous lifetime #1 defined here...
|
note: the anonymous lifetime as defined here...
|
||||||
--> $DIR/issue-37884.rs:6:5
|
--> $DIR/issue-37884.rs:6:5
|
||||||
|
|
|
|
||||||
LL | fn next(&'a mut self) -> Option<Self::Item>
|
LL | fn next(&'a mut self) -> Option<Self::Item>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue