@@ -1001,7 +1001,8 @@ fn add_fndef_axioms_to_function(
10011001 _ctx : & GlobalCtx ,
10021002 state : & mut State ,
10031003 function : & Function ,
1004- ) -> Result < Function , VirErr > {
1004+ fn_once_trait_in_scope : bool ,
1005+ ) -> Result < ( Function , Vec < TraitImpl > , Option < AssocTypeImpl > ) , VirErr > {
10051006 state. reset_for_function ( ) ;
10061007
10071008 let params: Vec < _ > = function
@@ -1031,10 +1032,64 @@ fn add_fndef_axioms_to_function(
10311032
10321033 let fndef_singleton = SpannedTyped :: new (
10331034 & function. span ,
1034- & Arc :: new ( TypX :: FnDef ( fun. clone ( ) , typ_args, None ) ) ,
1035+ & Arc :: new ( TypX :: FnDef ( fun. clone ( ) , typ_args. clone ( ) , None ) ) ,
10351036 ExprX :: ExecFnByName ( fun. clone ( ) ) ,
10361037 ) ;
10371038
1039+ // Emit `FnDef : {Fn, FnMut, FnOnce}<Args>` and `<FnDef as FnOnce<Args>>::Output = Ret`.
1040+ //
1041+ // We emit a TraitImpl for each of the three Fn-family traits (not just Fn), because
1042+ // code that mentions only one through an associated-type projection (e.g. `Map::Item = F::Output`)
1043+ // never creates a Fn term for the Fn-related axioms to trigger on.
1044+ let ( trait_impls_out, assoc_type_impl) = if fn_once_trait_in_scope {
1045+ let self_typ = Arc :: new ( TypX :: FnDef ( fun. clone ( ) , typ_args. clone ( ) , None ) ) ;
1046+ let arg_typs: Vec < Typ > = params. iter ( ) . map ( |p| p. a . clone ( ) ) . collect ( ) ;
1047+ let args_tuple_typ = Arc :: new ( TypX :: Datatype (
1048+ Dt :: Tuple ( arg_typs. len ( ) ) ,
1049+ Arc :: new ( arg_typs) ,
1050+ Arc :: new ( vec ! [ ] ) ,
1051+ ) ) ;
1052+ let trait_typ_args = Arc :: new ( vec ! [ self_typ, args_tuple_typ] ) ;
1053+
1054+ let mk_impl_path = |kind : ClosureKind | {
1055+ Arc :: new ( crate :: ast:: PathX {
1056+ krate : CrateId :: Internal ,
1057+ segments : Arc :: new ( vec ! [ crate :: def:: impl_fndef( & function. x. name, kind) ] ) ,
1058+ } )
1059+ } ;
1060+
1061+ let mut trait_impls_out: Vec < TraitImpl > = Vec :: new ( ) ;
1062+ for kind in [ ClosureKind :: Fn , ClosureKind :: FnMut , ClosureKind :: FnOnce ] {
1063+ let trait_implx = crate :: ast:: TraitImplX {
1064+ impl_path : mk_impl_path ( kind) ,
1065+ typ_params : function. x . typ_params . clone ( ) ,
1066+ typ_bounds : function. x . typ_bounds . clone ( ) ,
1067+ trait_path : kind. trait_path ( ) ,
1068+ trait_typ_args : trait_typ_args. clone ( ) ,
1069+ trait_typ_arg_impls : Spanned :: new ( function. span . clone ( ) , Arc :: new ( vec ! [ ] ) ) ,
1070+ owning_module : None ,
1071+ auto_imported : true ,
1072+ external_trait_blanket : false ,
1073+ } ;
1074+ trait_impls_out. push ( Spanned :: new ( function. span . clone ( ) , trait_implx) ) ;
1075+ }
1076+
1077+ let assoc_typ_implx = crate :: ast:: AssocTypeImplX {
1078+ name : Arc :: new ( "Output" . to_string ( ) ) ,
1079+ impl_path : mk_impl_path ( ClosureKind :: FnOnce ) ,
1080+ typ_params : function. x . typ_params . clone ( ) ,
1081+ typ_bounds : function. x . typ_bounds . clone ( ) ,
1082+ trait_path : ClosureKind :: FnOnce . trait_path ( ) ,
1083+ trait_typ_args,
1084+ typ : function. x . ret . x . typ . clone ( ) ,
1085+ impl_paths : Arc :: new ( vec ! [ ] ) ,
1086+ } ;
1087+
1088+ ( trait_impls_out, Some ( Spanned :: new ( function. span . clone ( ) , assoc_typ_implx) ) )
1089+ } else {
1090+ ( Vec :: new ( ) , None )
1091+ } ;
1092+
10381093 let mut fndef_axioms = vec ! [ ] ;
10391094
10401095 // Don't need to repeat the 'requires' for a trait impl fn because requires can't change
@@ -1087,7 +1142,7 @@ fn add_fndef_axioms_to_function(
10871142 let mut functionx = function. x . clone ( ) ;
10881143 assert ! ( functionx. fndef_axioms. is_none( ) ) ;
10891144 functionx. fndef_axioms = Some ( Arc :: new ( fndef_axioms) ) ;
1090- Ok ( Spanned :: new ( function. span . clone ( ) , functionx) )
1145+ Ok ( ( Spanned :: new ( function. span . clone ( ) , functionx) , trait_impls_out , assoc_type_impl ) )
10911146}
10921147
10931148fn simplify_function (
@@ -1349,13 +1404,24 @@ pub fn simplify_krate(ctx: &mut GlobalCtx, krate: &Krate) -> Result<Krate, VirEr
13491404 let mut assoc_type_impls =
13501405 vec_map_result ( & assoc_type_impls, |a| simplify_assoc_type_impl ( & mut state, a) ) ?;
13511406
1352- let functions = vec_map_result ( & functions, |f : & Function | {
1407+ let fn_once_trait_path = ClosureKind :: FnOnce . trait_path ( ) ;
1408+ let fn_once_trait_in_scope = traits. iter ( ) . any ( |t| t. x . name == fn_once_trait_path) ;
1409+
1410+ let mut new_functions: Vec < Function > = Vec :: with_capacity ( functions. len ( ) ) ;
1411+ for f in functions. iter ( ) {
13531412 if need_fndef_axiom ( & state. fndef_typs , f) {
1354- add_fndef_axioms_to_function ( ctx, & mut state, f)
1413+ let ( f2, tis, ai) =
1414+ add_fndef_axioms_to_function ( ctx, & mut state, f, fn_once_trait_in_scope) ?;
1415+ trait_impls. extend ( tis) ;
1416+ if let Some ( ai) = ai {
1417+ assoc_type_impls. push ( ai) ;
1418+ }
1419+ new_functions. push ( f2) ;
13551420 } else {
1356- Ok ( f. clone ( ) )
1421+ new_functions . push ( f. clone ( ) ) ;
13571422 }
1358- } ) ?;
1423+ }
1424+ let functions = new_functions;
13591425
13601426 // Add a generic datatype to represent each tuple arity
13611427 // Iterate in sorted order to get consistent output
0 commit comments