Skip to content

Commit 1570bed

Browse files
authored
Align :method Expr return value between interpreter and codegen (#58076)
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 8681bb8 commit 1570bed

File tree

5 files changed

+34
-17
lines changed

5 files changed

+34
-17
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);

src/julia-syntax.scm

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -439,9 +439,11 @@
439439
,body))))
440440
(if (or (symbol? name) (globalref? name))
441441
`(block ,@generator (method ,name) (latestworld-if-toplevel) ,mdef (unnecessary ,name)) ;; return the function
442-
(if (not (null? generator))
443-
`(block ,@generator ,mdef)
444-
mdef))))))
442+
(if (overlay? name)
443+
(if (not (null? generator))
444+
`(block ,@generator ,mdef)
445+
mdef)
446+
`(block ,@generator ,mdef (null))))))))
445447

446448
;; wrap expr in nested scopes assigning names to vals
447449
(define (scopenest names vals expr)
@@ -4127,6 +4129,7 @@ f(x) = yt(x)
41274129
'()
41284130
(map-cl-convert (butlast (cdr sig))
41294131
fname lam namemap defined toplevel interp opaq parsed-method-stack globals locals)))
4132+
(r (make-ssavalue))
41304133
(sig (and sig (if (eq? (car sig) 'block)
41314134
(last sig)
41324135
sig))))
@@ -4150,7 +4153,7 @@ f(x) = yt(x)
41504153
((null? cvs)
41514154
`(block
41524155
,@sp-inits
4153-
(method ,(cadr e) ,(cl-convert
4156+
(= ,r (method ,(cadr e) ,(cl-convert
41544157
;; anonymous functions with keyword args generate global
41554158
;; functions that refer to the type of a local function
41564159
(rename-sig-types sig namemap)
@@ -4162,17 +4165,19 @@ f(x) = yt(x)
41624165
`(lambda ,(cadr lam2)
41634166
(,(clear-capture-bits (car vis))
41644167
,@(cdr vis))
4165-
,body)))
4166-
(latestworld)))
4168+
,body))))
4169+
(latestworld)
4170+
,r))
41674171
(else
41684172
(let* ((exprs (lift-toplevel (convert-lambda lam2 '|#anon| #t '() #f parsed-method-stack)))
41694173
(top-stmts (cdr exprs))
41704174
(newlam (compact-and-renumber (linearize (car exprs)) 'none 0)))
41714175
`(toplevel-butfirst
41724176
(block ,@sp-inits
4173-
(method ,(cadr e) ,(cl-convert sig fname lam namemap defined toplevel interp opaq parsed-method-stack globals locals)
4174-
,(julia-bq-macro newlam))
4175-
(latestworld))
4177+
(= ,r (method ,(cadr e) ,(cl-convert sig fname lam namemap defined toplevel interp opaq parsed-method-stack globals locals)
4178+
,(julia-bq-macro newlam)))
4179+
(latestworld)
4180+
,r)
41764181
,@top-stmts))))
41774182

41784183
;; local case - lift to a new type at top level
@@ -4999,8 +5004,10 @@ f(x) = yt(x)
49995004
(let ((l (make-ssavalue)))
50005005
(emit `(= ,l ,(compile lam break-labels #t #f)))
50015006
l))))
5002-
(emit `(method ,(or (cadr e) '(false)) ,sig ,lam))
5003-
(if value (compile '(null) break-labels value tail)))
5007+
(let ((val (make-ssavalue)))
5008+
(emit `(= ,val (method ,(or (cadr e) '(false)) ,sig ,lam)))
5009+
(if tail (emit-return tail val))
5010+
val))
50045011
(cond (tail (emit-return tail e))
50055012
(value e)
50065013
(else (emit e)))))

test/core.jl

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8308,11 +8308,12 @@ end
83088308
module OverlayModule
83098309

83108310
using Base.Experimental: @MethodTable, @overlay
8311+
using Test
83118312

83128313
@MethodTable mt
83138314
# long function def
8314-
@overlay mt function sin(x::Float64)
8315-
1
8315+
let m = @overlay mt function sin(x::Float64); 1; end
8316+
@test isa(m, Method)
83168317
end
83178318
# short function def
83188319
@overlay mt cos(x::Float64) = 2

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)