Skip to content

Commit 59eb9f9

Browse files
authored
remove Core._apply Builtin (#39115)
We can emulate this deprecated function, until we delete it in v2. This in turn revealed some missing error checks, which we also add. Fixes #39113
1 parent fa14d0b commit 59eb9f9

File tree

15 files changed

+48
-68
lines changed

15 files changed

+48
-68
lines changed

base/boot.jl

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,4 +803,7 @@ Integer(x::Union{Float16, Float32, Float64}) = Int(x)
803803
# The internal jl_parse which will call into Core._parse if not `nothing`.
804804
_parse = nothing
805805

806+
# support for deprecated uses of internal _apply function
807+
_apply(x...) = Core._apply_iterate(Main.Base.iterate, x...)
808+
806809
ccall(:jl_set_istopmod, Cvoid, (Any, Bool), Core, true)

base/compiler/abstractinterpretation.jl

Lines changed: 6 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -577,13 +577,7 @@ end
577577

578578
# simulate iteration protocol on container type up to fixpoint
579579
function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @nospecialize(itertype), sv::InferenceState)
580-
if !isdefined(Main, :Base) || !isdefined(Main.Base, :iterate) || !isconst(Main.Base, :iterate)
581-
return Any[Vararg{Any}], nothing
582-
end
583-
if itft === nothing
584-
iteratef = getfield(Main.Base, :iterate)
585-
itft = Const(iteratef)
586-
elseif isa(itft, Const)
580+
if isa(itft, Const)
587581
iteratef = itft.val
588582
else
589583
return Any[Vararg{Any}], nothing
@@ -595,6 +589,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
595589
# Return Bottom if this is not an iterator.
596590
# WARNING: Changes to the iteration protocol must be reflected here,
597591
# this is not just an optimization.
592+
# TODO: this doesn't realize that Array, SimpleVector, Tuple, and NamedTuple do not use the iterate protocol
598593
stateordonet === Bottom && return Any[Bottom], AbstractIterationInfo(CallMeta[CallMeta(Bottom, info)])
599594
valtype = statetype = Bottom
600595
ret = Any[]
@@ -658,7 +653,7 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
658653
aftw = widenconst(aft)
659654
if !isa(aft, Const) && (!isType(aftw) || has_free_typevars(aftw))
660655
if !isconcretetype(aftw) || (aftw <: Builtin)
661-
add_remark!(interp, sv, "Core._apply called on a function of a non-concrete type")
656+
add_remark!(interp, sv, "Core._apply_iterate called on a function of a non-concrete type")
662657
# bail now, since it seems unlikely that abstract_call will be able to do any better after splitting
663658
# this also ensures we don't call abstract_call_gf_by_type below on an IntrinsicFunction or Builtin
664659
return CallMeta(Any, false)
@@ -805,7 +800,8 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U
805800
end
806801
rt = builtin_tfunction(interp, f, argtypes[2:end], sv)
807802
if f === getfield && isa(fargs, Vector{Any}) && la == 3 && isa(argtypes[3], Const) && isa(argtypes[3].val, Int) && argtypes[2] Tuple
808-
cti, _ = precise_container_type(interp, nothing, argtypes[2], sv)
803+
# TODO: why doesn't this use the getfield_tfunc?
804+
cti, _ = precise_container_type(interp, iterate, argtypes[2], sv)
809805
idx = argtypes[3].val
810806
if 1 <= idx <= length(cti)
811807
rt = unwrapva(cti[idx])
@@ -923,11 +919,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
923919
la = length(argtypes)
924920

925921
if isa(f, Builtin)
926-
if f === _apply
927-
ft = argtype_by_index(argtypes, 2)
928-
ft === Bottom && return CallMeta(Bottom, false)
929-
return abstract_apply(interp, nothing, ft, argtype_tail(argtypes, 3), sv, max_methods)
930-
elseif f === _apply_iterate
922+
if f === _apply_iterate
931923
itft = argtype_by_index(argtypes, 2)
932924
ft = argtype_by_index(argtypes, 3)
933925
(itft === Bottom || ft === Bottom) && return CallMeta(Bottom, false)

base/compiler/compiler.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
# This file is a part of Julia. License is MIT: https://julialang.org/license
22

3-
getfield(getfield(Main, :Core), :eval)(getfield(Main, :Core), :(baremodule Compiler
3+
getfield(Core, :eval)(Core, :(baremodule Compiler
44

55
using Core.Intrinsics, Core.IR
66

77
import Core: print, println, show, write, unsafe_write, stdout, stderr,
8-
_apply, _apply_iterate, svec, apply_type, Builtin, IntrinsicFunction,
8+
_apply_iterate, svec, apply_type, Builtin, IntrinsicFunction,
99
MethodInstance, CodeInstance, MethodMatch
1010

1111
const getproperty = Core.getfield

base/compiler/optimize.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -326,19 +326,19 @@ function statement_cost(ex::Expr, line::Int, src::CodeInfo, sptypes::Vector{Any}
326326
# The efficiency of operations like a[i] and s.b
327327
# depend strongly on whether the result can be
328328
# inferred, so check the type of ex
329-
if f === Main.Core.getfield || f === Main.Core.tuple
329+
if f === Core.getfield || f === Core.tuple
330330
# we might like to penalize non-inferrability, but
331331
# tuple iteration/destructuring makes that impossible
332332
# return plus_saturate(argcost, isknowntype(extyp) ? 1 : params.inline_nonleaf_penalty)
333333
return 0
334-
elseif f === Main.Core.isa
334+
elseif f === Core.isa
335335
# If we're in a union context, we penalize type computations
336336
# on union types. In such cases, it is usually better to perform
337337
# union splitting on the outside.
338338
if union_penalties && isa(argextype(ex.args[2], src, sptypes, slottypes), Union)
339339
return params.inline_nonleaf_penalty
340340
end
341-
elseif (f === Main.Core.arrayref || f === Main.Core.const_arrayref) && length(ex.args) >= 3
341+
elseif (f === Core.arrayref || f === Core.const_arrayref) && length(ex.args) >= 3
342342
atyp = argextype(ex.args[3], src, sptypes, slottypes)
343343
return isknowntype(atyp) ? 4 : error_path ? params.inline_error_path_cost : params.inline_nonleaf_penalty
344344
end

base/compiler/ssair/inlining.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -573,7 +573,7 @@ function batch_inline!(todo::Vector{Pair{Int, Any}}, ir::IRCode, linetable::Vect
573573
return ir
574574
end
575575

576-
# This assumes the caller has verified that all arguments to the _apply call are Tuples.
576+
# This assumes the caller has verified that all arguments to the _apply_iterate call are Tuples.
577577
function rewrite_apply_exprargs!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::Int,
578578
argexprs::Vector{Any}, atypes::Vector{Any}, arginfos::Vector{Any},
579579
arg_start::Int, et::Union{EdgeTracker, Nothing}, caches::Union{InferenceCaches, Nothing},
@@ -909,7 +909,7 @@ end
909909
function inline_apply!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::Int, sig::Signature,
910910
et, caches, params::OptimizationParams)
911911
stmt = ir.stmts[idx][:inst]
912-
while sig.f === Core._apply || sig.f === Core._apply_iterate
912+
while sig.f === Core._apply_iterate
913913
info = ir.stmts[idx][:info]
914914
if isa(info, UnionSplitApplyCallInfo)
915915
if length(info.infos) != 1
@@ -923,7 +923,7 @@ function inline_apply!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::Int, sig::
923923
@assert info === nothing || info === false
924924
new_info = info = nothing
925925
end
926-
arg_start = sig.f === Core._apply ? 2 : 3
926+
arg_start = 3
927927
atypes = sig.atypes
928928
if arg_start > length(atypes)
929929
return nothing
@@ -1010,7 +1010,7 @@ function process_simple!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::Int, sta
10101010
sig = call_sig(ir, stmt)
10111011
sig === nothing && return nothing
10121012

1013-
# Handle _apply
1013+
# Handle _apply_iterate
10141014
sig = inline_apply!(ir, todo, idx, sig, state.et, state.caches, state.params)
10151015
sig === nothing && return nothing
10161016

base/compiler/types.jl

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -102,14 +102,14 @@ struct InferenceParams
102102
# before computing the set of matching methods
103103
MAX_UNION_SPLITTING::Int
104104
# the maximum number of union-tuples to swap / expand
105-
# when inferring a call to _apply
105+
# when inferring a call to _apply_iterate
106106
MAX_APPLY_UNION_ENUM::Int
107107

108108
# parameters limiting large (tuple) types
109109
TUPLE_COMPLEXITY_LIMIT_DEPTH::Int
110110

111-
# when attempting to inlining _apply, abort the optimization if the tuple
112-
# contains more than this many elements
111+
# when attempting to inline _apply_iterate, abort the optimization if the
112+
# tuple contains more than this many elements
113113
MAX_TUPLE_SPLAT::Int
114114

115115
function InferenceParams(;

src/builtin_proto.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ extern "C" {
2222
DECLARE_BUILTIN(throw); DECLARE_BUILTIN(is);
2323
DECLARE_BUILTIN(typeof); DECLARE_BUILTIN(sizeof);
2424
DECLARE_BUILTIN(issubtype); DECLARE_BUILTIN(isa);
25-
DECLARE_BUILTIN(_apply); DECLARE_BUILTIN(_apply_pure);
25+
DECLARE_BUILTIN(_apply_pure);
2626
DECLARE_BUILTIN(_call_latest); DECLARE_BUILTIN(_apply_iterate);
2727
DECLARE_BUILTIN(_call_in_world);
2828
DECLARE_BUILTIN(isdefined); DECLARE_BUILTIN(nfields);

src/builtins.c

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,7 @@ STATIC_INLINE void _grow_to(jl_value_t **root, jl_value_t ***oldargs, jl_svec_t
525525

526526
static jl_function_t *jl_iterate_func JL_GLOBALLY_ROOTED;
527527

528-
static jl_value_t *do_apply(jl_value_t *F, jl_value_t **args, uint32_t nargs, jl_value_t *iterate)
528+
static jl_value_t *do_apply( jl_value_t **args, uint32_t nargs, jl_value_t *iterate)
529529
{
530530
jl_function_t *f = args[0];
531531
if (nargs == 2) {
@@ -567,12 +567,7 @@ static jl_value_t *do_apply(jl_value_t *F, jl_value_t **args, uint32_t nargs, jl
567567
}
568568
}
569569
if (extra && iterate == NULL) {
570-
if (jl_iterate_func == NULL) {
571-
jl_iterate_func = jl_get_function(jl_top_module, "iterate");
572-
if (jl_iterate_func == NULL)
573-
jl_undefined_var_error(jl_symbol("iterate"));
574-
}
575-
iterate = jl_iterate_func;
570+
jl_undefined_var_error(jl_symbol("iterate"));
576571
}
577572
// allocate space for the argument array and gc roots for it
578573
// based on our previous estimates
@@ -696,13 +691,7 @@ static jl_value_t *do_apply(jl_value_t *F, jl_value_t **args, uint32_t nargs, jl
696691
JL_CALLABLE(jl_f__apply_iterate)
697692
{
698693
JL_NARGSV(_apply_iterate, 2);
699-
return do_apply(F, args+1, nargs-1, args[0]);
700-
}
701-
702-
JL_CALLABLE(jl_f__apply)
703-
{
704-
JL_NARGSV(_apply, 1);
705-
return do_apply(F, args, nargs, NULL);
694+
return do_apply(args + 1, nargs - 1, args[0]);
706695
}
707696

708697
// this is like `_apply`, but with quasi-exact checks to make sure it is pure
@@ -720,7 +709,7 @@ JL_CALLABLE(jl_f__apply_pure)
720709
// and `promote` works better this way
721710
size_t last_age = ptls->world_age;
722711
ptls->world_age = jl_world_counter;
723-
ret = jl_f__apply(NULL, args, nargs);
712+
ret = do_apply(args, nargs, NULL);
724713
ptls->world_age = last_age;
725714
ptls->in_pure_callback = last_in;
726715
}
@@ -1578,7 +1567,6 @@ void jl_init_primitives(void) JL_GC_DISABLED
15781567

15791568
// internal functions
15801569
jl_builtin_apply_type = add_builtin_func("apply_type", jl_f_apply_type);
1581-
jl_builtin__apply = add_builtin_func("_apply", jl_f__apply);
15821570
jl_builtin__apply_iterate = add_builtin_func("_apply_iterate", jl_f__apply_iterate);
15831571
jl_builtin__expr = add_builtin_func("_expr", jl_f__expr);
15841572
jl_builtin_svec = add_builtin_func("svec", jl_f_svec);

src/codegen.cpp

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -838,7 +838,6 @@ static const std::map<jl_fptr_args_t, JuliaFunction*> builtin_func_map = {
838838
{ &jl_f_isa, new JuliaFunction{"jl_f_isa", get_func_sig, get_func_attrs} },
839839
{ &jl_f_typeassert, new JuliaFunction{"jl_f_typeassert", get_func_sig, get_func_attrs} },
840840
{ &jl_f_ifelse, new JuliaFunction{"jl_f_ifelse", get_func_sig, get_func_attrs} },
841-
{ &jl_f__apply, new JuliaFunction{"jl_f__apply", get_func_sig, get_func_attrs} },
842841
{ &jl_f__apply_iterate, new JuliaFunction{"jl_f__apply_iterate", get_func_sig, get_func_attrs} },
843842
{ &jl_f__apply_pure, new JuliaFunction{"jl_f__apply_pure", get_func_sig, get_func_attrs} },
844843
{ &jl_f__call_latest, new JuliaFunction{"jl_f__call_latest", get_func_sig, get_func_attrs} },
@@ -2684,13 +2683,11 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
26842683
}
26852684
}
26862685

2687-
else if (((f == jl_builtin__apply && nargs == 2) ||
2688-
(f == jl_builtin__apply_iterate && nargs == 3)) && ctx.vaSlot > 0) {
2689-
int arg_start = f == jl_builtin__apply ? 2 : 3;
2690-
// turn Core._apply(f, Tuple) ==> f(Tuple...) using the jlcall calling convention if Tuple is the va allocation
2691-
if (LoadInst *load = dyn_cast_or_null<LoadInst>(argv[arg_start].V)) {
2686+
else if ((f == jl_builtin__apply_iterate && nargs == 3) && ctx.vaSlot > 0) {
2687+
// turn Core._apply_iterate(iter, f, Tuple) ==> f(Tuple...) using the jlcall calling convention if Tuple is the va allocation
2688+
if (LoadInst *load = dyn_cast_or_null<LoadInst>(argv[3].V)) {
26922689
if (load->getPointerOperand() == ctx.slots[ctx.vaSlot].boxroot && ctx.argArray) {
2693-
Value *theF = boxed(ctx, argv[arg_start-1]);
2690+
Value *theF = boxed(ctx, argv[2]);
26942691
Value *nva = emit_n_varargs(ctx);
26952692
#ifdef _P64
26962693
nva = ctx.builder.CreateTrunc(nva, T_int32);

src/module.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,8 @@ JL_DLLEXPORT jl_value_t *jl_get_global(jl_module_t *m, jl_sym_t *var)
623623

624624
JL_DLLEXPORT void jl_set_global(jl_module_t *m JL_ROOTING_ARGUMENT, jl_sym_t *var, jl_value_t *val JL_ROOTED_ARGUMENT)
625625
{
626+
JL_TYPECHK(jl_set_global, module, (jl_value_t*)m);
627+
JL_TYPECHK(jl_set_global, symbol, (jl_value_t*)var);
626628
jl_binding_t *bp = jl_get_binding_wr(m, var, 1);
627629
JL_GC_PROMISE_ROOTED(bp);
628630
jl_checked_assignment(bp, val);

0 commit comments

Comments
 (0)