forked from JuliaLang/julia
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdeprecated.jl
272 lines (234 loc) · 10.3 KB
/
deprecated.jl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
# This file is a part of Julia. License is MIT: https://julialang.org/license
# Deprecated functions and objects
#
# Please add new deprecations at the bottom of the file.
# A function deprecated in a release will be removed in the next one.
# Please also add a reference to the pull request which introduced the
# deprecation. For simple cases where a direct replacement is available,
# use @deprecate. @deprecate takes care of calling the replacement
# and of exporting the function.
#
# For more complex cases, move the body of the deprecated method in this file,
# and call depwarn() directly from inside it. The symbol depwarn() expects is
# the name of the function, which is used to ensure that the deprecation warning
# is only printed the first time for each call place.
"""
@deprecate old new [ex=true]
Deprecate method `old` and specify the replacement call `new`. Prevent `@deprecate` from
exporting `old` by setting `ex` to `false`. `@deprecate` defines a new method with the same
signature as `old`.
!!! compat "Julia 1.5"
As of Julia 1.5, functions defined by `@deprecate` do not print warning when `julia`
is run without the `--depwarn=yes` flag set, as the default value of `--depwarn` option
is `no`. The warnings are printed from tests run by `Pkg.test()`.
# Examples
```jldoctest
julia> @deprecate old(x) new(x)
old (generic function with 1 method)
julia> @deprecate old(x) new(x) false
old (generic function with 1 method)
```
"""
macro deprecate(old, new, ex=true)
meta = Expr(:meta, :noinline)
if isa(old, Symbol)
oldname = Expr(:quote, old)
newname = Expr(:quote, new)
Expr(:toplevel,
ex ? Expr(:export, esc(old)) : nothing,
:(function $(esc(old))(args...)
$meta
depwarn($"`$old` is deprecated, use `$new` instead.", Core.Typeof($(esc(old))).name.mt.name)
$(esc(new))(args...)
end))
elseif isa(old, Expr) && (old.head === :call || old.head === :where)
remove_linenums!(new)
oldcall = sprint(show_unquoted, old)
newcall = sprint(show_unquoted, new)
# if old.head is a :where, step down one level to the :call to avoid code duplication below
callexpr = old.head === :call ? old : old.args[1]
if callexpr.head === :call
if isa(callexpr.args[1], Symbol)
oldsym = callexpr.args[1]::Symbol
elseif isa(callexpr.args[1], Expr) && callexpr.args[1].head === :curly
oldsym = callexpr.args[1].args[1]::Symbol
else
error("invalid usage of @deprecate")
end
else
error("invalid usage of @deprecate")
end
Expr(:toplevel,
ex ? Expr(:export, esc(oldsym)) : nothing,
:($(esc(old)) = begin
$meta
depwarn($"`$oldcall` is deprecated, use `$newcall` instead.", Core.Typeof($(esc(oldsym))).name.mt.name)
$(esc(new))
end))
else
error("invalid usage of @deprecate")
end
end
function depwarn(msg, funcsym; force::Bool=false)
opts = JLOptions()
if opts.depwarn == 2
throw(ErrorException(msg))
end
deplevel = force || opts.depwarn == 1 ? CoreLogging.Warn : CoreLogging.BelowMinLevel
@logmsg(
deplevel,
msg,
_module=begin
bt = backtrace()
frame, caller = firstcaller(bt, funcsym)
# TODO: Is it reasonable to attribute callers without linfo to Core?
caller.linfo isa Core.MethodInstance ? caller.linfo.def.module : Core
end,
_file=String(caller.file),
_line=caller.line,
_id=(frame,funcsym),
_group=:depwarn,
caller=caller,
maxlog=funcsym === nothing ? nothing : 1
)
nothing
end
firstcaller(bt::Vector, ::Nothing) = Ptr{Cvoid}(0), StackTraces.UNKNOWN
firstcaller(bt::Vector, funcsym::Symbol) = firstcaller(bt, (funcsym,))
function firstcaller(bt::Vector, funcsyms)
# Identify the calling line
found = false
for ip in bt
lkups = StackTraces.lookup(ip)
for lkup in lkups
if lkup == StackTraces.UNKNOWN || lkup.from_c
continue
end
if found
return ip, lkup
end
found = lkup.func in funcsyms
# look for constructor type name
if !found
li = lkup.linfo
if li isa Core.MethodInstance
ft = ccall(:jl_first_argument_datatype, Any, (Any,), (li.def::Method).sig)
if isa(ft, DataType) && ft.name === Type.body.name
ft = unwrap_unionall(ft.parameters[1])
found = (isa(ft, DataType) && ft.name.name in funcsyms)
end
end
end
end
end
return C_NULL, StackTraces.UNKNOWN
end
deprecate(m::Module, s::Symbol, flag=1) = ccall(:jl_deprecate_binding, Cvoid, (Any, Any, Cint), m, s, flag)
macro deprecate_binding(old, new, export_old=true, dep_message=:nothing, constant=true)
dep_message === :nothing && (dep_message = ", use $new instead.")
return Expr(:toplevel,
export_old ? Expr(:export, esc(old)) : nothing,
Expr(:const, Expr(:(=), esc(Symbol(string("_dep_message_",old))), esc(dep_message))),
constant ? Expr(:const, Expr(:(=), esc(old), esc(new))) : Expr(:(=), esc(old), esc(new)),
Expr(:call, :deprecate, __module__, Expr(:quote, old)))
end
macro deprecate_stdlib(old, mod, export_old=true, newname=old)
rename = old === newname ? "" : " as `$newname`"
dep_message = """: it has been moved to the standard library package `$mod`$rename.
Add `using $mod` to your imports."""
new = GlobalRef(Base.root_module(Base, mod), newname)
return Expr(:toplevel,
export_old ? Expr(:export, esc(old)) : nothing,
Expr(:const, Expr(:(=), esc(Symbol(string("_dep_message_",old))), esc(dep_message))),
Expr(:const, Expr(:(=), esc(old), esc(new))),
Expr(:call, :deprecate, __module__, Expr(:quote, old)))
end
macro deprecate_moved(old, new, export_old=true)
eold = esc(old)
emsg = string(old, " has been moved to the package ", new, ".jl.\n",
"Run `Pkg.add(\"", new, "\")` to install it, restart Julia,\n",
"and then run `using ", new, "` to load it.")
return Expr(:toplevel,
:($eold(args...; kwargs...) = error($emsg)),
export_old ? Expr(:export, eold) : nothing,
Expr(:call, :deprecate, __module__, Expr(:quote, old), 2))
end
# BEGIN 1.0 deprecations
@deprecate one(i::CartesianIndex) oneunit(i)
@deprecate one(I::Type{CartesianIndex{N}}) where {N} oneunit(I)
@deprecate BigFloat(x, prec::Int) BigFloat(x; precision=prec)
@deprecate BigFloat(x, prec::Int, rounding::RoundingMode) BigFloat(x, rounding; precision=prec)
@deprecate BigFloat(x::Real, prec::Int) BigFloat(x; precision=prec)
@deprecate BigFloat(x::Real, prec::Int, rounding::RoundingMode) BigFloat(x, rounding; precision=prec)
# END 1.0 deprecations
# BEGIN 1.5 deprecations
"""
isimmutable(v) -> Bool
!!! warning
Consider using `!ismutable(v)` instead, as `isimmutable(v)` will be replaced by `!ismutable(v)` in a future release. (Since Julia 1.5)
Return `true` iff value `v` is immutable. See [Mutable Composite Types](@ref)
for a discussion of immutability. Note that this function works on values, so if you give it
a type, it will tell you that a value of `DataType` is mutable.
# Examples
```jldoctest
julia> isimmutable(1)
true
julia> isimmutable([1,2])
false
```
"""
isimmutable(@nospecialize(x)) = !ismutable(x)
export isimmutable
# Note isimmutable is not @deprecated out of performance concerns
macro get!(h, key0, default)
f, l = __source__.file, __source__.line
@warn "`@get!(dict, key, default)` at $f:$l is deprecated, use `get!(()->default, dict, key)` instead."
return quote
get!(()->$(esc(default)), $(esc(h)), $(esc(key0)))
end
end
pointer(V::SubArray{<:Any,<:Any,<:Array,<:Tuple{Vararg{RangeIndex}}}, is::Tuple) = pointer(V, CartesianIndex(is))
# END 1.5 deprecations
# BEGIN 1.6 deprecations
# These changed from SimpleVector to `MethodMatch`. These definitions emulate
# being a SimpleVector to ease transition for packages that make explicit
# use of (internal) APIs that return raw method matches.
iterate(match::Core.MethodMatch, field::Int=1) =
field > nfields(match) ? nothing : (getfield(match, field), field+1)
getindex(match::Core.MethodMatch, field::Int) =
getfield(match, field)
# these were internal functions, but some packages seem to be relying on them
tuple_type_head(T::Type) = fieldtype(T, 1)
tuple_type_cons(::Type, ::Type{Union{}}) = Union{}
function tuple_type_cons(::Type{S}, ::Type{T}) where T<:Tuple where S
@_pure_meta
Tuple{S, T.parameters...}
end
function parameter_upper_bound(t::UnionAll, idx)
@_pure_meta
return rewrap_unionall((unwrap_unionall(t)::DataType).parameters[idx], t)
end
# these were internal functions, but some packages seem to be relying on them
@deprecate cat_shape(dims, shape::Tuple{}, shapes::Tuple...) cat_shape(dims, shapes) false
cat_shape(dims, shape::Tuple{}) = () # make sure `cat_shape(dims, ())` do not recursively calls itself
@deprecate unsafe_indices(A) axes(A) false
@deprecate unsafe_length(r) length(r) false
# these were internal type aliases, but some pacakges seem to be relying on them
const Any16{N} = Tuple{Any,Any,Any,Any,Any,Any,Any,Any,
Any,Any,Any,Any,Any,Any,Any,Any,Vararg{Any,N}}
const All16{T,N} = Tuple{T,T,T,T,T,T,T,T,
T,T,T,T,T,T,T,T,Vararg{T,N}}
# END 1.6 deprecations
# BEGIN 1.7 deprecations
# the plan is to eventually overload getproperty to access entries of the dict
@noinline function getproperty(x::Pairs, s::Symbol)
depwarn("use values(kwargs) and keys(kwargs) instead of kwargs.data and kwargs.itr", :getproperty, force=true)
return getfield(x, s)
end
# This function was marked as experimental and not exported.
@deprecate catch_stack(task=current_task(); include_bt=true) current_exceptions(task; backtrace=include_bt) false
# END 1.7 deprecations
# BEGIN 1.8 deprecations
@deprecate var"@_inline_meta" var"@inline" false
@deprecate var"@_noinline_meta" var"@noinline" false
# END 1.8 deprecations