@@ -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;
0 commit comments