Skip to content

Commit

Permalink
builtins: add Core.throw_methoderror (#55705)
Browse files Browse the repository at this point in the history
This allows us to simulate/mark calls that are known-to-fail.

Required for #54972
  • Loading branch information
topolarity authored and kshyatt committed Sep 12, 2024
1 parent e4a4270 commit b8d0111
Show file tree
Hide file tree
Showing 8 changed files with 32 additions and 4 deletions.
13 changes: 13 additions & 0 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2226,6 +2226,17 @@ function abstract_throw(interp::AbstractInterpreter, argtypes::Vector{Any}, ::Ab
return CallMeta(Union{}, exct, EFFECTS_THROWS, NoCallInfo())
end

function abstract_throw_methoderror(interp::AbstractInterpreter, argtypes::Vector{Any}, ::AbsIntState)
exct = if length(argtypes) == 1
ArgumentError
elseif !isvarargtype(argtypes[2])
MethodError
else
tmerge(𝕃ᵢ, MethodError, ArgumentError)
end
return CallMeta(Union{}, exct, EFFECTS_THROWS, NoCallInfo())
end

# call where the function is known exactly
function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
arginfo::ArgInfo, si::StmtInfo, sv::AbsIntState,
Expand All @@ -2246,6 +2257,8 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
return abstract_applicable(interp, argtypes, sv, max_methods)
elseif f === throw
return abstract_throw(interp, argtypes, sv)
elseif f === Core.throw_methoderror
return abstract_throw_methoderror(interp, argtypes, sv)
end
rt = abstract_call_builtin(interp, f, arginfo, sv)
ft = popfirst!(argtypes)
Expand Down
1 change: 1 addition & 0 deletions base/compiler/ssair/EscapeAnalysis/EscapeAnalysis.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1213,6 +1213,7 @@ escape_builtin!(::typeof(Core.donotdelete), _...) = false
# not really safe, but `ThrownEscape` will be imposed later
escape_builtin!(::typeof(isdefined), _...) = false
escape_builtin!(::typeof(throw), _...) = false
escape_builtin!(::typeof(Core.throw_methoderror), _...) = false

function escape_builtin!(::typeof(ifelse), astate::AnalysisState, pc::Int, args::Vector{Any})
length(args) == 4 || return false
Expand Down
4 changes: 4 additions & 0 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ function add_tfunc(@nospecialize(f::Builtin), minarg::Int, maxarg::Int, @nospeci
end

add_tfunc(throw, 1, 1, @nospecs((𝕃::AbstractLattice, x)->Bottom), 0)
add_tfunc(Core.throw_methoderror, 1, INT_INF, @nospecs((𝕃::AbstractLattice, x)->Bottom), 0)

# the inverse of typeof_tfunc
# returns (type, isexact, isconcrete, istype)
Expand Down Expand Up @@ -2313,6 +2314,7 @@ const _CONSISTENT_BUILTINS = Any[
(<:),
typeassert,
throw,
Core.throw_methoderror,
setfield!,
donotdelete
]
Expand All @@ -2335,6 +2337,7 @@ const _EFFECT_FREE_BUILTINS = [
(<:),
typeassert,
throw,
Core.throw_methoderror,
getglobal,
compilerbarrier,
]
Expand All @@ -2350,6 +2353,7 @@ const _INACCESSIBLEMEM_BUILTINS = Any[
isa,
nfields,
throw,
Core.throw_methoderror,
tuple,
typeassert,
typeof,
Expand Down
1 change: 1 addition & 0 deletions src/builtin_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ DECLARE_BUILTIN(svec);
DECLARE_BUILTIN(swapfield);
DECLARE_BUILTIN(swapglobal);
DECLARE_BUILTIN(throw);
DECLARE_BUILTIN(throw_methoderror);
DECLARE_BUILTIN(tuple);
DECLARE_BUILTIN(typeassert);
DECLARE_BUILTIN(typeof);
Expand Down
9 changes: 9 additions & 0 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,14 @@ JL_CALLABLE(jl_f_throw)
return jl_nothing;
}

JL_CALLABLE(jl_f_throw_methoderror)
{
JL_NARGSV(throw_methoderror, 1);
size_t world = jl_get_tls_world_age();
jl_method_error(args[0], &args[1], nargs, world);
return jl_nothing;
}

JL_CALLABLE(jl_f_ifelse)
{
JL_NARGS(ifelse, 3, 3);
Expand Down Expand Up @@ -2437,6 +2445,7 @@ void jl_init_primitives(void) JL_GC_DISABLED
add_builtin_func("_compute_sparams", jl_f__compute_sparams);
add_builtin_func("_svec_ref", jl_f__svec_ref);
add_builtin_func("current_scope", jl_f_current_scope);
add_builtin_func("throw_methoderror", jl_f_throw_methoderror);

// builtin types
add_builtin("Any", (jl_value_t*)jl_any_type);
Expand Down
4 changes: 2 additions & 2 deletions src/gf.c
Original file line number Diff line number Diff line change
Expand Up @@ -2335,7 +2335,7 @@ JL_DLLEXPORT void jl_method_table_insert(jl_methtable_t *mt, jl_method_t *method
JL_GC_POP();
}

static void JL_NORETURN jl_method_error_bare(jl_function_t *f, jl_value_t *args, size_t world)
static void JL_NORETURN jl_method_error_bare(jl_value_t *f, jl_value_t *args, size_t world)
{
if (jl_methoderror_type) {
jl_value_t *e = jl_new_struct_uninit(jl_methoderror_type);
Expand All @@ -2360,7 +2360,7 @@ static void JL_NORETURN jl_method_error_bare(jl_function_t *f, jl_value_t *args,
// not reached
}

void JL_NORETURN jl_method_error(jl_function_t *f, jl_value_t **args, size_t na, size_t world)
void JL_NORETURN jl_method_error(jl_value_t *f, jl_value_t **args, size_t na, size_t world)
{
jl_value_t *argtup = jl_f_tuple(NULL, args, na - 1);
JL_GC_PUSH1(&argtup);
Expand Down
2 changes: 1 addition & 1 deletion src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -705,7 +705,7 @@ int jl_valid_type_param(jl_value_t *v);

JL_DLLEXPORT jl_value_t *jl_apply_2va(jl_value_t *f, jl_value_t **args, uint32_t nargs);

void JL_NORETURN jl_method_error(jl_function_t *f, jl_value_t **args, size_t na, size_t world);
void JL_NORETURN jl_method_error(jl_value_t *F, jl_value_t **args, size_t na, size_t world);
JL_DLLEXPORT jl_value_t *jl_get_exceptionf(jl_datatype_t *exception_type, const char *fmt, ...);

JL_DLLEXPORT void jl_typeassert(jl_value_t *x, jl_value_t *t);
Expand Down
2 changes: 1 addition & 1 deletion src/staticdata.c
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ static htable_t relocatable_ext_cis;
// (reverse of fptr_to_id)
// This is a manually constructed dual of the fvars array, which would be produced by codegen for Julia code, for C.
static const jl_fptr_args_t id_to_fptrs[] = {
&jl_f_throw, &jl_f_is, &jl_f_typeof, &jl_f_issubtype, &jl_f_isa,
&jl_f_throw, &jl_f_throw_methoderror, &jl_f_is, &jl_f_typeof, &jl_f_issubtype, &jl_f_isa,
&jl_f_typeassert, &jl_f__apply_iterate, &jl_f__apply_pure,
&jl_f__call_latest, &jl_f__call_in_world, &jl_f__call_in_world_total, &jl_f_isdefined,
&jl_f_tuple, &jl_f_svec, &jl_f_intrinsic_call,
Expand Down

0 comments on commit b8d0111

Please sign in to comment.