@@ -1079,4 +1079,183 @@ end
10791079 longnt = NamedTuple {ntuple(i -> Symbol(:a, i), 20)} (ntuple (identity, 20 ))
10801080 @test filter (iseven, longnt) === NamedTuple {ntuple(i -> Symbol(:a, 2i), 10)} (ntuple (i -> 2 i, 10 ))
10811081 @test filter (x -> x< 2 , (longnt... , z= 1.5 )) === (a1= 1 , z= 1.5 )
1082- end
1082+ end
1083+
1084+ # https://github.com/JuliaLang/julia/pull/58940
1085+ @testset " @__FUNCTION__" begin
1086+ @testset " Basic usage" begin
1087+ # @__FUNCTION__ in regular functions
1088+ test_function_basic () = @__FUNCTION__
1089+ @test test_function_basic () === test_function_basic
1090+ end
1091+
1092+ @testset " Recursion" begin
1093+ # Factorial with @__FUNCTION__
1094+ factorial_function (n) = n <= 1 ? 1 : n * (@__FUNCTION__ )(n - 1 )
1095+ @test factorial_function (5 ) == 120
1096+
1097+ # Fibonacci with @__FUNCTION__
1098+ struct RecursiveCallableStruct; end
1099+ @eval (:: RecursiveCallableStruct )(n) = n <= 1 ? n : (@__FUNCTION__ )(n- 1 ) + (@__FUNCTION__ )(n- 2 )
1100+ @test RecursiveCallableStruct ()(10 ) === 55
1101+
1102+ # Anonymous function recursion
1103+ @test (n -> n <= 1 ? 1 : n * (@__FUNCTION__ )(n - 1 ))(5 ) == 120
1104+ end
1105+
1106+ @testset " Closures and nested functions" begin
1107+ # Prevents boxed closures
1108+ function make_closure ()
1109+ fib (n) = n <= 1 ? 1 : (@__FUNCTION__ )(n - 1 ) + (@__FUNCTION__ )(n - 2 )
1110+ return fib
1111+ end
1112+ Test. @inferred make_closure ()
1113+ closure = make_closure ()
1114+ @test closure (5 ) == 8
1115+ Test. @inferred closure (5 )
1116+
1117+ # Complex closure of closures
1118+ function f1 ()
1119+ function f2 ()
1120+ function f3 ()
1121+ return @__FUNCTION__
1122+ end
1123+ return (@__FUNCTION__ ), f3 ()
1124+ end
1125+ return (@__FUNCTION__ ), f2 ()...
1126+ end
1127+ Test. @inferred f1 ()
1128+ @test f1 ()[1 ] === f1
1129+ @test f1 ()[2 ] != = f1
1130+ @test f1 ()[3 ] != = f1
1131+ @test f1 ()[3 ]() === f1 ()[3 ]
1132+ @test f1 ()[2 ]()[2 ]() === f1 ()[3 ]
1133+ end
1134+
1135+ @testset " Do blocks" begin
1136+ function test_do_block ()
1137+ result = map ([1 , 2 , 3 ]) do x
1138+ return (@__FUNCTION__ , x)
1139+ end
1140+ # All should refer to the same do-block function
1141+ @test all (r -> r[1 ] === result[1 ][1 ], result)
1142+ # Values should be different
1143+ @test [r[2 ] for r in result] == [1 , 2 , 3 ]
1144+ # It should be different than `test_do_block`
1145+ @test result[1 ][1 ] != = test_do_block
1146+ end
1147+ test_do_block ()
1148+ end
1149+
1150+ @testset " Keyword arguments" begin
1151+ # @__FUNCTION__ with kwargs
1152+ foo (; n) = n <= 1 ? 1 : n * (@__FUNCTION__ )(; n = n - 1 )
1153+ @test foo (n = 5 ) == 120
1154+ end
1155+
1156+ @testset " Callable structs" begin
1157+ # @__FUNCTION__ in callable structs
1158+ @gensym A
1159+ @eval module $ A
1160+ import .. @__FUNCTION__
1161+
1162+ struct CallableStruct{T}; val:: T ; end
1163+ (c:: CallableStruct )() = @__FUNCTION__
1164+ end
1165+ @eval using .$ A: CallableStruct
1166+ c = CallableStruct (5 )
1167+ if isdefined (Base, Symbol (" @__FUNCTION__" ))
1168+ @test c () === c
1169+ else
1170+ @test_broken c () === c
1171+ end
1172+
1173+ # In closures, var"#self#" should refer to the enclosing function,
1174+ # NOT the enclosing struct instance
1175+ struct CallableStruct2; end
1176+ @eval function (obj:: CallableStruct2 )()
1177+ function inner_func ()
1178+ @__FUNCTION__
1179+ end
1180+ inner_func
1181+ end
1182+
1183+ let cs = CallableStruct2 ()
1184+ @test cs ()() === cs ()
1185+ @test cs ()() != = cs
1186+ end
1187+
1188+ # Accessing values via self-reference
1189+ struct CallableStruct3
1190+ value:: Int
1191+ end
1192+ @eval (obj:: CallableStruct3 )() = @__FUNCTION__
1193+ @eval (obj:: CallableStruct3 )(x) = (@__FUNCTION__ ). value + x
1194+
1195+ let cs = CallableStruct3 (42 )
1196+ if isdefined (Base, Symbol (" @__FUNCTION__" ))
1197+ @test cs () === cs
1198+ @test cs (10 ) === 52
1199+ else
1200+ @test_broken cs () === cs
1201+ @test_broken cs (10 ) === 52
1202+ end
1203+ end
1204+
1205+ # Callable struct with args and kwargs
1206+ struct CallableStruct4
1207+ end
1208+ @eval function (obj:: CallableStruct4 )(x, args... ; y= 2 , kws... )
1209+ return (; func= (@__FUNCTION__ ), x, args, y, kws)
1210+ end
1211+ c = CallableStruct4 ()
1212+ if isdefined (Base, Symbol (" @__FUNCTION__" ))
1213+ @test c (1 ). func === c
1214+ @test c (2 , 3 ). args == (3 ,)
1215+ @test c (2 ; y= 4 ). y == 4
1216+ @test c (2 ; y= 4 , a= 5 , b= 6 , c= 7 ). kws[:c ] == 7
1217+ else
1218+ @test_broken c (1 ). func === c
1219+ @test_broken c (2 , 3 ). args == (3 ,)
1220+ @test_broken c (2 ; y= 4 ). y == 4
1221+ @test_broken c (2 ; y= 4 , a= 5 , b= 6 , c= 7 ). kws[:c ] == 7
1222+ end
1223+ end
1224+
1225+ @testset " Special cases" begin
1226+ # Generated functions
1227+ let @generated foo2 () = :(@__FUNCTION__ )
1228+ @test foo2 () === foo2
1229+ end
1230+
1231+ # Should not access arg-map for local variables
1232+ @gensym f
1233+ @eval begin
1234+ function $ f end
1235+ function ($ f:: typeof ($ f))()
1236+ $ f = 1
1237+ @__FUNCTION__
1238+ end
1239+ end
1240+ if isdefined (Base, Symbol (" @__FUNCTION__" ))
1241+ @test @eval ($ f () === $ f)
1242+ else
1243+ @test_broken @eval ($ f () === $ f)
1244+ end
1245+ end
1246+
1247+ if isdefined (Base, Symbol (" @__FUNCTION__" ))
1248+ @testset " Error upon misuse" begin
1249+ @gensym B
1250+ @test_throws (
1251+ " \" @__FUNCTION__\" can only be used inside a function" ,
1252+ @eval (module $ B; @__FUNCTION__ ; end )
1253+ )
1254+
1255+ @test_throws (
1256+ " \" @__FUNCTION__\" not allowed inside comprehension or generator" ,
1257+ @eval ([(@__FUNCTION__ ) for _ in 1 : 10 ])
1258+ )
1259+ end
1260+ end
1261+ end
0 commit comments