Skip to content

Commit

Permalink
Weed out relicts from at-compat (#626)
Browse files Browse the repository at this point in the history
* Remove at-compat for type aliases

  Was added in #326, now obsolete as no longer required on minimum
  supported Julia version 0.6.

* Remove at-compat for Nullable construction

  Was added in #287, now obsolete as no longer required on minimum 
  supported Julia version 0.6.

* Remove at-compat for Foo{<:Bar} sugar

  Was added in #317 (and #336), now obsolete as no longer required on 
  minimum supported Julia version 0.6.

* Remove at-compat for index styles

  Was added in #329, now obsolete as no longer required on minimum 
  supported Julia version 0.6.

* Remove at-compat for type declarations

  Was added in #325, now obsolete as no longer required on minimum 
  supported Julia version 0.6.

* Remove unused at-compat helper functions

* Remove README entries for removed at-compat functionality

  * new style call overloading (added in #181, removed in #385)
  * `get(io, s false)` (added in #212, #215, #225, removed in #385)
  * `.=` (added in #292 and #316, removed in #372)

* Remove `Compat.collect(A)`

  Was added in #350 and #351, now obsolete as no longer required on 
  minimum supported Julia version 0.6.
  • Loading branch information
martinholters authored Aug 31, 2018
1 parent 0fef5d3 commit 96e41ae
Show file tree
Hide file tree
Showing 4 changed files with 6 additions and 269 deletions.
34 changes: 1 addition & 33 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -49,37 +49,11 @@ Please check the list below for the specific syntax you need.

Currently, the `@compat` macro supports the following syntaxes:

* `@compat (a::B{T}){T}(c) = d` — the Julia 0.5-style call overload

* `@compat(get(io, s, false))`, with `s` equal to `:limit`, `:compact` or `:multiline`, to detect the corresponding print settings (performs useful work only on Julia 0.5, defaults to `false` otherwise)

* `@compat Nullable(value, hasvalue)` to handle the switch from the `Nullable` `:isnull` field to `:hasvalue` field ([#18510])

* `@compat x .= y` converts to an in-place assignment to `x` (via `broadcast!`) ([#17510]).
However, beware that `.=` in Julia 0.4 has the precedence of `==`, not of assignment `=`, so if the right-hand-side `y`
includes expressions with lower precedence than `==` you should enclose it in parentheses `x .= (y)` to ensure the
correct order of evaluation. Also, `x .+= y` converts to `x .= (x .+ y)`, and similarly for the other updating
assignment operators (`.*=` and so on).

* `@compat Array{<:Real}`, `@compat Array{>:Int}`, and similar uses of `<:T` (resp. `>:T`) to define a set of "covariant" (resp. "contravariant") parameterized types ([#20414]).
In 0.5, this only works for non-nested usages (e.g. you can't define `Array{<:Array{<:Real}}`).

* `@compat abstract type T end` and `@compat primitive type T 8 end`
to declare abstract and primitive types. [#20418]
This only works when `@compat` is applied directly on the declaration.

* `@compat A{T} = B{T}` or `@compat const A{T} = B{T}` to declare type alias with free
parameters. [#20500]. Use `const A = B{T}` or `const A = B` for type alias without free parameters (i.e. no type parameter on the left hand side).

* `@compat Base.IndexStyle(::Type{<:MyArray}) = IndexLinear()` and `@compat Base.IndexStyle(::Type{<:MyArray}) = IndexCartesian()` to define traits for abstract arrays, replacing the former `Base.linearindexing{T<:MyArray}(::Type{T}) = Base.LinearFast()` and `Base.linearindexing{T<:MyArray}(::Type{T}) = Base.LinearSlow()`, respectively.

* `Compat.collect(A)` returns an `Array`, no matter what indices the array `A` has. [#21257]

* `@compat foo(::CartesianRange{N})` to replace the former
`foo(::CartesianRange{CartesianIndex{N}})` ([#20974]). Note that
`CartesianRange` now has two type parameters, so using them as
fields in other `struct`s requires manual intervention.

* Required keyword arguments ([#25830]). For example, `@compat foo(; x, y)` makes `x` and `y` required keyword arguments: when calling `foo`, an error is thrown if `x` or `y` is not explicitly provided.

## Module Aliases
Expand Down Expand Up @@ -527,12 +501,10 @@ includes this fix. Find the minimum version from there.
[#16986]: https://github.com/JuliaLang/julia/issues/16986
[#17302]: https://github.com/JuliaLang/julia/issues/17302
[#17323]: https://github.com/JuliaLang/julia/issues/17323
[#17510]: https://github.com/JuliaLang/julia/issues/17510
[#17623]: https://github.com/JuliaLang/julia/issues/17623
[#18082]: https://github.com/JuliaLang/julia/issues/18082
[#18380]: https://github.com/JuliaLang/julia/issues/18380
[#18484]: https://github.com/JuliaLang/julia/issues/18484
[#18510]: https://github.com/JuliaLang/julia/issues/18510
[#18629]: https://github.com/JuliaLang/julia/issues/18629
[#18727]: https://github.com/JuliaLang/julia/issues/18727
[#18977]: https://github.com/JuliaLang/julia/issues/18977
Expand All @@ -548,12 +520,8 @@ includes this fix. Find the minimum version from there.
[#20164]: https://github.com/JuliaLang/julia/issues/20164
[#20321]: https://github.com/JuliaLang/julia/issues/20321
[#20407]: https://github.com/JuliaLang/julia/issues/20407
[#20414]: https://github.com/JuliaLang/julia/issues/20414
[#20418]: https://github.com/JuliaLang/julia/issues/20418
[#20500]: https://github.com/JuliaLang/julia/issues/20500
[#20974]: https://github.com/JuliaLang/julia/issues/20974
[#21197]: https://github.com/JuliaLang/julia/issues/21197
[#21257]: https://github.com/JuliaLang/julia/issues/21257
[#21346]: https://github.com/JuliaLang/julia/issues/21346
[#21709]: https://github.com/JuliaLang/julia/issues/21709
[#22064]: https://github.com/JuliaLang/julia/issues/22064
Expand Down
30 changes: 0 additions & 30 deletions src/Compat.jl
Original file line number Diff line number Diff line change
Expand Up @@ -169,13 +169,6 @@ end
Base.Broadcast.broadcast{N}(f, t::NTuple{N}, ts::Vararg{NTuple{N}}) = map(f, t, ts...)
end

# julia#18510
if VERSION < v"0.6.0-dev.826"
_Nullable_field2(x) = !x
else
_Nullable_field2(x) = x
end

# julia#18484
@static if VERSION < v"0.6.0-dev.848"
unsafe_get(x::Nullable) = x.value
Expand Down Expand Up @@ -257,15 +250,6 @@ include("arraymacros.jl")
# julia #18839
import Base.Iterators # TODO deprecate, remove

@static if VERSION < v"0.6.0-dev.2840"
export IndexStyle, IndexLinear, IndexCartesian
eval(Expr(:typealias, :IndexStyle, :(Base.LinearIndexing)))
eval(Expr(:typealias, :IndexLinear, :(Base.LinearFast)))
eval(Expr(:typealias, :IndexCartesian, :(Base.LinearSlow)))
IndexStyle{T}(::Type{T}) = Base.linearindexing(T)
IndexStyle(args...) = Base.linearindexing(args...)
end

if VERSION < v"0.6.0-dev.1653"
for (fname, felt) in ((:zeros,:zero), (:ones,:one))
@eval begin
Expand Down Expand Up @@ -342,20 +326,6 @@ else
end
end

# https://github.com/JuliaLang/julia/pull/21257
@static if VERSION < v"0.6.0-pre.beta.28"
collect(A) = collect_indices(indices(A), A)
collect_indices(::Tuple{}, A) = copy!(Array{eltype(A)}(), A)
collect_indices(indsA::Tuple{Vararg{Base.OneTo}}, A) =
copy!(Array{eltype(A)}(map(length, indsA)), A)
function collect_indices(indsA, A)
B = Array{eltype(A)}(map(length, indsA))
copy!(B, CartesianRange(indices(B)), A, CartesianRange(indsA))
end
else
const collect = Base.collect
end

# https://github.com/JuliaLang/julia/pull/21197
if VERSION < v"0.7.0-DEV.257"
# allow the elements of the Cmd to be accessed as an array or iterator
Expand Down
100 changes: 2 additions & 98 deletions src/compatmacro.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,6 @@
using Base.Meta
export @compat

"""Get just the function part of a function declaration."""
withincurly(ex) = isexpr(ex, :curly) ? ex.args[1] : ex

is_index_style(ex::Expr) = ex == :(Compat.IndexStyle) || ex == :(Base.IndexStyle) ||
(ex.head == :(.) && (ex.args[1] == :Compat || ex.args[1] == :Base) &&
ex.args[2] == Expr(:quote, :IndexStyle))

is_index_style(arg) = false

istopsymbol(ex, mod, sym) = ex in (sym, Expr(:(.), mod, Expr(:quote, sym)))

if VERSION < v"0.6.0-dev.2782"
function new_style_typealias(ex::ANY)
isexpr(ex, :(=)) || return false
ex = ex::Expr
return length(ex.args) == 2 && isexpr(ex.args[1], :curly)
end
else
new_style_typealias(ex) = false
end

if !isdefined(Base, :UndefKeywordError)
struct UndefKeywordError <: Exception
kw
Expand All @@ -42,43 +21,13 @@ symbol2kw(arg) = arg
function _compat(ex::Expr)
if ex.head === :call
f = ex.args[1]
if VERSION < v"0.6.0-dev.826" && length(ex.args) == 3 && # julia#18510
istopsymbol(withincurly(ex.args[1]), :Base, :Nullable)
ex = Expr(:call, f, ex.args[2], Expr(:call, :(Compat._Nullable_field2), ex.args[3]))
end
if !isdefined(Base, :UndefKeywordError) && length(ex.args) > 1 && isexpr(ex.args[2], :parameters)
params = ex.args[2]
params.args = map(symbol2kw, params.args)
end
elseif ex.head === :curly
f = ex.args[1]
if VERSION < v"0.6.0-dev.2575" #20414
ex = Expr(:curly, map(a -> isexpr(a, :call, 2) && a.args[1] == :(<:) ?
:($TypeVar($(QuoteNode(gensym(:T))), $(a.args[2]), false)) :
isexpr(a, :call, 2) && a.args[1] == :(>:) ?
:($TypeVar($(QuoteNode(gensym(:T))), $(a.args[2]), $Any, false)) : a,
ex.args)...)
end
elseif ex.head === :quote && isa(ex.args[1], Symbol)
# Passthrough
return ex
elseif new_style_typealias(ex)
ex.head = :typealias
elseif ex.head === :const && length(ex.args) == 1 && new_style_typealias(ex.args[1])
ex = ex.args[1]::Expr
ex.head = :typealias
end
if VERSION < v"0.6.0-dev.2840"
if ex.head == :(=) && isa(ex.args[1], Expr) && ex.args[1].head == :call
a = ex.args[1].args[1]
if is_index_style(a)
ex.args[1].args[1] = :(Base.linearindexing)
elseif isa(a, Expr) && a.head == :curly
if is_index_style(a.args[1])
ex.args[1].args[1].args[1] = :(Base.linearindexing)
end
end
end
end
if VERSION < v"0.7.0-DEV.880"
if ex.head == :curly && ex.args[1] == :CartesianRange && length(ex.args) >= 2
Expand All @@ -98,51 +47,6 @@ end

_compat(ex) = ex

function _get_typebody(ex::Expr)
args = ex.args
if ex.head !== :type || length(args) != 3 || args[1] !== true
throw(ArgumentError("Invalid usage of @compat: $ex"))
end
name = args[2]
if !isexpr(args[3], :block)
throw(ArgumentError("Invalid type declaration: $ex"))
end
body = (args[3]::Expr).args
filter!(body) do e
if isa(e, LineNumberNode) || isexpr(e, :line)
return false
end
return true
end
return name, body
end

function _compat_primitive(typedecl)
name, body = _get_typebody(typedecl)
if length(body) != 1
throw(ArgumentError("Invalid primitive type declaration: $typedecl"))
end
return Expr(:bitstype, body[1], name)
end

function _compat_abstract(typedecl)
name, body = _get_typebody(typedecl)
if length(body) != 0
throw(ArgumentError("Invalid abstract type declaration: $typedecl"))
end
return Expr(:abstract, name)
end

macro compat(ex...)
if VERSION < v"0.6.0-dev.2746" && length(ex) == 2 && ex[1] === :primitive
return esc(_compat_primitive(ex[2]))
elseif length(ex) != 1
throw(ArgumentError("@compat called with wrong number of arguments: $ex"))
elseif (VERSION < v"0.6.0-dev.2746" && isexpr(ex[1], :abstract) &&
length(ex[1].args) == 1 && isexpr(ex[1].args[1], :type))
# This can in principle be handled in nested case but we do not
# do that to be consistent with primitive types.
return esc(_compat_abstract(ex[1].args[1]))
end
esc(_compat(ex[1]))
macro compat(ex)
esc(_compat(ex))
end
111 changes: 3 additions & 108 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -192,61 +192,19 @@ if VERSION < v"0.7.0-DEV.3017"
UInt8,
]
for T in types
# julia#18510, Nullable constructors
x = @compat Nullable(one(T), true)
@test isnull(x) === false
@test isa(x.value, T)
@test eltype(x) === T

x = @compat Nullable{T}(one(T), true)
y = @compat Nullable{Any}(one(T), true)
@test isnull(x) === false
@test isnull(y) === false
@test isa(x.value, T)
@test eltype(x) === T
@test eltype(y) === Any

x = @compat Nullable{T}(one(T), false)
y = @compat Nullable{Any}(one(T), false)
@test isnull(x) === true
@test isnull(y) === true
@test eltype(x) === T
@test eltype(y) === Any

x = @compat Nullable(one(T), false)
@test isnull(x) === true
@test eltype(x) === T

x = @compat Nullable{T}()
@test isnull(x) === true
@test eltype(x) === T

# julia#18484, generic isnull, unsafe_get
a = one(T)
x = @compat Nullable(a, true)
x = Nullable(a, true)
@test isequal(unsafe_get(x), a)

x = @compat Nullable{Array{T}}()
x = Nullable{Array{T}}()
@test_throws UndefRefError unsafe_get(x)
end
end

@test xor(1,5) == 4
@test 1 5 == 4

# julia#20414
@compat let T = Array{<:Real}, f(x::AbstractVector{<:Real}) = 1
@test isa([3,4],T)
@test !isa([3,4im],T)
@test f(1:3) == f([1,2]) == 1
end
@compat let T = Array{>:Integer}, f(x::AbstractVector{>:Integer}) = 1
@test isa(Integer[1,2],T)
@test !isa([3,4],T)
@test !isa([3.0,4.0],T)
@test f(Integer[1,2]) == f([1,'a',:sym]) == 1
end

# supertype operator
@test !(Int >: Integer)
@test Integer >: Int
Expand All @@ -263,16 +221,6 @@ let io = IOBuffer()
@test String(take!(io)) == "bbb"
end

# julia#17510
let x = [1,2,3]
@compat x .= [3,4,5]
@test x == [3,4,5]
@compat x .= x .== 4
@test x == [0,1,0]
@compat x .= 7
@test x == [7,7,7]
end

let s = "Koala test: 🐨"
@test transcode(UInt16, s) == UInt16[75,111,97,108,97,32,116,101,115,116,58,32,55357,56360]
@test transcode(UInt32, s) == UInt32[75,111,97,108,97,32,116,101,115,116,58,32,128040]
Expand Down Expand Up @@ -326,7 +274,7 @@ for x in (3.1, -17, 3//4, big(111.1), Inf)
end

# julia#20006
@compat abstract type AbstractFoo20006 end
abstract type AbstractFoo20006 end
eval(Expr(
struct_sym, false,
Expr(:(<:), :(ConcreteFoo20006{T<:Int}), :AbstractFoo20006),
Expand Down Expand Up @@ -468,47 +416,6 @@ let x = [1,2,3]
@test f(x) == [1,4,9]
end

# PR #20418
@compat abstract type Abstract20418{T} <: Ref{T} end
@test Compat.TypeUtils.isabstract(Abstract20418)
@compat primitive type Primitive20418{T} <: Ref{T} 16 end
@test !Compat.TypeUtils.isabstract(Primitive20418)
@test isbitstype(Primitive20418{Int})
@test sizeof(Primitive20418{Int}) == 2

# PR #20500
@compat A20500{T<:Integer} = Array{T,20500}
@compat const A20500_2{T<:Union{Int,Float32}} = Pair{T,T}
f20500() = A20500
f20500_2() = A20500_2
@inferred f20500()
@inferred f20500_2()

module CompatArray
using Compat
const struct_sym = VERSION < v"0.7.0-DEV.1263" ? :type : :struct
eval(Expr(
struct_sym, false,
Expr(:(<:), :(CartesianArray{T,N}), :(AbstractArray{T,N})),
quote
parent::Array{T,N}
end))
eval(Expr(
struct_sym, false,
Expr(:(<:), :(LinearArray{T,N}), :(AbstractArray{T,N})),
quote
parent::Array{T,N}
end))
@compat Base.IndexStyle(::Type{<:LinearArray}) = IndexLinear()
end
@test IndexStyle(Array{Float32,2}) === IndexLinear()
@test IndexStyle(CompatArray.CartesianArray{Float32,2}) === IndexCartesian()
@test IndexStyle(CompatArray.LinearArray{Float32,2}) === IndexLinear()
let a = CompatArray.CartesianArray(rand(2,3)), b = CompatArray.LinearArray(rand(2,3))
@test IndexStyle(a) === IndexCartesian()
@test IndexStyle(b) === IndexLinear()
end

if VERSION < v"0.6.0-dev.1653"
for (A,val) in ((zeros(1:5, Float32, 3, 2), 0),
(ones(1:5, Float32, 3, 2), 1),
Expand Down Expand Up @@ -601,18 +508,6 @@ using Compat: StringVector
@test length(StringVector(5)) == 5
@test String(fill!(StringVector(5), 0x61)) == "aaaaa"

# collect
if VERSION < v"0.7.0-"
# Note: This is disabled on 0.7, since the Compat.collect functionality is only
# applicable on 0.5, and OffsetArrays currently has some incompatibilities with
# 0.7. This can be reenabled later if needed.
using OffsetArrays
a = OffsetArray(1:3, -1:1)
b = Compat.collect(a)
@test indices(b) === (Base.OneTo(3),)
@test b == [1,2,3]
end

# PR 22064
module Test22064
using Compat
Expand Down

0 comments on commit 96e41ae

Please sign in to comment.