Skip to content

Commit

Permalink
new deprecate_moved macro, better support for replacing deprecated bi…
Browse files Browse the repository at this point in the history
…ndings (#22763)

new deprecate_moved macro, and better support for replacing deprecated bindings without warnings
  • Loading branch information
stevengj authored and JeffBezanson committed Jul 15, 2017
1 parent b0b0cbc commit 35ec98d
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 49 deletions.
65 changes: 20 additions & 45 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ function firstcaller(bt::Array{Ptr{Void},1}, funcsyms)
return lkup
end

deprecate(m::Module, s::Symbol) = ccall(:jl_deprecate_binding, Void, (Any, Any), m, s)
deprecate(m::Module, s::Symbol, flag=1) = ccall(:jl_deprecate_binding, Void, (Any, Any, Cint), m, s, flag)

macro deprecate_binding(old, new, export_old=true)
return Expr(:toplevel,
Expand All @@ -112,6 +112,18 @@ macro deprecate_binding(old, new, export_old=true)
Expr(:call, :deprecate, __module__, Expr(:quote, old)))
end

macro deprecate_moved(old, new, export_old=true)
eold = esc(old)
return Expr(:toplevel,
:(function $eold(args...; kwargs...)
error($eold, " 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.")
end),
export_old ? Expr(:export, eold) : nothing,
Expr(:call, :deprecate, __module__, Expr(:quote, old), 2))
end

# BEGIN 0.6-alpha deprecations (delete when 0.6 is released)

@deprecate isambiguous(m1::Method, m2::Method, b::Bool) isambiguous(m1, m2, ambiguous_bottom=b) false
Expand Down Expand Up @@ -684,21 +696,12 @@ end
@deprecate xor(A::AbstractArray, B::AbstractArray) xor.(A, B)

# QuadGK moved to a package (#19741)
function quadgk(args...; kwargs...)
error(string(quadgk, args, " has been moved to the package QuadGK.jl.\n",
"Run Pkg.add(\"QuadGK\") to install QuadGK on Julia v0.6 and later, and then run `using QuadGK`."))
end
export quadgk
@deprecate_moved quadgk "QuadGK"

# Collections functions moved to a package (#19800)
module Collections
export PriorityQueue, enqueue!, dequeue!, heapify!, heapify, heappop!, heappush!, isheap, peek
for f in (:PriorityQueue, :enqueue!, :dequeue!, :heapify!, :heapify, :heappop!, :heappush!, :isheap, :peek)
@eval function ($f)(args...; kwargs...)
error(string($f, args, " has been moved to the package DataStructures.jl.\n",
"Run Pkg.add(\"DataStructures\") to install DataStructures on Julia v0.6 and later, ",
"and then run `using DataStructures`."))
end
@eval Base.@deprecate_moved $f "DataStructures"
end
end
export Collections
Expand Down Expand Up @@ -1288,14 +1291,7 @@ for f in (:airyai, :airyaiprime, :airybi, :airybiprime, :airyaix, :airyaiprimex,
:eta, :zeta, :digamma, :invdigamma, :polygamma, :trigamma,
:hankelh1, :hankelh1x, :hankelh2, :hankelh2x,
:airy, :airyx, :airyprime)
@eval begin
function $f(args...; kwargs...)
error(string($f, args, " has been moved to the package SpecialFunctions.jl.\n",
"Run Pkg.add(\"SpecialFunctions\") to install SpecialFunctions on Julia v0.6 and later,\n",
"and then run `using SpecialFunctions`."))
end
export $f
end
@eval @deprecate_moved $f "SpecialFunctions"
end

@deprecate_binding LinearIndexing IndexStyle false
Expand Down Expand Up @@ -1443,43 +1439,22 @@ module DFT
:plan_dct, :plan_dct!, :plan_fft, :plan_fft!, :plan_idct, :plan_idct!,
:plan_ifft, :plan_ifft!, :plan_irfft, :plan_rfft, :rfft]
pkg = endswith(String(f), "shift") ? "AbstractFFTs" : "FFTW"
@eval begin
function $f(args...; kwargs...)
error($f, " has been moved to the package $($pkg).jl.\n",
"Run `Pkg.add(\"$($pkg)\")` to install $($pkg) then run `using $($pkg)` ",
"to load it.")
end
export $f
end
@eval Base.@deprecate_moved $f $pkg
end
module FFTW
for f in [:r2r, :r2r!, :plan_r2r, :plan_r2r!]
@eval begin
function $f(args...; kwargs...)
error($f, " has been moved to the package FFTW.jl.\n",
"Run `Pkg.add(\"FFTW\")` to install FFTW then run `using FFTW` ",
"to load it.")
end
export $f
end
@eval Base.@deprecate_moved $f "FFTW"
end
end
export FFTW
end
using .DFT
for f in names(DFT)
for f in filter(s -> isexported(DFT, s), names(DFT, true))
@eval export $f
end
module DSP
for f in [:conv, :conv2, :deconv, :filt, :filt!, :xcorr]
@eval begin
function $f(args...; kwargs...)
error($f, " has been moved to the package DSP.jl.\n",
"Run `Pkg.add(\"DSP\")` to install DSP then run `using DSP` ",
"to load it.")
end
export $f
end
@eval Base.@deprecate_moved $f "DSP"
end
end
using .DSP
Expand Down
2 changes: 1 addition & 1 deletion src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -400,7 +400,7 @@ typedef struct {
uint8_t constp:1;
uint8_t exportp:1;
uint8_t imported:1;
uint8_t deprecated:1;
uint8_t deprecated:2; // 0=not deprecated, 1=renamed, 2=moved to another package
} jl_binding_t;

typedef struct _jl_module_t {
Expand Down
12 changes: 9 additions & 3 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,7 @@ static jl_binding_t *jl_get_binding_(jl_module_t *m, jl_sym_t *var, modstack_t *
// couldn't resolve; try next using (see issue #6105)
continue;
if (owner != NULL && tempb->owner != b->owner &&
!tempb->deprecated && !b->deprecated &&
!(tempb->constp && tempb->value && b->constp && b->value == tempb->value)) {
jl_printf(JL_STDERR,
"WARNING: both %s and %s export \"%s\"; uses of it in module %s must be qualified\n",
Expand Down Expand Up @@ -461,10 +462,12 @@ JL_DLLEXPORT int jl_is_const(jl_module_t *m, jl_sym_t *var)
return b && b->constp;
}

JL_DLLEXPORT void jl_deprecate_binding(jl_module_t *m, jl_sym_t *var)
// set the deprecated flag for a binding:
// 0=not deprecated, 1=renamed, 2=moved to another package
JL_DLLEXPORT void jl_deprecate_binding(jl_module_t *m, jl_sym_t *var, int flag)
{
jl_binding_t *b = jl_get_binding(m, var);
if (b) b->deprecated = 1;
if (b) b->deprecated = flag;
}

JL_DLLEXPORT int jl_is_binding_deprecated(jl_module_t *m, jl_sym_t *var)
Expand All @@ -478,7 +481,10 @@ extern int jl_lineno;

void jl_binding_deprecation_warning(jl_binding_t *b)
{
if (b->deprecated && jl_options.depwarn) {
// Only print a warning for deprecated == 1 (renamed).
// For deprecated == 2 (moved to a package) the binding is to a function
// that throws an error, so we don't want to print a warning too.
if (b->deprecated == 1 && jl_options.depwarn) {
if (jl_options.depwarn != JL_OPTIONS_DEPWARN_ERROR)
jl_printf(JL_STDERR, "WARNING: ");
if (b->owner)
Expand Down
12 changes: 12 additions & 0 deletions test/misc.jl
Original file line number Diff line number Diff line change
Expand Up @@ -769,10 +769,22 @@ module DeprecationTests # to test @deprecate
# test deprecation of a constructor
struct A{T} end
@deprecate A{T}(x::S) where {T, S} f()

# test that @deprecate_moved can be overridden by an import
Base.@deprecate_moved foo1234 "Foo"
Base.@deprecate_moved bar "Bar" false
end # module
module Foo1234
export foo1234
foo1234(x) = x+1
end

@testset "@deprecate" begin
using .DeprecationTests
using .Foo1234
@test foo1234(3) == 4
@test_throws ErrorException DeprecationTests.bar(3)

# enable when issue #22043 is fixed
# @test @test_warn "f1 is deprecated, use f instead." f1()
# @test @test_nowarn f1()
Expand Down

0 comments on commit 35ec98d

Please sign in to comment.