Skip to content

Commit 45448cd

Browse files
committed
Align :method Expr return value between interpreter and codegen
Interpreter/inference think the 3-argument `:method` Expr returns `nothing`. Codegen thinks it returns the new method. I think the latter makes more sense, because it lets us write explicit syntax-level dependency links between method definitions and constants (used e.g. for external abstract interpreters), which is something that Revise may need in the future. Adjust the interpreter/inference to properly return the method.
1 parent 1117df6 commit 45448cd

File tree

3 files changed

+13
-4
lines changed

3 files changed

+13
-4
lines changed

Compiler/src/abstractinterpretation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3409,7 +3409,7 @@ function abstract_eval_statement_expr(interp::AbstractInterpreter, e::Expr, ssta
34093409
elseif ehead === :cfunction
34103410
return abstract_eval_cfunction(interp, e, sstate, sv)
34113411
elseif ehead === :method
3412-
rt = (length(e.args) == 1) ? Any : Nothing
3412+
rt = (length(e.args) == 1) ? Any : Method
34133413
return RTEffects(rt, Any, EFFECTS_UNKNOWN)
34143414
elseif ehead === :copyast
34153415
return abstract_eval_copyast(interp, e, sstate, sv)

src/interpreter.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,9 @@ static jl_value_t *eval_methoddef(jl_expr_t *ex, interpreter_state *s)
106106
}
107107
atypes = eval_value(args[1], s);
108108
meth = eval_value(args[2], s);
109-
jl_method_def((jl_svec_t*)atypes, mt, (jl_code_info_t*)meth, s->module);
109+
jl_method_t *ret = jl_method_def((jl_svec_t*)atypes, mt, (jl_code_info_t*)meth, s->module);
110110
JL_GC_POP();
111-
return jl_nothing;
111+
return (jl_value_t *)ret;
112112
}
113113

114114
// expression evaluator
@@ -626,7 +626,8 @@ static jl_value_t *eval_body(jl_array_t *stmts, interpreter_state *s, size_t ip,
626626
}
627627
else if (toplevel) {
628628
if (head == jl_method_sym && jl_expr_nargs(stmt) > 1) {
629-
eval_methoddef((jl_expr_t*)stmt, s);
629+
jl_value_t *res = eval_methoddef((jl_expr_t*)stmt, s);
630+
s->locals[jl_source_nslots(s->src) + s->ip] = res;
630631
}
631632
else if (head == jl_toplevel_sym) {
632633
jl_value_t *res = jl_toplevel_eval(s->module, stmt);

test/syntax.jl

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4315,3 +4315,11 @@ module DoubleImport
43154315
import Random
43164316
end
43174317
@test DoubleImport.Random === Test.Random
4318+
4319+
# Expr(:method) returns the method
4320+
let ex = @Meta.lower function return_my_method(); 1; end
4321+
code = ex.args[1].code
4322+
idx = findfirst(ex->Meta.isexpr(ex, :method) && length(ex.args) > 1, code)
4323+
code[end] = Core.ReturnNode(Core.SSAValue(idx))
4324+
@test isa(Core.eval(@__MODULE__, ex), Method)
4325+
end

0 commit comments

Comments
 (0)