diff --git a/src/construct.jl b/src/construct.jl index 1b3766ef..17fcc5e5 100644 --- a/src/construct.jl +++ b/src/construct.jl @@ -479,8 +479,8 @@ function queuenext!(iter::ExprSplitter) if head === :module # Find or create the module newname = ex.args[2]::Symbol - if isdefined(mod, newname) - newmod = getfield(mod, newname) + if invokelatest(isdefined, mod, newname) + newmod = invokelatest(getfield, mod, newname) newmod isa Module || throw(ErrorException("invalid redefinition of constant $(newname)")) mod = newmod else diff --git a/src/interpret.jl b/src/interpret.jl index 3d77a11c..f9615003 100644 --- a/src/interpret.jl +++ b/src/interpret.jl @@ -2,7 +2,7 @@ isassign(frame::Frame) = isassign(frame, frame.pc) isassign(frame::Frame, pc::Int) = (pc in frame.framecode.used) lookup_var(frame::Frame, val::SSAValue) = frame.framedata.ssavalues[val.id] -lookup_var(frame::Frame, ref::GlobalRef) = @invokelatest getfield(ref.mod, ref.name) +lookup_var(frame::Frame, ref::GlobalRef) = invokelatest(getfield, ref.mod, ref.name) function lookup_var(frame::Frame, slot::SlotNumber) val = frame.framedata.locals[slot.id] val !== nothing && return val.value @@ -31,7 +31,7 @@ macro lookup(args...) nodetmp = gensym(:node) # used to hoist, e.g., args[4] if havemod fallback = quote - isa($nodetmp, Symbol) ? getfield($(esc(mod)), $nodetmp) : + isa($nodetmp, Symbol) ? invokelatest(getfield, $(esc(mod)), $nodetmp) : $nodetmp end else @@ -45,7 +45,7 @@ macro lookup(args...) isa($nodetmp, GlobalRef) ? lookup_var($(esc(frame)), $nodetmp) : isa($nodetmp, SlotNumber) ? lookup_var($(esc(frame)), $nodetmp) : isa($nodetmp, QuoteNode) ? $nodetmp.value : - isa($nodetmp, Symbol) ? getfield(moduleof($(esc(frame))), $nodetmp) : + isa($nodetmp, Symbol) ? invokelatest(getfield, moduleof($(esc(frame))), $nodetmp) : isa($nodetmp, Expr) ? lookup_expr($(esc(frame)), $nodetmp) : $fallback end @@ -90,7 +90,7 @@ function lookup_or_eval(@nospecialize(recurse), frame::Frame, @nospecialize(node elseif isa(node, GlobalRef) return lookup_var(frame, node) elseif isa(node, Symbol) - return getfield(moduleof(frame), node) + return invokelatest(getfield, moduleof(frame), node) elseif isa(node, QuoteNode) return node.value elseif isa(node, Expr) @@ -111,7 +111,7 @@ function lookup_or_eval(@nospecialize(recurse), frame::Frame, @nospecialize(node elseif f === typeassert && length(ex.args) == 3 return typeassert(ex.args[2], ex.args[3]) elseif f === Base.getproperty && length(ex.args) == 3 - return Base.getproperty(ex.args[2], ex.args[3]) + return invokelatest(Base.getproperty, ex.args[2], ex.args[3]) elseif f === Core.Compiler.Val && length(ex.args) == 2 return Core.Compiler.Val(ex.args[2]) elseif f === Val && length(ex.args) == 2 @@ -311,10 +311,16 @@ function evaluate_methoddef(frame::Frame, node::Expr) if f isa Symbol || f isa GlobalRef mod = f isa Symbol ? moduleof(frame) : f.mod name = f isa Symbol ? f : f.name - if Base.isbindingresolved(mod, name) && @invokelatest isdefined(mod, name) # `isdefined` accesses the binding, making it impossible to create a new one - f = @invokelatest getfield(mod, name) + if isbindingresolved_deprecated + f = Core.eval(mod, Expr(:function, name)) else - f = Core.eval(mod, Expr(:function, name)) # create a new function + # TODO: This logic isn't fully correct, but it's been used for a long + # time, so let's leave it for now. + if Base.isbindingresolved(mod, name) && @invokelatest isdefined(mod, name) # `isdefined` accesses the binding, making it impossible to create a new one + f = @invokelatest getfield(mod, name) + else + f = Core.eval(mod, Expr(:function, name)) # create a new function + end end end length(node.args) == 1 && return f @@ -563,7 +569,7 @@ function step_expr!(@nospecialize(recurse), frame::Frame, @nospecialize(node), i # FIXME: undefine the slot? elseif istoplevel && isa(node, LineNumberNode) elseif istoplevel && isa(node, Symbol) - rhs = getfield(moduleof(frame), node) + rhs = invokelatest(getfield, moduleof(frame), node) elseif @static (isdefined(Core.IR, :EnterNode) && true) && isa(node, Core.IR.EnterNode) rhs = node.catch_dest push!(data.exception_frames, rhs) diff --git a/src/localmethtable.jl b/src/localmethtable.jl index f535635b..6fe5b00d 100644 --- a/src/localmethtable.jl +++ b/src/localmethtable.jl @@ -61,7 +61,7 @@ function get_call_framecode(fargs::Vector{Any}, parentframe::FrameCode, idx::Int # We haven't yet encountered this argtype combination and need to look it up by dispatch fargs[1] = f = to_function(fargs[1]) ret = prepare_call(f, fargs; enter_generated=enter_generated) - ret === nothing && return f(fargs[2:end]...), nothing + ret === nothing && return invokelatest(f, fargs[2:end]...), nothing is_compiled = isa(ret[1], Compiled) local framecode if is_compiled diff --git a/src/optimize.jl b/src/optimize.jl index 39343011..a62fda11 100644 --- a/src/optimize.jl +++ b/src/optimize.jl @@ -23,10 +23,12 @@ function smallest_ref(stmts, arg, idmin) return idmin end +const isbindingresolved_deprecated = which(Base.isbindingresolved, Tuple{Module, Symbol}).file == Symbol("deprecated.jl") function lookup_global_ref(a::GlobalRef) - if (Base.isbindingresolved(a.mod, a.name) && + isbindingresolved_deprecated && return a + if Base.isbindingresolved(a.mod, a.name) && (@invokelatest isdefined(a.mod, a.name)) && - (@invokelatest isconst(a.mod, a.name))) + (@invokelatest isconst(a.mod, a.name)) return QuoteNode(@invokelatest getfield(a.mod, a.name)) end return a diff --git a/src/packagedef.jl b/src/packagedef.jl index 17ed49c9..5a00d08a 100644 --- a/src/packagedef.jl +++ b/src/packagedef.jl @@ -1,5 +1,5 @@ using Base.Meta -import Base: +, -, convert, isless, get_world_counter, mapany, ntupleany +import Base: +, -, convert, isless, get_world_counter, mapany, ntupleany, invokelatest using Core: CodeInfo, SimpleVector, LineInfoNode, GotoNode, GotoIfNot, ReturnNode, GeneratedFunctionStub, MethodInstance, NewvarNode, TypeName diff --git a/src/utils.jl b/src/utils.jl index d349f850..6f82b7c0 100644 --- a/src/utils.jl +++ b/src/utils.jl @@ -22,7 +22,7 @@ end _Typeof(x) = isa(x, Type) ? Type{x} : typeof(x) function to_function(@nospecialize(x)) - isa(x, GlobalRef) ? getfield(x.mod, x.name) : x + isa(x, GlobalRef) ? invokelatest(getfield, x.mod, x.name) : x end """