Skip to content

Commit 7c05bd1

Browse files
committed
Ensure TypeVar definitions accompany method defs moved to top level
The `K"method_defs"` needs to group a preamble+sets of methods for a function together so that typevars can be defined in the preamble and the whole thing moved to top level as one piece, if necessary, during closure conversion. Previous refactoring had broken that - reinstated it here. There's some repetition of the typevars here for certain cases like kwcall overloads vs the actual function overloads, vs the separate kw body function - we can't tell during desugaring whether a function will become a closure or not so it's possible we might need to run these TypeVar initializations twice.
1 parent 317d75e commit 7c05bd1

File tree

3 files changed

+106
-95
lines changed

3 files changed

+106
-95
lines changed

src/desugaring.jl

Lines changed: 57 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -2369,10 +2369,17 @@ function expand_function_generator(ctx, srcref, callex_srcref, func_name, func_n
23692369
push!(gen_arg_types, @ast ctx gen_arg_names[i] "Any"::K"core")
23702370
end
23712371
# Code generator definition
2372-
gen_func_method_defs = @ast ctx srcref [K"method_defs"
2373-
gen_name
2374-
method_def_expr(ctx, srcref, callex_srcref, nothing, SyntaxList(ctx), gen_arg_names,
2375-
gen_arg_types, gen_body, nothing)
2372+
gen_func_method_defs = @ast ctx srcref [K"block"
2373+
[K"function_decl" gen_name]
2374+
[K"scope_block"(scope_type=:hard)
2375+
[K"method_defs"
2376+
gen_name
2377+
[K"block"
2378+
method_def_expr(ctx, srcref, callex_srcref, nothing, SyntaxList(ctx),
2379+
gen_arg_names, gen_arg_types, gen_body, nothing)
2380+
]
2381+
]
2382+
]
23762383
]
23772384

23782385
# Extract non-generated body
@@ -2414,7 +2421,7 @@ function expand_function_generator(ctx, srcref, callex_srcref, func_name, func_n
24142421
split_generated(ctx, body, false)
24152422
]
24162423

2417-
return gen_name, gen_func_method_defs, nongen_body
2424+
return gen_func_method_defs, nongen_body
24182425
end
24192426

24202427
# Generate a method for every number of allowed optional arguments
@@ -2472,8 +2479,8 @@ function scope_nest(ctx, names, values, body)
24722479
end
24732480

24742481
# Generate body function and `Core.kwcall` overloads for functions taking keywords.
2475-
function keyword_function_defs(ctx, srcref, callex_srcref, name_str,
2476-
typevar_names, typevar_stmts, arg_names,
2482+
function keyword_function_defs(ctx, srcref, callex_srcref, name_str, typevar_names,
2483+
typevar_stmts, new_typevar_stmts, arg_names,
24772484
arg_types, has_slurp, first_default, arg_defaults,
24782485
keywords, body, ret_var)
24792486
mangled_name = let n = isnothing(name_str) ? "_" : name_str
@@ -2700,23 +2707,29 @@ function keyword_function_defs(ctx, srcref, callex_srcref, name_str,
27002707
check_all_typevars_used(body_arg_types, typevar_names, typevar_stmts)
27012708

27022709
kw_func_method_defs = @ast ctx srcref [K"block"
2703-
[K"method_defs"
2704-
body_func_name
2705-
[K"block"
2706-
# TODO: nkw
2707-
method_def_expr(ctx, srcref, callex_srcref, "nothing"::K"core",
2708-
typevar_names, body_arg_names, body_arg_types,
2709-
[K"block"
2710-
[K"meta" "nkw"::K"Symbol" numchildren(keywords)::K"Integer"]
2711-
body
2712-
],
2713-
ret_var)
2710+
[K"function_decl" body_func_name]
2711+
[K"scope_block"(scope_type=:hard)
2712+
[K"method_defs"
2713+
body_func_name
2714+
[K"block"
2715+
new_typevar_stmts...
2716+
method_def_expr(ctx, srcref, callex_srcref, "nothing"::K"core",
2717+
typevar_names, body_arg_names, body_arg_types,
2718+
[K"block"
2719+
[K"meta" "nkw"::K"Symbol" numchildren(keywords)::K"Integer"]
2720+
body
2721+
],
2722+
ret_var)
2723+
]
27142724
]
27152725
]
2716-
[K"method_defs"
2717-
"nothing"::K"core"
2718-
[K"block"
2719-
kwcall_method_defs...
2726+
[K"scope_block"(scope_type=:hard)
2727+
[K"method_defs"
2728+
"nothing"::K"core"
2729+
[K"block"
2730+
new_typevar_stmts...
2731+
kwcall_method_defs...
2732+
]
27202733
]
27212734
]
27222735
]
@@ -2737,7 +2750,7 @@ function keyword_function_defs(ctx, srcref, callex_srcref, name_str,
27372750
]
27382751
end
27392752

2740-
body_func_name, kw_func_method_defs, body_for_positional_args_only
2753+
kw_func_method_defs, body_for_positional_args_only
27412754
end
27422755

27432756
# Check valid identifier/function names
@@ -2936,27 +2949,27 @@ function expand_function_def(ctx, ex, docs, rewrite_call=identity, rewrite_body=
29362949
]
29372950
end
29382951

2939-
gen_func_name = nothing
29402952
gen_func_method_defs = nothing
29412953
if is_generated(body)
2942-
gen_func_name, gen_func_method_defs, body =
2954+
gen_func_method_defs, body =
29432955
expand_function_generator(ctx, ex, callex, name, name_str, body, arg_names, typevar_names)
29442956

29452957
end
29462958

29472959
if isnothing(keywords)
2948-
body_func_name, kw_func_method_defs = (nothing, nothing)
2949-
# NB: This check seems good as it statically catches any useless
2950-
# typevars which can't be inferred. However it wasn't previously an
2951-
# error so we might need to reduce it to a warning?
2960+
kw_func_method_defs = nothing
2961+
# NB: The following check seems good as it statically catches any useless
2962+
# static parameters which can't be bound during method invocation.
2963+
# However it wasn't previously an error so we might need to reduce it
2964+
# to a warning?
29522965
check_all_typevars_used(arg_types, typevar_names, typevar_stmts)
29532966
main_typevar_names = typevar_names
29542967
else
29552968
# Rewrite `body` here so that the positional-only versions dispatch there.
2956-
body_func_name, kw_func_method_defs, body =
2969+
kw_func_method_defs, body =
29572970
keyword_function_defs(ctx, ex, callex, name_str, typevar_names, typevar_stmts,
2958-
arg_names, arg_types, has_slurp, first_default, arg_defaults,
2959-
keywords, body, ret_var)
2971+
new_typevar_stmts, arg_names, arg_types, has_slurp,
2972+
first_default, arg_defaults, keywords, body, ret_var)
29602973
# The main function (but without keywords) needs its typevars trimmed,
29612974
# as some of them may be for the keywords only.
29622975
main_typevar_names = trim_used_typevars(ctx, arg_types, typevar_names, typevar_stmts)
@@ -2993,28 +3006,22 @@ function expand_function_def(ctx, ex, docs, rewrite_call=identity, rewrite_body=
29933006
end
29943007

29953008
@ast ctx ex [K"block"
2996-
if !isnothing(gen_func_name)
2997-
[K"function_decl"(gen_func_name) gen_func_name]
2998-
end
2999-
if !isnothing(body_func_name)
3000-
[K"function_decl"(body_func_name) body_func_name]
3001-
end
30023009
if !isnothing(bare_func_name)
3010+
# Need the main function type created here before running any code
3011+
# in kw_func_method_defs
30033012
[K"function_decl"(bare_func_name) bare_func_name]
30043013
end
3014+
gen_func_method_defs
3015+
kw_func_method_defs
30053016
[K"scope_block"(scope_type=:hard)
3006-
[K"block"
3007-
new_typevar_stmts...
3008-
gen_func_method_defs
3009-
kw_func_method_defs
3010-
[K"method_defs"
3011-
isnothing(bare_func_name) ? "nothing"::K"core" : bare_func_name
3012-
[K"block"
3013-
if !isnothing(method_table_val)
3014-
[K"=" method_table method_table_val]
3015-
end
3016-
method_stmts...
3017-
]
3017+
[K"method_defs"
3018+
isnothing(bare_func_name) ? "nothing"::K"core" : bare_func_name
3019+
[K"block"
3020+
new_typevar_stmts...
3021+
if !isnothing(method_table_val)
3022+
[K"=" method_table method_table_val]
3023+
end
3024+
method_stmts...
30183025
]
30193026
]
30203027
]

test/closures_ir.jl

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -572,12 +572,12 @@ let y = y_init
572572
end
573573
#---------------------
574574
1 TestMod.y_init
575-
2 (call core.svec :y)
575+
2 (call core.svec :#f_kw_closure#0)
576576
3 (call core.svec true)
577-
4 (call JuliaLowering.eval_closure_type TestMod :##f_kw_closure#0##0 %₂ %₃)
578-
5 (call core.svec :#f_kw_closure#0)
577+
4 (call JuliaLowering.eval_closure_type TestMod :#f_kw_closure##0 %₂ %₃)
578+
5 (call core.svec :y)
579579
6 (call core.svec true)
580-
7 (call JuliaLowering.eval_closure_type TestMod :#f_kw_closure##0 %₅ %₆)
580+
7 (call JuliaLowering.eval_closure_type TestMod :##f_kw_closure#0##0 %₅ %₆)
581581
8 TestMod.##f_kw_closure#0##0
582582
9 TestMod.X
583583
10 TestMod.#f_kw_closure##0
@@ -619,15 +619,15 @@ end
619619
23 (= slot₂/#f_kw_closure#0 (call core.Box))
620620
24 slot₁/y
621621
25 (call core.setfield! %₂₄ :contents %₁)
622-
26 TestMod.##f_kw_closure#0##0
623-
27 slot/y
622+
26 TestMod.#f_kw_closure##0
623+
27 slot/#f_kw_closure#0
624624
28 (new %₂₆ %₂₇)
625-
29 slot/#f_kw_closure#0
626-
30 (call core.setfield! %₂₉ :contents %₂₈)
627-
31 TestMod.#f_kw_closure##0
628-
32 slot₂/#f_kw_closure#0
629-
33 (new %₃₁ %₃₂)
630-
34 (= slot₃/f_kw_closure %₃₃)
625+
29 (= slot/f_kw_closure %₂₈)
626+
30 TestMod.##f_kw_closure#0##0
627+
31 slot₁/y
628+
32 (new %₃₀ %₃₁)
629+
33 slot₂/#f_kw_closure#0
630+
34 (call core.setfield! %₃₃ :contents %₃₂)
631631
35 (call core.typeof core.kwcall)
632632
36 TestMod.#f_kw_closure##0
633633
37 (call core.svec %₃₅ core.NamedTuple %₃₆)

test/functions_ir.jl

Lines changed: 37 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -955,8 +955,8 @@ function f_kw_simple(a::Int=1, b::Float64=1.0; x::Char='a', y::Bool=true)
955955
(a, b, x, y)
956956
end
957957
#---------------------
958-
1 (method TestMod.#f_kw_simple#0)
959-
2 (method TestMod.f_kw_simple)
958+
1 (method TestMod.f_kw_simple)
959+
2 (method TestMod.#f_kw_simple#0)
960960
3 TestMod.#f_kw_simple#0
961961
4 (call core.Typeof %₃)
962962
5 TestMod.Char
@@ -1091,8 +1091,8 @@ function f_kw_slurp_simple(; all_kws...)
10911091
all_kws
10921092
end
10931093
#---------------------
1094-
1 (method TestMod.#f_kw_slurp_simple#0)
1095-
2 (method TestMod.f_kw_slurp_simple)
1094+
1 (method TestMod.f_kw_slurp_simple)
1095+
2 (method TestMod.#f_kw_slurp_simple#0)
10961096
3 TestMod.#f_kw_slurp_simple#0
10971097
4 (call core.Typeof %₃)
10981098
5 (call top.pairs core.NamedTuple)
@@ -1143,8 +1143,8 @@ function f_kw_slurp(; x=x_default, non_x_kws...)
11431143
all_kws
11441144
end
11451145
#---------------------
1146-
1 (method TestMod.#f_kw_slurp#0)
1147-
2 (method TestMod.f_kw_slurp)
1146+
1 (method TestMod.f_kw_slurp)
1147+
2 (method TestMod.#f_kw_slurp#0)
11481148
3 TestMod.#f_kw_slurp#0
11491149
4 (call core.Typeof %₃)
11501150
5 (call top.pairs core.NamedTuple)
@@ -1212,8 +1212,8 @@ function f_kw_sparams(x::X; a::A=a_def, b::X=b_def) where {X,A}
12121212
(X,A)
12131213
end
12141214
#---------------------
1215-
1 (method TestMod.#f_kw_sparams#0)
1216-
2 (method TestMod.f_kw_sparams)
1215+
1 (method TestMod.f_kw_sparams)
1216+
2 (method TestMod.#f_kw_sparams#0)
12171217
3 (= slot₂/X (call core.TypeVar :X))
12181218
4 (= slot₁/A (call core.TypeVar :A))
12191219
5 TestMod.#f_kw_sparams#0
@@ -1236,16 +1236,18 @@ end
12361236
3 static_parameter₂
12371237
4 (call core.tuple %%₃)
12381238
5 (return %₄)
1239-
19 (call core.typeof core.kwcall)
1240-
20 TestMod.f_kw_sparams
1241-
21 (call core.Typeof %₂₀)
1242-
22 slot₂/X
1243-
23 (call core.svec %₁₉ core.NamedTuple %₂₁ %₂₂)
1244-
24 slot₂/X
1245-
25 (call core.svec %₂₄)
1246-
26 SourceLocation::1:10
1247-
27 (call core.svec %₂₃ %₂₅ %₂₆)
1248-
28 --- method core.nothing %₂₇
1239+
19 (= slot₄/X (call core.TypeVar :X))
1240+
20 (= slot₃/A (call core.TypeVar :A))
1241+
21 (call core.typeof core.kwcall)
1242+
22 TestMod.f_kw_sparams
1243+
23 (call core.Typeof %₂₂)
1244+
24 slot₄/X
1245+
25 (call core.svec %₂₁ core.NamedTuple %₂₃ %₂₄)
1246+
26 slot₄/X
1247+
27 (call core.svec %₂₆)
1248+
28 SourceLocation::1:10
1249+
29 (call core.svec %₂₅ %₂₇ %₂₈)
1250+
30 --- method core.nothing %₂₉
12491251
slots: [slot₁/#self#(!read) slot₂/kws slot₃/#self# slot₄/x slot₅/kwtmp slot₆/a(!read) slot₇/b(!read)]
12501252
1 (newvar slot₆/a)
12511253
2 (newvar slot₇/b)
@@ -1282,23 +1284,25 @@ end
12821284
33 TestMod.#f_kw_sparams#0
12831285
34 (call %₃₃ %₁₀ %₂₅ slot₃/#self# slot₄/x)
12841286
35 (return %₃₄)
1285-
29 TestMod.f_kw_sparams
1286-
30 (call core.Typeof %₂₉)
1287-
31 slot₂/X
1288-
32 (call core.svec %₃₀ %₃₁)
1289-
33 slot₂/X
1290-
34 (call core.svec %₃₃)
1291-
35 SourceLocation::1:10
1292-
36 (call core.svec %₃₂ %₃₄ %₃₅)
1293-
37 --- method core.nothing %₃₆
1287+
31 (= slot₆/X (call core.TypeVar :X))
1288+
32 (= slot₅/A (call core.TypeVar :A))
1289+
33 TestMod.f_kw_sparams
1290+
34 (call core.Typeof %₃₃)
1291+
35 slot₆/X
1292+
36 (call core.svec %₃₄ %₃₅)
1293+
37 slot₆/X
1294+
38 (call core.svec %₃₇)
1295+
39 SourceLocation::1:10
1296+
40 (call core.svec %₃₆ %₃₈ %₃₉)
1297+
41 --- method core.nothing %₄₀
12941298
slots: [slot₁/#self# slot₂/x]
12951299
1 TestMod.#f_kw_sparams#0
12961300
2 TestMod.a_def
12971301
3 TestMod.b_def
12981302
4 (call %%%₃ slot₁/#self# slot₂/x)
12991303
5 (return %₄)
1300-
38 TestMod.f_kw_sparams
1301-
39 (return %₃₈)
1304+
42 TestMod.f_kw_sparams
1305+
43 (return %₄₂)
13021306

13031307
########################################
13041308
# Error: Static parameter which is unused in keyword body arg types
@@ -1358,8 +1362,8 @@ end
13581362
generator_code(x,y)
13591363
end
13601364
#---------------------
1361-
1 (method TestMod.#f_only_generated@generator#0)
1362-
2 (method TestMod.f_only_generated)
1365+
1 (method TestMod.f_only_generated)
1366+
2 (method TestMod.#f_only_generated@generator#0)
13631367
3 TestMod.#f_only_generated@generator#0
13641368
4 (call core.Typeof %₃)
13651369
5 (call core.svec %₄ JuliaLowering.MacroContext core.Any core.Any core.Any)
@@ -1399,8 +1403,8 @@ function f_partially_generated(x, y)
13991403
(nongen_stuff, maybe_gen_stuff)
14001404
end
14011405
#---------------------
1402-
1 (method TestMod.#f_partially_generated@generator#0)
1403-
2 (method TestMod.f_partially_generated)
1406+
1 (method TestMod.f_partially_generated)
1407+
2 (method TestMod.#f_partially_generated@generator#0)
14041408
3 TestMod.#f_partially_generated@generator#0
14051409
4 (call core.Typeof %₃)
14061410
5 (call core.svec %₄ JuliaLowering.MacroContext core.Any core.Any core.Any)

0 commit comments

Comments
 (0)