Skip to content

Add support for namespaced method call #25052

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 3 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -294,13 +294,7 @@ This section lists changes that do not have deprecation warnings.
* The return type of `reinterpret` has changed to `ReinterpretArray`. `reinterpret` on sparse
arrays has been discontinued.

* `Base.find_in_path` is now `Base.find_package` or `Base.find_source_file` ([#24320]).

* `finalizer` now takes functions or pointers as its first argument, and the object being
finalized as its second (rather than the reverse). For the majority of use cases
deprecation warnings will be triggered. However, deprecation warnings will not trigger where
(1) the callable argument is not a subtype of `Function`; or (2) both arguments are
`Function`s or `Ptr{Void}`s ([#24605]).
* `Base.find_in_path` is now `Base.find_package` or `Base.find_source_file` ([#24320])

* The `kill` function now throws errors on user error (e.g. on permission
errors), but returns successfully if the process had previously exited.
Expand Down
10 changes: 0 additions & 10 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2178,16 +2178,6 @@ end
@deprecate cumsum(A::AbstractArray) cumsum(A, 1)
@deprecate cumprod(A::AbstractArray) cumprod(A, 1)

# issue #16307
@deprecate finalizer(o, f::Function) finalizer(f, o)
# This misses other callables but they are very rare in the wild
@deprecate finalizer(o, f::Ptr{Void}) finalizer(f, o)

# Avoid ambiguity, can remove when deprecations are removed:
# This is almost certainly going to be a silent failure for code that is not updated.
finalizer(f::Ptr{Void}, o::Ptr{Void}) = invoke(finalizer, Tuple{Ptr{Void}, Any}, f, o)
finalizer(f::Ptr{Void}, o::Function) = invoke(finalizer, Tuple{Ptr{Void}, Any}, f, o)

# Broadcast extension API (#23939)
@eval Broadcast begin
Base.@deprecate_binding containertype combine_styles false
Expand Down
33 changes: 33 additions & 0 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,16 @@ macro _gc_preserve_end(token)
Expr(:gc_preserve_end, esc(token))
end

"""
@__MODULE__ -> Module

Get the `Module` of the toplevel eval,
which is the `Module` code is currently being read from.
"""
macro __MODULE__()
return __module__
end

"""
@nospecialize

Expand Down Expand Up @@ -666,6 +676,29 @@ function invokelatest(f, args...; kwargs...)
Core._apply_latest(inner)
end

# Use an explicit closure so that type inference can construct it
struct FieldFunc{F,T}
f::F
v::T
FieldFunc{F,T}(f::F, v::T) where {F,T} = new(f, v)
end
FieldFunc(f::F, v::T) where {F,T} = FieldFunc{F,T}(f, v)
FieldFunc(f::F, ::Type{T}) where {F,T} = FieldFunc{F,Type{T}}(f, T)

function (f::FieldFunc)(args...; kwargs...)
@_inline_meta
return f.f(f.v, args...; kwargs...)
end

function fieldcall_lookup(@nospecialize(obj), field::Symbol)
if isa(obj, Module)
return Core.getfield(obj, field)
end
f = ccall(:jl_fieldcall_lookup, Any, (Any, Any, Any),
@__MODULE__, typeof(obj), field)
return FieldFunc(f, obj)
end

# iteration protocol

"""
Expand Down
4 changes: 2 additions & 2 deletions base/event.jl
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,7 @@ mutable struct AsyncCondition
function AsyncCondition()
this = new(Libc.malloc(_sizeof_uv_async), Condition(), true)
associate_julia_struct(this.handle, this)
finalizer(uvfinalize, this)
finalizer(this, uvfinalize)
err = ccall(:uv_async_init, Cint, (Ptr{Void}, Ptr{Void}, Ptr{Void}),
eventloop(), this, uv_jl_asynccb::Ptr{Void})
if err != 0
Expand Down Expand Up @@ -369,7 +369,7 @@ mutable struct Timer
end

associate_julia_struct(this.handle, this)
finalizer(uvfinalize, this)
finalizer(this, uvfinalize)

ccall(:uv_update_time, Void, (Ptr{Void},), eventloop())
ccall(:uv_timer_start, Cint, (Ptr{Void}, Ptr{Void}, UInt64, UInt64),
Expand Down
6 changes: 3 additions & 3 deletions base/gcutils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
==(w, v::WeakRef) = isequal(w, v.value)

"""
finalizer(f, x)
finalizer(x, f)

Register a function `f(x)` to be called when there are no program-accessible references to
`x`, and return `x`. The type of `x` must be a `mutable struct`, otherwise the behavior of
this function is unpredictable.
"""
function finalizer(@nospecialize(f), @nospecialize(o))
function finalizer(@nospecialize(o), @nospecialize(f))
if isimmutable(o)
error("objects of type ", typeof(o), " cannot be finalized")
end
Expand All @@ -20,7 +20,7 @@ function finalizer(@nospecialize(f), @nospecialize(o))
return o
end

function finalizer(f::Ptr{Void}, o::T) where T
function finalizer(o::T, f::Ptr{Void}) where T
@_inline_meta
if isimmutable(T)
error("objects of type ", T, " cannot be finalized")
Expand Down
2 changes: 1 addition & 1 deletion base/gmp.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ mutable struct BigInt <: Signed
function BigInt()
b = new(zero(Cint), zero(Cint), C_NULL)
MPZ.init!(b)
finalizer(cglobal((:__gmpz_clear, :libgmp)), b)
finalizer(b, cglobal((:__gmpz_clear, :libgmp)))
return b
end
end
Expand Down
78 changes: 78 additions & 0 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1806,6 +1806,38 @@ function builtin_tfunction(@nospecialize(f), argtypes::Array{Any,1},
return tf[3](argtypes...)
end

function get_type_module(@nospecialize(ty))
# TODO: this can be relaxed
isleaftype(ty) || return nothing
return ty.name.module
end

function fieldcall_lookup_tfunc(@nospecialize(f), argtypes, sv)
objt = argtypes[2]
objtw = widenconst(objt)
fldt = argtypes[3]
if objtw === Module
return getfield_tfunc(objt, fldt)
elseif !isleaftype(objtw)
return Any
elseif !(isa(fldt, Const) && isa(fldt.val, Symbol))
return Any
end
fld = fldt.val::Symbol
tymod = get_type_module(objtw)
parent_mod = typeof(f).name.module
if tymod === nothing
return Any
elseif tymod === Core
tymod = parent_mod
end
FieldFuncT = parent_mod.FieldFunc
newft = abstract_eval_global(tymod, fld)
new_types = [Type{FieldFuncT}, newft, objtw]
return abstract_call_gf_by_type(FieldFuncT, new_types,
argtypes_to_type(new_types), sv)
end

limit_tuple_depth(params::InferenceParams, @nospecialize(t)) = limit_tuple_depth_(params,t,0)

function limit_tuple_depth_(params::InferenceParams, @nospecialize(t), d::Int)
Expand Down Expand Up @@ -2492,6 +2524,8 @@ function abstract_call(@nospecialize(f), fargs::Union{Tuple{},Vector{Any}}, argt
end
end
return isa(rt, TypeVar) ? rt.ub : rt
elseif length(fargs) == 3 && istopfunction(tm, f, :fieldcall_lookup)
return fieldcall_lookup_tfunc(f, argtypes, sv)
elseif f === Core.kwfunc
if length(argtypes) == 2
ft = widenconst(argtypes[2])
Expand Down Expand Up @@ -4582,6 +4616,45 @@ function invoke_NF(argexprs, @nospecialize(etype), atypes::Vector{Any}, sv::Opti
return NF
end

function try_inline_fieldcall_lookup(@nospecialize(f),
@nospecialize(ft), e, atypes,
pending_stmt, boundscheck, sv)
objt = atypes[2]
objtw = widenconst(objt)
fldt = atypes[3]
if !(isa(fldt, Const) && isa(fldt.val, Symbol))
return NF
end
fld = fldt.val::Symbol
argexprs = e.args
if objtw === Module
argexprs[1] = getfield
atypes[1] = typeof(getfield)
return inlineable(getfield, typeof(getfield), e, atypes,
pending_stmt, boundscheck, sv)
end
tymod = get_type_module(objtw)
parent_mod = typeof(f).name.module
if tymod === nothing
return Any
elseif tymod === Core
tymod = parent_mod
end
newft = abstract_eval_global(tymod, fld)
FieldFuncT = parent_mod.FieldFunc
# obj
argexprs[3] = argexprs[2]
atypes[3] = atypes[2]
# func
argexprs[2] = GlobalRef(tymod, fld)
atypes[2] = newft
# FieldFunc
argexprs[1] = FieldFuncT
atypes[1] = Type{FieldFuncT}
return inlineable(FieldFuncT, Type{FieldFuncT}, e, atypes,
pending_stmt, boundscheck, sv)
end

# inline functions whose bodies are "inline_worthy"
# where the function body doesn't contain any argument more than once.
# static parameters are ok if all the static parameter values are leaf types,
Expand All @@ -4603,6 +4676,11 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
end
end
topmod = _topmod(sv)
if istopfunction(topmod, f, :fieldcall_lookup)
return try_inline_fieldcall_lookup(f, ft, e, atypes,
pending_stmt,
boundscheck, sv)
end
# special-case inliners for known pure functions that compute types
if sv.params.inlining
if isa(e.typ, Const) # || isconstType(e.typ)
Expand Down
2 changes: 1 addition & 1 deletion base/iostream.jl
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ function IOStream(name::AbstractString, finalize::Bool)
buf = zeros(UInt8,sizeof_ios_t)
x = IOStream(name, buf)
if finalize
finalizer(close, x)
finalizer(x, close)
end
return x
end
Expand Down
2 changes: 1 addition & 1 deletion base/libgit2/gitcredential.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mutable struct GitCredential
username::Nullable{<:AbstractString},
password::Nullable{<:AbstractString})
c = new(protocol, host, path, username, password, true)
finalizer(securezero!, c)
finalizer(c, securezero!)
return c
end
end
Expand Down
10 changes: 5 additions & 5 deletions base/libgit2/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -944,7 +944,7 @@ for (typ, owntyp, sup, cname) in [
obj = new(ptr)
if fin
Threads.atomic_add!(REFCOUNT, UInt(1))
finalizer(Base.close, obj)
finalizer(obj, Base.close)
end
return obj
end
Expand All @@ -958,7 +958,7 @@ for (typ, owntyp, sup, cname) in [
obj = new(owner, ptr)
if fin
Threads.atomic_add!(REFCOUNT, UInt(1))
finalizer(Base.close, obj)
finalizer(obj, Base.close)
end
return obj
end
Expand Down Expand Up @@ -1000,7 +1000,7 @@ mutable struct GitSignature <: AbstractGitObject
function GitSignature(ptr::Ptr{SignatureStruct})
@assert ptr != C_NULL
obj = new(ptr)
finalizer(Base.close, obj)
finalizer(obj, Base.close)
return obj
end
end
Expand Down Expand Up @@ -1143,7 +1143,7 @@ mutable struct UserPasswordCredential <: AbstractCredential
pass::String
function UserPasswordCredential(user::AbstractString="", pass::AbstractString="")
c = new(user, pass)
finalizer(securezero!, c)
finalizer(c, securezero!)
return c
end

Expand Down Expand Up @@ -1181,7 +1181,7 @@ mutable struct SSHCredential <: AbstractCredential
function SSHCredential(user::AbstractString="", pass::AbstractString="",
prvkey::AbstractString="", pubkey::AbstractString="")
c = new(user, pass, prvkey, pubkey)
finalizer(securezero!, c)
finalizer(c, securezero!)
return c
end

Expand Down
2 changes: 1 addition & 1 deletion base/locks.jl
Original file line number Diff line number Diff line change
Expand Up @@ -185,7 +185,7 @@ mutable struct Mutex <: AbstractLock
function Mutex()
m = new(zero(Int16), Libc.malloc(UV_MUTEX_SIZE))
ccall(:uv_mutex_init, Void, (Ptr{Void},), m.handle)
finalizer(_uv_hook_close, m)
finalizer(m, _uv_hook_close)
return m
end
end
Expand Down
4 changes: 2 additions & 2 deletions base/mpfr.jl
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ mutable struct BigFloat <: AbstractFloat
prec = precision(BigFloat)
z = new(zero(Clong), zero(Cint), zero(Clong), C_NULL)
ccall((:mpfr_init2,:libmpfr), Void, (Ref{BigFloat}, Clong), z, prec)
finalizer(cglobal((:mpfr_clear, :libmpfr)), z)
finalizer(z, cglobal((:mpfr_clear, :libmpfr)))
return z
end

Expand Down Expand Up @@ -967,7 +967,7 @@ function Base.deepcopy_internal(x::BigFloat, stackdict::ObjectIdDict)
prec = precision(x)
y = BigFloat(zero(Clong), zero(Cint), zero(Clong), C_NULL)
ccall((:mpfr_init2,:libmpfr), Void, (Ref{BigFloat}, Clong), y, prec)
finalizer(cglobal((:mpfr_clear, :libmpfr)), y)
finalizer(y, cglobal((:mpfr_clear, :libmpfr)))
ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), y, x, ROUNDING_MODE[])
stackdict[x] = y
return y
Expand Down
4 changes: 2 additions & 2 deletions base/precompile.jl
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ precompile(Tuple{typeof(Base.convert), Type{Ptr{Int32}}, Ptr{UInt8}})
precompile(Tuple{Type{Base.Multimedia.TextDisplay}, Base.TTY})
precompile(Tuple{typeof(Base._start)})
precompile(Tuple{typeof(Base.copy!), Array{String, 1}, Int64, Array{Any, 1}, Int64, Int64})
precompile(Tuple{typeof(Base.finalizer), typeof(Base.uvfinalize), Base.TCPServer})
precompile(Tuple{typeof(Base.finalizer), Base.TCPServer, typeof(Base.uvfinalize)})
precompile(Tuple{Type{Base.TCPServer}, Ptr{Void}, Int64})
precompile(Tuple{typeof(Base.show), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Int32})
precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.Libc.RawFD})
Expand Down Expand Up @@ -94,7 +94,7 @@ precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tu
precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Int64})
precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Int64})
precompile(Tuple{typeof(Core.Inference.isbits), Base.DevNullStream})
precompile(Tuple{typeof(Base.finalizer), typeof(Base.uvfinalize), Base.Process})
precompile(Tuple{typeof(Base.finalizer), Base.Process, typeof(Base.uvfinalize)})
precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Base.DevNullStream, Bool}})
precompile(Tuple{Type{Ref{Base.Cstring}}, Array{String, 1}})
precompile(Tuple{typeof(Core.Inference.eltype), Type{Array{String, 1}}})
Expand Down
2 changes: 1 addition & 1 deletion base/process.jl
Original file line number Diff line number Diff line change
Expand Up @@ -328,7 +328,7 @@ mutable struct Process <: AbstractPipe
typemin(fieldtype(Process, :exitcode)),
typemin(fieldtype(Process, :termsignal)),
Condition(), Condition())
finalizer(uvfinalize, this)
finalizer(this, uvfinalize)
return this
end
end
Expand Down
10 changes: 0 additions & 10 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,6 @@ Base.LinAlg
"""
module_parent(m::Module) = ccall(:jl_module_parent, Ref{Module}, (Any,), m)

"""
@__MODULE__ -> Module

Get the `Module` of the toplevel eval,
which is the `Module` code is currently being read from.
"""
macro __MODULE__()
return __module__
end

"""
fullname(m::Module)

Expand Down
8 changes: 4 additions & 4 deletions base/regex.jl
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,10 @@ mutable struct Regex
end
re = compile(new(pattern, compile_options, match_options, C_NULL,
C_NULL, Csize_t[], C_NULL))
finalizer(re) do re
re.regex == C_NULL || PCRE.free_re(re.regex)
re.match_data == C_NULL || PCRE.free_match_data(re.match_data)
end
finalizer(re, re->begin
re.regex == C_NULL || PCRE.free_re(re.regex)
re.match_data == C_NULL || PCRE.free_match_data(re.match_data)
end)
re
end
end
Expand Down
4 changes: 1 addition & 3 deletions base/repl/REPL.jl
Original file line number Diff line number Diff line change
Expand Up @@ -836,9 +836,7 @@ function setup_interface(
try
hist_path = find_hist_file()
f = open(hist_path, true, true, true, false, false)
finalizer(replc) do replc
close(f)
end
finalizer(replc, replc->close(f))
hist_from_file(hp, f, hist_path)
catch e
print_response(repl, e, catch_backtrace(), true, Base.have_color)
Expand Down
Loading