diff --git a/base/essentials.jl b/base/essentials.jl index a01598ca4a6ca..9bdf306cac43e 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -713,7 +713,7 @@ call obsolete versions of a function `f`. `f` directly, and the type of the result cannot be inferred by the compiler.) """ function invokelatest(@nospecialize(f), @nospecialize args...; kwargs...) - kwargs = Base.merge(NamedTuple(), kwargs) + kwargs = merge(NamedTuple(), kwargs) if isempty(kwargs) return Core._call_latest(f, args...) end diff --git a/base/reflection.jl b/base/reflection.jl index 29a4b5f4a66ca..870103f612a11 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -1645,7 +1645,6 @@ min_world(m::Core.CodeInfo) = m.min_world max_world(m::Core.CodeInfo) = m.max_world get_world_counter() = ccall(:jl_get_world_counter, UInt, ()) - """ propertynames(x, private=false) @@ -1676,3 +1675,51 @@ Return a boolean indicating whether the object `x` has `s` as one of its own pro See also: [`propertynames`](@ref), [`hasfield`](@ref). """ hasproperty(x, s::Symbol) = s in propertynames(x) + +""" + @invoke f(arg::T, ...; kwargs...) + +Provides a convenient way to call [`invoke`](@ref); +`@invoke f(arg1::T1, arg2::T2; kwargs...)` will be expanded into `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)`. +When an argument's type annotation is omitted, it's specified as `Any` argument, e.g. +`@invoke f(arg1::T, arg2)` will be expanded into `invoke(f, Tuple{T,Any}, arg1, arg2)`. +""" +macro invoke(ex) + f, args, kwargs = destructure_callex(ex) + arg2typs = map(args) do x + isexpr(x, :(::)) ? (x.args...,) : (x, GlobalRef(Core, :Any)) + end + args, argtypes = first.(arg2typs), last.(arg2typs) + return esc(:($(GlobalRef(Core, :invoke))($(f), Tuple{$(argtypes...)}, $(args...); $(kwargs...)))) +end + +""" + @invokelatest f(args...; kwargs...) + +Provides a convenient way to call [`Base.invokelatest`](@ref). +`@invokelatest f(args...; kwargs...)` will simply be expanded into +`Base.invokelatest(f, args...; kwargs...)`. +""" +macro invokelatest(ex) + f, args, kwargs = destructure_callex(ex) + return esc(:($(GlobalRef(@__MODULE__, :invokelatest))($(f), $(args...); $(kwargs...)))) +end + +function destructure_callex(ex) + isexpr(ex, :call) || throw(ArgumentError("a call expression f(args...; kwargs...) should be given")) + + f = first(ex.args) + args = [] + kwargs = [] + for x in ex.args[2:end] + if isexpr(x, :parameters) + append!(kwargs, x.args) + elseif isexpr(x, :kw) + push!(kwargs, x) + else + push!(args, x) + end + end + + return f, args, kwargs +end diff --git a/base/util.jl b/base/util.jl index a8bbd92116a83..f26823cc69ad8 100644 --- a/base/util.jl +++ b/base/util.jl @@ -536,54 +536,6 @@ function _kwdef!(blk, params_args, call_args) blk end -""" - @invoke f(arg::T, ...; kwargs...) - -Provides a convenient way to call [`invoke`](@ref); -`@invoke f(arg1::T1, arg2::T2; kwargs...)` will be expanded into `invoke(f, Tuple{T1,T2}, arg1, arg2; kwargs...)`. -When an argument's type annotation is omitted, it's specified as `Any` argument, e.g. -`@invoke f(arg1::T, arg2)` will be expanded into `invoke(f, Tuple{T,Any}, arg1, arg2)`. -""" -macro invoke(ex) - f, args, kwargs = destructure_callex(ex) - arg2typs = map(args) do x - is_expr(x, :(::)) ? (x.args...,) : (x, GlobalRef(Core, :Any)) - end - args, argtypes = first.(arg2typs), last.(arg2typs) - return esc(:($(GlobalRef(Core, :invoke))($(f), Tuple{$(argtypes...)}, $(args...); $(kwargs...)))) -end - -""" - @invokelatest f(args...; kwargs...) - -Provides a convenient way to call [`Base.invokelatest`](@ref). -`@invokelatest f(args...; kwargs...)` will simply be expanded into -`Base.invokelatest(f, args...; kwargs...)`. -""" -macro invokelatest(ex) - f, args, kwargs = destructure_callex(ex) - return esc(:($(GlobalRef(Base, :invokelatest))($(f), $(args...); $(kwargs...)))) -end - -function destructure_callex(ex) - is_expr(ex, :call) || throw(ArgumentError("a call expression f(args...; kwargs...) should be given")) - - f = first(ex.args) - args = [] - kwargs = [] - for x in ex.args[2:end] - if is_expr(x, :parameters) - append!(kwargs, x.args) - elseif is_expr(x, :kw) - push!(kwargs, x) - else - push!(args, x) - end - end - - return f, args, kwargs -end - # testing """