Skip to content

Commit 237e267

Browse files
committed
Refactor visit_fn.
1 parent 80c6a1f commit 237e267

File tree

2 files changed

+97
-66
lines changed

2 files changed

+97
-66
lines changed

compiler/rustc_resolve/src/late.rs

Lines changed: 96 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -746,86 +746,117 @@ impl<'a: 'ast, 'ast> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast> {
746746
self.diagnostic_metadata.current_function = Some((fn_kind, sp));
747747
}
748748
debug!("(resolving function) entering function");
749-
let declaration = fn_kind.decl();
750749

751750
// Create a value rib for the function.
752751
self.with_rib(ValueNS, rib_kind, |this| {
753752
// Create a label rib for the function.
754753
this.with_label_rib(FnItemRibKind, |this| {
755-
let async_node_id = fn_kind.header().and_then(|h| h.asyncness.opt_return_id());
754+
match fn_kind {
755+
FnKind::Fn(_, _, sig, _, generics, body) => {
756+
this.visit_generics(generics);
756757

757-
if let FnKind::Fn(_, _, _, _, generics, _) = fn_kind {
758-
this.visit_generics(generics);
759-
}
758+
let declaration = &sig.decl;
759+
let async_node_id = sig.header.asyncness.opt_return_id();
760760

761-
if let Some(async_node_id) = async_node_id {
762-
// In `async fn`, argument-position elided lifetimes
763-
// must be transformed into fresh generic parameters so that
764-
// they can be applied to the opaque `impl Trait` return type.
765-
this.with_lifetime_rib(
766-
LifetimeRibKind::AnonymousCreateParameter(fn_id),
767-
|this| {
761+
// Argument-position elided lifetimes must be transformed into fresh
762+
// generic parameters. This is especially useful for `async fn`, where
763+
// these fresh generic parameters can be applied to the opaque `impl Trait`
764+
// return type.
765+
this.with_lifetime_rib(
766+
if async_node_id.is_some() {
767+
LifetimeRibKind::AnonymousCreateParameter(fn_id)
768+
} else {
769+
LifetimeRibKind::AnonymousPassThrough(fn_id, false)
770+
},
768771
// Add each argument to the rib.
769-
this.resolve_params(&declaration.inputs)
770-
},
771-
);
772-
773-
// Construct the list of in-scope lifetime parameters for async lowering.
774-
// We include all lifetime parameters, either named or "Fresh".
775-
// The order of those parameters does not matter, as long as it is
776-
// deterministic.
777-
let mut extra_lifetime_params =
778-
this.r.extra_lifetime_params_map.get(&fn_id).cloned().unwrap_or_default();
779-
for rib in this.lifetime_ribs.iter().rev() {
780-
extra_lifetime_params.extend(
781-
rib.bindings
782-
.iter()
783-
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
772+
|this| this.resolve_params(&declaration.inputs),
784773
);
785-
match rib.kind {
786-
LifetimeRibKind::Item => break,
787-
LifetimeRibKind::AnonymousCreateParameter(id) => {
788-
if let Some(earlier_fresh) =
789-
this.r.extra_lifetime_params_map.get(&id)
790-
{
791-
extra_lifetime_params.extend(earlier_fresh);
774+
775+
// Construct the list of in-scope lifetime parameters for async lowering.
776+
// We include all lifetime parameters, either named or "Fresh".
777+
// The order of those parameters does not matter, as long as it is
778+
// deterministic.
779+
if let Some(async_node_id) = async_node_id {
780+
let mut extra_lifetime_params = this
781+
.r
782+
.extra_lifetime_params_map
783+
.get(&fn_id)
784+
.cloned()
785+
.unwrap_or_default();
786+
for rib in this.lifetime_ribs.iter().rev() {
787+
extra_lifetime_params.extend(
788+
rib.bindings
789+
.iter()
790+
.map(|(&ident, &(node_id, res))| (ident, node_id, res)),
791+
);
792+
match rib.kind {
793+
LifetimeRibKind::Item => break,
794+
LifetimeRibKind::AnonymousCreateParameter(binder) => {
795+
if let Some(earlier_fresh) =
796+
this.r.extra_lifetime_params_map.get(&binder)
797+
{
798+
extra_lifetime_params.extend(earlier_fresh);
799+
}
800+
}
801+
_ => {}
792802
}
793803
}
794-
_ => {}
804+
this.r
805+
.extra_lifetime_params_map
806+
.insert(async_node_id, extra_lifetime_params);
795807
}
796-
}
797-
this.r.extra_lifetime_params_map.insert(async_node_id, extra_lifetime_params);
798808

799-
this.with_lifetime_rib(
800-
LifetimeRibKind::AnonymousPassThrough(async_node_id, true),
801-
|this| visit::walk_fn_ret_ty(this, &declaration.output),
802-
);
803-
} else {
804-
// Add each argument to the rib.
805-
this.with_lifetime_rib(
806-
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
807-
|this| this.resolve_params(&declaration.inputs),
808-
);
809-
this.with_lifetime_rib(
810-
LifetimeRibKind::AnonymousPassThrough(fn_id, true),
811-
|this| visit::walk_fn_ret_ty(this, &declaration.output),
812-
);
813-
};
809+
this.with_lifetime_rib(
810+
LifetimeRibKind::AnonymousPassThrough(
811+
// For async fn, the return type appears inside a custom
812+
// `impl Future` RPIT, so we override the binder's id.
813+
async_node_id.unwrap_or(fn_id),
814+
true,
815+
),
816+
|this| visit::walk_fn_ret_ty(this, &declaration.output),
817+
);
814818

815-
// Ignore errors in function bodies if this is rustdoc
816-
// Be sure not to set this until the function signature has been resolved.
817-
let previous_state = replace(&mut this.in_func_body, true);
818-
// Resolve the function body, potentially inside the body of an async closure
819-
this.with_lifetime_rib(
820-
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
821-
|this| match fn_kind {
822-
FnKind::Fn(.., body) => walk_list!(this, visit_block, body),
823-
FnKind::Closure(_, body) => this.visit_expr(body),
824-
},
825-
);
819+
if let Some(body) = body {
820+
// Ignore errors in function bodies if this is rustdoc
821+
// Be sure not to set this until the function signature has been resolved.
822+
let previous_state = replace(&mut this.in_func_body, true);
823+
// Resolve the function body, potentially inside the body of an async closure
824+
this.with_lifetime_rib(
825+
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
826+
|this| this.visit_block(body),
827+
);
826828

827-
debug!("(resolving function) leaving function");
828-
this.in_func_body = previous_state;
829+
debug!("(resolving function) leaving function");
830+
this.in_func_body = previous_state;
831+
}
832+
}
833+
FnKind::Closure(declaration, body) => {
834+
// Do not attempt to create generic lifetime parameters.
835+
// FIXME: Revisit this decision once `for<>` bounds on closures become a
836+
// thing.
837+
this.with_lifetime_rib(
838+
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
839+
// Add each argument to the rib.
840+
|this| this.resolve_params(&declaration.inputs),
841+
);
842+
this.with_lifetime_rib(
843+
LifetimeRibKind::AnonymousPassThrough(fn_id, true),
844+
|this| visit::walk_fn_ret_ty(this, &declaration.output),
845+
);
846+
847+
// Ignore errors in function bodies if this is rustdoc
848+
// Be sure not to set this until the function signature has been resolved.
849+
let previous_state = replace(&mut this.in_func_body, true);
850+
// Resolve the function body, potentially inside the body of an async closure
851+
this.with_lifetime_rib(
852+
LifetimeRibKind::AnonymousPassThrough(fn_id, false),
853+
|this| this.visit_expr(body),
854+
);
855+
856+
debug!("(resolving function) leaving function");
857+
this.in_func_body = previous_state;
858+
}
859+
}
829860
})
830861
});
831862
self.diagnostic_metadata.current_function = previous_value;

src/test/ui/issues/issue-37884.stderr

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ LL | | }
1111
|
1212
= note: expected fn pointer `fn(&mut RepeatMut<'a, T>) -> Option<_>`
1313
found fn pointer `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
14-
note: the anonymous lifetime #1 defined here...
14+
note: the anonymous lifetime as defined here...
1515
--> $DIR/issue-37884.rs:6:5
1616
|
1717
LL | fn next(&'a mut self) -> Option<Self::Item>

0 commit comments

Comments
 (0)