Skip to content

Commit 20b967a

Browse files
committed
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 (cherry picked from commit 59eb9f9)
1 parent 2e322be commit 20b967a

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
@@ -800,4 +800,7 @@ Integer(x::Union{Float16, Float32, Float64}) = Int(x)
800800
# The internal jl_parse which will call into Core._parse if not `nothing`.
801801
_parse = nothing
802802

803+
# support for deprecated uses of internal _apply function
804+
_apply(x...) = Core._apply_iterate(Main.Base.iterate, x...)
805+
803806
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
@@ -589,13 +589,7 @@ end
589589

590590
# simulate iteration protocol on container type up to fixpoint
591591
function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @nospecialize(itertype), sv::InferenceState)
592-
if !isdefined(Main, :Base) || !isdefined(Main.Base, :iterate) || !isconst(Main.Base, :iterate)
593-
return Any[Vararg{Any}], nothing
594-
end
595-
if itft === nothing
596-
iteratef = getfield(Main.Base, :iterate)
597-
itft = Const(iteratef)
598-
elseif isa(itft, Const)
592+
if isa(itft, Const)
599593
iteratef = itft.val
600594
else
601595
return Any[Vararg{Any}], nothing
@@ -607,6 +601,7 @@ function abstract_iteration(interp::AbstractInterpreter, @nospecialize(itft), @n
607601
# Return Bottom if this is not an iterator.
608602
# WARNING: Changes to the iteration protocol must be reflected here,
609603
# this is not just an optimization.
604+
# TODO: this doesn't realize that Array, SimpleVector, Tuple, and NamedTuple do not use the iterate protocol
610605
stateordonet === Bottom && return Any[Bottom], AbstractIterationInfo(CallMeta[CallMeta(Bottom, info)])
611606
valtype = statetype = Bottom
612607
ret = Any[]
@@ -670,7 +665,7 @@ function abstract_apply(interp::AbstractInterpreter, @nospecialize(itft), @nospe
670665
aftw = widenconst(aft)
671666
if !isa(aft, Const) && (!isType(aftw) || has_free_typevars(aftw))
672667
if !isconcretetype(aftw) || (aftw <: Builtin)
673-
add_remark!(interp, sv, "Core._apply called on a function of a non-concrete type")
668+
add_remark!(interp, sv, "Core._apply_iterate called on a function of a non-concrete type")
674669
# bail now, since it seems unlikely that abstract_call will be able to do any better after splitting
675670
# this also ensures we don't call abstract_call_gf_by_type below on an IntrinsicFunction or Builtin
676671
return CallMeta(Any, false)
@@ -830,7 +825,8 @@ function abstract_call_builtin(interp::AbstractInterpreter, f::Builtin, fargs::U
830825
end
831826
rt = builtin_tfunction(interp, f, argtypes[2:end], sv)
832827
if f === getfield && isa(fargs, Vector{Any}) && la == 3 && isa(argtypes[3], Const) && isa(argtypes[3].val, Int) && argtypes[2] Tuple
833-
cti, _ = precise_container_type(interp, nothing, argtypes[2], sv)
828+
# TODO: why doesn't this use the getfield_tfunc?
829+
cti, _ = precise_container_type(interp, iterate, argtypes[2], sv)
834830
idx = argtypes[3].val::Int
835831
if 1 <= idx <= length(cti)
836832
rt = unwrapva(cti[idx])
@@ -949,11 +945,7 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
949945
la = length(argtypes)
950946

951947
if isa(f, Builtin)
952-
if f === _apply
953-
ft = argtype_by_index(argtypes, 2)
954-
ft === Bottom && return CallMeta(Bottom, false)
955-
return abstract_apply(interp, nothing, ft, argtype_tail(argtypes, 3), sv, max_methods)
956-
elseif f === _apply_iterate
948+
if f === _apply_iterate
957949
itft = argtype_by_index(argtypes, 2)
958950
ft = argtype_by_index(argtypes, 3)
959951
(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
@@ -1013,7 +1013,7 @@ function process_simple!(ir::IRCode, todo::Vector{Pair{Int, Any}}, idx::Int, sta
10131013
sig = call_sig(ir, stmt)
10141014
sig === nothing && return nothing
10151015

1016-
# Handle _apply
1016+
# Handle _apply_iterate
10171017
sig = inline_apply!(ir, todo, idx, sig, state.et, state.caches, state.params)
10181018
sig === nothing && return nothing
10191019

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
@@ -506,7 +506,7 @@ STATIC_INLINE void _grow_to(jl_value_t **root, jl_value_t ***oldargs, jl_svec_t
506506

507507
static jl_function_t *jl_iterate_func JL_GLOBALLY_ROOTED;
508508

509-
static jl_value_t *do_apply(jl_value_t *F, jl_value_t **args, uint32_t nargs, jl_value_t *iterate)
509+
static jl_value_t *do_apply( jl_value_t **args, uint32_t nargs, jl_value_t *iterate)
510510
{
511511
jl_function_t *f = args[0];
512512
if (nargs == 2) {
@@ -548,12 +548,7 @@ static jl_value_t *do_apply(jl_value_t *F, jl_value_t **args, uint32_t nargs, jl
548548
}
549549
}
550550
if (extra && iterate == NULL) {
551-
if (jl_iterate_func == NULL) {
552-
jl_iterate_func = jl_get_function(jl_top_module, "iterate");
553-
if (jl_iterate_func == NULL)
554-
jl_undefined_var_error(jl_symbol("iterate"));
555-
}
556-
iterate = jl_iterate_func;
551+
jl_undefined_var_error(jl_symbol("iterate"));
557552
}
558553
// allocate space for the argument array and gc roots for it
559554
// based on our previous estimates
@@ -677,13 +672,7 @@ static jl_value_t *do_apply(jl_value_t *F, jl_value_t **args, uint32_t nargs, jl
677672
JL_CALLABLE(jl_f__apply_iterate)
678673
{
679674
JL_NARGSV(_apply_iterate, 2);
680-
return do_apply(F, args+1, nargs-1, args[0]);
681-
}
682-
683-
JL_CALLABLE(jl_f__apply)
684-
{
685-
JL_NARGSV(_apply, 1);
686-
return do_apply(F, args, nargs, NULL);
675+
return do_apply(args + 1, nargs - 1, args[0]);
687676
}
688677

689678
// this is like `_apply`, but with quasi-exact checks to make sure it is pure
@@ -701,7 +690,7 @@ JL_CALLABLE(jl_f__apply_pure)
701690
// and `promote` works better this way
702691
size_t last_age = ptls->world_age;
703692
ptls->world_age = jl_world_counter;
704-
ret = jl_f__apply(NULL, args, nargs);
693+
ret = do_apply(args, nargs, NULL);
705694
ptls->world_age = last_age;
706695
ptls->in_pure_callback = last_in;
707696
}
@@ -1549,7 +1538,6 @@ void jl_init_primitives(void) JL_GC_DISABLED
15491538

15501539
// internal functions
15511540
jl_builtin_apply_type = add_builtin_func("apply_type", jl_f_apply_type);
1552-
jl_builtin__apply = add_builtin_func("_apply", jl_f__apply);
15531541
jl_builtin__apply_iterate = add_builtin_func("_apply_iterate", jl_f__apply_iterate);
15541542
jl_builtin__expr = add_builtin_func("_expr", jl_f__expr);
15551543
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} },
@@ -2695,13 +2694,11 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
26952694
}
26962695
}
26972696

2698-
else if (((f == jl_builtin__apply && nargs == 2) ||
2699-
(f == jl_builtin__apply_iterate && nargs == 3)) && ctx.vaSlot > 0) {
2700-
int arg_start = f == jl_builtin__apply ? 2 : 3;
2701-
// turn Core._apply(f, Tuple) ==> f(Tuple...) using the jlcall calling convention if Tuple is the va allocation
2702-
if (LoadInst *load = dyn_cast_or_null<LoadInst>(argv[arg_start].V)) {
2697+
else if ((f == jl_builtin__apply_iterate && nargs == 3) && ctx.vaSlot > 0) {
2698+
// turn Core._apply_iterate(iter, f, Tuple) ==> f(Tuple...) using the jlcall calling convention if Tuple is the va allocation
2699+
if (LoadInst *load = dyn_cast_or_null<LoadInst>(argv[3].V)) {
27032700
if (load->getPointerOperand() == ctx.slots[ctx.vaSlot].boxroot && ctx.argArray) {
2704-
Value *theF = boxed(ctx, argv[arg_start-1]);
2701+
Value *theF = boxed(ctx, argv[2]);
27052702
Value *nva = emit_n_varargs(ctx);
27062703
#ifdef _P64
27072704
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)