Skip to content

Commit 52d81b0

Browse files
oxinaboxSacha0
authored andcommitted
Finalizers take function as first argument (closes #16307) (#24605)
make finalizers take function as first argument
1 parent f9db0ab commit 52d81b0

34 files changed

+103
-76
lines changed

NEWS.md

+7-1
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,13 @@ This section lists changes that do not have deprecation warnings.
275275
* The return type of `reinterpret` has changed to `ReinterpretArray`. `reinterpret` on sparse
276276
arrays has been discontinued.
277277

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

280286
* The `kill` function now throws errors on user error (e.g. on permission
281287
errors), but returns successfully if the process had previously exited.

base/deprecated.jl

+11
Original file line numberDiff line numberDiff line change
@@ -2200,6 +2200,17 @@ end
22002200
@deprecate chol!(x::Number, uplo) chol(x) false
22012201
end
22022202

2203+
2204+
# issue #16307
2205+
@deprecate finalizer(o, f::Function) finalizer(f, o)
2206+
# This misses other callables but they are very rare in the wild
2207+
@deprecate finalizer(o, f::Ptr{Void}) finalizer(f, o)
2208+
2209+
# Avoid ambiguity, can remove when deprecations are removed:
2210+
# This is almost certainly going to be a silent failure for code that is not updated.
2211+
finalizer(f::Ptr{Void}, o::Ptr{Void}) = invoke(finalizer, Tuple{Ptr{Void}, Any}, f, o)
2212+
finalizer(f::Ptr{Void}, o::Function) = invoke(finalizer, Tuple{Ptr{Void}, Any}, f, o)
2213+
22032214
# END 0.7 deprecations
22042215

22052216
# BEGIN 1.0 deprecations

base/distributed/cluster.jl

+5-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,11 @@ function create_worker(manager, wconfig)
518518

519519
w = Worker(w.id, r_s, w_s, manager; config=wconfig)
520520
# install a finalizer to perform cleanup if necessary
521-
finalizer(w, (w)->if myid() == 1 manage(w.manager, w.id, w.config, :finalize) end)
521+
finalizer(w) do w
522+
if myid() == 1
523+
manage(w.manager, w.id, w.config, :finalize)
524+
end
525+
end
522526

523527
# set when the new worker has finshed connections with all other workers
524528
ntfy_oid = RRID()

base/distributed/clusterserialize.jl

+6-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,9 @@ function serialize(s::ClusterSerializer, t::TypeName)
7474
serialize_typename(s, t)
7575
s.anonfunc_id = prev
7676
push!(s.tn_obj_sent, identifier)
77-
finalizer(t, x->cleanup_tname_glbs(s, identifier))
77+
finalizer(t) do x
78+
cleanup_tname_glbs(s, identifier)
79+
end
7880
end
7981

8082
# Send global refs if required.
@@ -133,7 +135,9 @@ function serialize_global_from_main(s::ClusterSerializer, sym)
133135
elseif !haskey(s.glbs_sent, oid)
134136
# set up a finalizer the first time this object is sent
135137
try
136-
finalizer(v, x->delete_global_tracker(s,x))
138+
finalizer(v) do x
139+
delete_global_tracker(s,x)
140+
end
137141
catch ex
138142
# Do not track objects that cannot be finalized.
139143
if isa(ex, ErrorException)

base/distributed/remotecall.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -52,13 +52,13 @@ function test_existing_ref(r::AbstractRemoteRef)
5252
end
5353

5454
client_refs[r] = nothing
55-
finalizer(r, finalize_ref)
55+
finalizer(finalize_ref, r)
5656
return r
5757
end
5858

5959
function finalize_ref(r::AbstractRemoteRef)
6060
if r.where > 0 # Handle the case of the finalizer having been called manually
61-
islocked(client_refs) && return finalizer(r, finalize_ref) # delay finalizer for later, when it's not already locked
61+
islocked(client_refs) && return finalizer(finalize_ref, r) # delay finalizer for later, when it's not already locked
6262
delete!(client_refs, r)
6363
if isa(r, RemoteChannel)
6464
send_del_client(r)

base/distributed/workerpool.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ mutable struct CachingPool <: AbstractWorkerPool
223223

224224
function CachingPool()
225225
wp = new(Channel{Int}(typemax(Int)), Set{Int}(), Dict{Int, Function}())
226-
finalizer(wp, clear!)
226+
finalizer(clear!, wp)
227227
wp
228228
end
229229
end

base/event.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ mutable struct AsyncCondition
303303
function AsyncCondition()
304304
this = new(Libc.malloc(_sizeof_uv_async), Condition(), true)
305305
associate_julia_struct(this.handle, this)
306-
finalizer(this, uvfinalize)
306+
finalizer(uvfinalize, this)
307307
err = ccall(:uv_async_init, Cint, (Ptr{Void}, Ptr{Void}, Ptr{Void}),
308308
eventloop(), this, uv_jl_asynccb::Ptr{Void})
309309
if err != 0
@@ -372,7 +372,7 @@ mutable struct Timer
372372
end
373373

374374
associate_julia_struct(this.handle, this)
375-
finalizer(this, uvfinalize)
375+
finalizer(uvfinalize, this)
376376

377377
ccall(:uv_update_time, Void, (Ptr{Void},), eventloop())
378378
ccall(:uv_timer_start, Cint, (Ptr{Void}, Ptr{Void}, UInt64, UInt64),

base/gcutils.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,21 @@
55
==(w, v::WeakRef) = isequal(w, v.value)
66

77
"""
8-
finalizer(x, f)
8+
finalizer(f, x)
99
1010
Register a function `f(x)` to be called when there are no program-accessible references to
1111
`x`. The type of `x` must be a `mutable struct`, otherwise the behavior of this function is
1212
unpredictable.
1313
"""
14-
function finalizer(@nospecialize(o), @nospecialize(f))
14+
function finalizer(@nospecialize(f), @nospecialize(o))
1515
if isimmutable(o)
1616
error("objects of type ", typeof(o), " cannot be finalized")
1717
end
1818
ccall(:jl_gc_add_finalizer_th, Void, (Ptr{Void}, Any, Any),
1919
Core.getptls(), o, f)
2020
end
2121

22-
function finalizer(o::T, f::Ptr{Void}) where T
22+
function finalizer(f::Ptr{Void}, o::T) where T
2323
@_inline_meta
2424
if isimmutable(T)
2525
error("objects of type ", T, " cannot be finalized")

base/gmp.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ mutable struct BigInt <: Signed
5555
function BigInt()
5656
b = new(zero(Cint), zero(Cint), C_NULL)
5757
MPZ.init!(b)
58-
finalizer(b, cglobal((:__gmpz_clear, :libgmp)))
58+
finalizer(cglobal((:__gmpz_clear, :libgmp)), b)
5959
return b
6060
end
6161
end

base/iostream.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ function IOStream(name::AbstractString, finalize::Bool)
1818
buf = zeros(UInt8,sizeof_ios_t)
1919
x = IOStream(name, buf)
2020
if finalize
21-
finalizer(x, close)
21+
finalizer(close, x)
2222
end
2323
return x
2424
end

base/libgit2/gitcredential.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ mutable struct GitCredential
1919
username::Nullable{<:AbstractString},
2020
password::Nullable{<:AbstractString})
2121
c = new(protocol, host, path, username, password, true)
22-
finalizer(c, securezero!)
22+
finalizer(securezero!, c)
2323
return c
2424
end
2525
end

base/libgit2/types.jl

+5-5
Original file line numberDiff line numberDiff line change
@@ -944,7 +944,7 @@ for (typ, owntyp, sup, cname) in [
944944
obj = new(ptr)
945945
if fin
946946
Threads.atomic_add!(REFCOUNT, UInt(1))
947-
finalizer(obj, Base.close)
947+
finalizer(Base.close, obj)
948948
end
949949
return obj
950950
end
@@ -958,7 +958,7 @@ for (typ, owntyp, sup, cname) in [
958958
obj = new(owner, ptr)
959959
if fin
960960
Threads.atomic_add!(REFCOUNT, UInt(1))
961-
finalizer(obj, Base.close)
961+
finalizer(Base.close, obj)
962962
end
963963
return obj
964964
end
@@ -1000,7 +1000,7 @@ mutable struct GitSignature <: AbstractGitObject
10001000
function GitSignature(ptr::Ptr{SignatureStruct})
10011001
@assert ptr != C_NULL
10021002
obj = new(ptr)
1003-
finalizer(obj, Base.close)
1003+
finalizer(Base.close, obj)
10041004
return obj
10051005
end
10061006
end
@@ -1144,7 +1144,7 @@ mutable struct UserPasswordCredentials <: AbstractCredentials
11441144
pass::String
11451145
function UserPasswordCredentials(user::AbstractString="", pass::AbstractString="")
11461146
c = new(user, pass)
1147-
finalizer(c, securezero!)
1147+
finalizer(securezero!, c)
11481148
return c
11491149
end
11501150

@@ -1182,7 +1182,7 @@ mutable struct SSHCredentials <: AbstractCredentials
11821182
function SSHCredentials(user::AbstractString="", pass::AbstractString="",
11831183
prvkey::AbstractString="", pubkey::AbstractString="")
11841184
c = new(user, pass, prvkey, pubkey)
1185-
finalizer(c, securezero!)
1185+
finalizer(securezero!, c)
11861186
return c
11871187
end
11881188

base/locks.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -185,7 +185,7 @@ mutable struct Mutex <: AbstractLock
185185
function Mutex()
186186
m = new(zero(Int16), Libc.malloc(UV_MUTEX_SIZE))
187187
ccall(:uv_mutex_init, Void, (Ptr{Void},), m.handle)
188-
finalizer(m, _uv_hook_close)
188+
finalizer(_uv_hook_close, m)
189189
return m
190190
end
191191
end

base/mpfr.jl

+2-2
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ mutable struct BigFloat <: AbstractFloat
6363
prec = precision(BigFloat)
6464
z = new(zero(Clong), zero(Cint), zero(Clong), C_NULL)
6565
ccall((:mpfr_init2,:libmpfr), Void, (Ref{BigFloat}, Clong), z, prec)
66-
finalizer(z, cglobal((:mpfr_clear, :libmpfr)))
66+
finalizer(cglobal((:mpfr_clear, :libmpfr)), z)
6767
return z
6868
end
6969

@@ -969,7 +969,7 @@ function Base.deepcopy_internal(x::BigFloat, stackdict::ObjectIdDict)
969969
prec = precision(x)
970970
y = BigFloat(zero(Clong), zero(Cint), zero(Clong), C_NULL)
971971
ccall((:mpfr_init2,:libmpfr), Void, (Ref{BigFloat}, Clong), y, prec)
972-
finalizer(y, cglobal((:mpfr_clear, :libmpfr)))
972+
finalizer(cglobal((:mpfr_clear, :libmpfr)), y)
973973
ccall((:mpfr_set, :libmpfr), Int32, (Ref{BigFloat}, Ref{BigFloat}, Int32), y, x, ROUNDING_MODE[])
974974
stackdict[x] = y
975975
return y

base/precompile.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ precompile(Tuple{typeof(Base.copy!), Array{String, 1}, Int64, Array{Any, 1}, Int
1919
precompile(Tuple{typeof(Base.empty!), Base.Dict{Int64, Union{Base.Distributed.Worker, Base.Distributed.LocalProcess}}})
2020
precompile(Tuple{typeof(Core.Inference.isbits), Base.Distributed.DefaultClusterManager})
2121
precompile(Tuple{typeof(Base.Distributed.init_worker), String, Base.Distributed.DefaultClusterManager})
22-
precompile(Tuple{typeof(Base.finalizer), Base.TCPServer, typeof(Base.uvfinalize)})
22+
precompile(Tuple{typeof(Base.finalizer), typeof(Base.uvfinalize), Base.TCPServer})
2323
precompile(Tuple{Type{Base.TCPServer}, Ptr{Void}, Int64})
2424
precompile(Tuple{typeof(Base.show), Base.IOContext{Base.GenericIOBuffer{Array{UInt8, 1}}}, Int32})
2525
precompile(Tuple{typeof(Base.print), Base.GenericIOBuffer{Array{UInt8, 1}}, Base.Libc.RawFD})
@@ -105,7 +105,7 @@ precompile(Tuple{typeof(Core.Inference.start), Core.Inference.Generator{Tuple{Tu
105105
precompile(Tuple{typeof(Core.Inference.done), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Int64})
106106
precompile(Tuple{typeof(Core.Inference.next), Core.Inference.Generator{Tuple{Tuple{Base.DevNullStream, Base.DevNullStream, Base.DevNullStream}}, Type{QuoteNode}}, Int64})
107107
precompile(Tuple{typeof(Core.Inference.isbits), Base.DevNullStream})
108-
precompile(Tuple{typeof(Base.finalizer), Base.Process, typeof(Base.uvfinalize)})
108+
precompile(Tuple{typeof(Base.finalizer), typeof(Base.uvfinalize), Base.Process})
109109
precompile(Tuple{typeof(Core.Inference.isbits), Tuple{Base.DevNullStream, Bool}})
110110
precompile(Tuple{Type{Ref{Base.Cstring}}, Array{String, 1}})
111111
precompile(Tuple{typeof(Core.Inference.eltype), Type{Array{String, 1}}})
@@ -1552,7 +1552,7 @@ precompile(Tuple{typeof(Base.rehash!), Base.Dict{WeakRef, Void}, Int64})
15521552
precompile(Tuple{typeof(Base.ht_keyindex2), Base.Dict{WeakRef, Void}, WeakRef})
15531553
precompile(Tuple{typeof(Base._setindex!), Base.Dict{WeakRef, Void}, Void, WeakRef, Int64})
15541554
precompile(Tuple{typeof(Base.setindex!), Base.Dict{WeakRef, Void}, Void, WeakRef})
1555-
precompile(Tuple{typeof(Base.finalizer), Base.Distributed.RemoteChannel{Base.Channel{Any}}, typeof(Base.Distributed.finalize_ref)})
1555+
precompile(Tuple{typeof(Base.finalizer), typeof(Base.Distributed.finalize_ref), Base.Distributed.RemoteChannel{Base.Channel{Any}}})
15561556
precompile(Tuple{typeof(Base.Distributed.test_existing_ref), Base.Distributed.RemoteChannel{Base.Channel{Any}}})
15571557
precompile(Tuple{Type{Base.Distributed.RemoteChannel{T} where T<:Base.AbstractChannel}, Int64})
15581558
precompile(Tuple{Type{Base.Channel{Int64}}, Int64})
@@ -1714,7 +1714,7 @@ precompile(Tuple{typeof(Base.Filesystem.mkdir), String, UInt16})
17141714
precompile(Tuple{typeof(Base.Filesystem.mkpath), String, UInt16})
17151715
precompile(Tuple{typeof(Base.Filesystem.samefile), String, String})
17161716
precompile(Tuple{typeof(Base.Filesystem.unlink), String})
1717-
precompile(Tuple{typeof(Base.finalizer), Base.Distributed.Future, typeof(Base.Distributed.finalize_ref)})
1717+
precompile(Tuple{typeof(Base.finalizer), typeof(Base.Distributed.finalize_ref), Base.Distributed.Future})
17181718
precompile(Tuple{typeof(Base.find_all_in_cache_path), Symbol})
17191719
precompile(Tuple{typeof(Base.find_package), String})
17201720
precompile(Tuple{typeof(Base.find_source_file), String})

base/process.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,7 @@ mutable struct Process <: AbstractPipe
328328
typemin(fieldtype(Process, :exitcode)),
329329
typemin(fieldtype(Process, :termsignal)),
330330
Condition(), Condition())
331-
finalizer(this, uvfinalize)
331+
finalizer(uvfinalize, this)
332332
return this
333333
end
334334
end

base/regex.jl

+4-4
Original file line numberDiff line numberDiff line change
@@ -29,10 +29,10 @@ mutable struct Regex
2929
end
3030
re = compile(new(pattern, compile_options, match_options, C_NULL,
3131
C_NULL, Csize_t[], C_NULL))
32-
finalizer(re, re->begin
33-
re.regex == C_NULL || PCRE.free_re(re.regex)
34-
re.match_data == C_NULL || PCRE.free_match_data(re.match_data)
35-
end)
32+
finalizer(re) do re
33+
re.regex == C_NULL || PCRE.free_re(re.regex)
34+
re.match_data == C_NULL || PCRE.free_match_data(re.match_data)
35+
end
3636
re
3737
end
3838
end

base/repl/REPL.jl

+3-1
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,9 @@ function setup_interface(
800800
try
801801
hist_path = find_hist_file()
802802
f = open(hist_path, true, true, true, false, false)
803-
finalizer(replc, replc->close(f))
803+
finalizer(replc) do replc
804+
close(f)
805+
end
804806
hist_from_file(hp, f, hist_path)
805807
catch e
806808
print_response(repl, e, catch_backtrace(), true, Base.have_color)

base/socket.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -278,7 +278,7 @@ mutable struct TCPSocket <: LibuvStream
278278
ReentrantLock(),
279279
DEFAULT_READ_BUFFER_SZ)
280280
associate_julia_struct(tcp.handle, tcp)
281-
finalizer(tcp, uvfinalize)
281+
finalizer(uvfinalize, tcp)
282282
return tcp
283283
end
284284
end
@@ -308,7 +308,7 @@ mutable struct TCPServer <: LibuvServer
308308
Condition(),
309309
Condition())
310310
associate_julia_struct(tcp.handle, tcp)
311-
finalizer(tcp, uvfinalize)
311+
finalizer(uvfinalize, tcp)
312312
return tcp
313313
end
314314
end
@@ -370,7 +370,7 @@ mutable struct UDPSocket <: LibuvStream
370370
Condition(),
371371
Condition())
372372
associate_julia_struct(udp.handle, udp)
373-
finalizer(udp, uvfinalize)
373+
finalizer(uvfinalize, udp)
374374
return udp
375375
end
376376
end

base/sparse/cholmod.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -204,7 +204,7 @@ mutable struct Dense{T<:VTypes} <: DenseMatrix{T}
204204
"unknown reasons. Please submit a bug report."))
205205
end
206206
A = new(p)
207-
finalizer(A, free!)
207+
finalizer(free!, A)
208208
return A
209209
end
210210
end
@@ -256,7 +256,7 @@ mutable struct Sparse{Tv<:VTypes} <: AbstractSparseMatrix{Tv,SuiteSparse_long}
256256
"unknown reasons. Please submit a bug report."))
257257
end
258258
A = new(p)
259-
finalizer(A, free!)
259+
finalizer(free!, A)
260260
return A
261261
end
262262
end
@@ -340,7 +340,7 @@ mutable struct Factor{Tv} <: Factorization{Tv}
340340
end
341341
F = new(p)
342342
if register_finalizer
343-
finalizer(F, free!)
343+
finalizer(free!, F)
344344
end
345345
return F
346346
end

base/sparse/umfpack.jl

+1-1
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ function lufact(S::SparseMatrixCSC{<:UMFVTypes,<:UMFITypes})
143143
zerobased ? copy(S.colptr) : decrement(S.colptr),
144144
zerobased ? copy(S.rowval) : decrement(S.rowval),
145145
copy(S.nzval))
146-
finalizer(res, umfpack_free_symbolic)
146+
finalizer(umfpack_free_symbolic, res)
147147
umfpack_numeric!(res)
148148
end
149149
lufact(A::SparseMatrixCSC{<:Union{Float16,Float32},Ti}) where {Ti<:UMFITypes} =

base/stream.jl

+3-3
Original file line numberDiff line numberDiff line change
@@ -120,7 +120,7 @@ mutable struct PipeEndpoint <: LibuvStream
120120
ReentrantLock(),
121121
DEFAULT_READ_BUFFER_SZ)
122122
associate_julia_struct(handle, p)
123-
finalizer(p, uvfinalize)
123+
finalizer(uvfinalize, p)
124124
return p
125125
end
126126
end
@@ -136,7 +136,7 @@ mutable struct PipeServer <: LibuvServer
136136
Condition(),
137137
Condition())
138138
associate_julia_struct(p.handle, p)
139-
finalizer(p, uvfinalize)
139+
finalizer(uvfinalize, p)
140140
return p
141141
end
142142
end
@@ -169,7 +169,7 @@ mutable struct TTY <: LibuvStream
169169
nothing, ReentrantLock(),
170170
DEFAULT_READ_BUFFER_SZ)
171171
associate_julia_struct(handle, tty)
172-
finalizer(tty, uvfinalize)
172+
finalizer(uvfinalize, tty)
173173
@static if Sys.iswindows()
174174
tty.ispty = ccall(:jl_ispty, Cint, (Ptr{Void},), handle) != 0
175175
end

0 commit comments

Comments
 (0)