Skip to content

Commit

Permalink
deprecate issubtype in favor of <:
Browse files Browse the repository at this point in the history
change printing of TypeErrors to avoid printing `<::`
  • Loading branch information
JeffBezanson committed Jul 28, 2017
1 parent 0f2a014 commit 8df2070
Show file tree
Hide file tree
Showing 20 changed files with 58 additions and 64 deletions.
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,8 @@ Deprecated or removed
* The function `showall` is deprecated. Showing entire values is the default, unless an
`IOContext` specifying `:limit=>true` is in use ([#22847]).

* `issubtype` has been deprecated in favor of `<:` (which used to be an alias for `issubtype`).

* Calling `write` on non-isbits arrays is deprecated in favor of explicit loops or
`serialize` ([#6466]).

Expand Down
2 changes: 1 addition & 1 deletion base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ export
fieldtype, getfield, setfield!, nfields, throw, tuple, ===, isdefined, eval,
# sizeof # not exported, to avoid conflicting with Base.sizeof
# type reflection
issubtype, typeof, isa, typeassert,
<:, typeof, isa, typeassert,
# method reflection
applicable, invoke,
# constants
Expand Down
2 changes: 2 additions & 0 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1338,6 +1338,8 @@ end

# BEGIN 0.7 deprecations

@deprecate issubtype (<:)

# 12807
start(::Union{Process, ProcessChain}) = 1
done(::Union{Process, ProcessChain}, i::Int) = (i == 3)
Expand Down
17 changes: 0 additions & 17 deletions base/docs/helpdb/Base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1546,23 +1546,6 @@ by `show` generally includes Julia-specific formatting and type information.
"""
show(x)

"""
issubtype(type1, type2)
Return `true` if and only if all values of `type1` are also of `type2`. Can also be written
using the `<:` infix operator as `type1 <: type2`.
# Examples
```jldoctest
julia> issubtype(Int8, Int32)
false
julia> Int8 <: Integer
true
```
"""
issubtype(type1, type2)

"""
finalizer(x, f)
Expand Down
14 changes: 7 additions & 7 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -732,13 +732,13 @@ add_tfunc(isa, 2, 2,
# TODO: handle non-leaftype(t) by testing against lower and upper bounds
return Bool
end, 0)
add_tfunc(issubtype, 2, 2,
add_tfunc(<:, 2, 2,
function (@nospecialize(a), @nospecialize(b))
if (isa(a,Const) || isType(a)) && (isa(b,Const) || isType(b))
a = instanceof_tfunc(a)
b = instanceof_tfunc(b)
if !has_free_typevars(a) && !has_free_typevars(b)
return Const(issubtype(a, b))
return Const(a <: b)
end
end
return Bool
Expand Down Expand Up @@ -2218,10 +2218,10 @@ function abstract_call(@nospecialize(f), fargs::Union{Tuple{},Vector{Any}}, argt
end
return rty
elseif length(fargs) == 3 && istopfunction(tm, f, :(>:))
# swap T1 and T2 arguments and call issubtype
fargs = Any[issubtype, fargs[3], fargs[2]]
argtypes = Any[typeof(issubtype), argtypes[3], argtypes[2]]
rty = abstract_call(issubtype, fargs, argtypes, vtypes, sv)
# swap T1 and T2 arguments and call <:
fargs = Any[<:, fargs[3], fargs[2]]
argtypes = Any[typeof(<:), argtypes[3], argtypes[2]]
rty = abstract_call(<:, fargs, argtypes, vtypes, sv)
return rty
end

Expand Down Expand Up @@ -4204,7 +4204,7 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
issubtype_stmts = Any[ Expr(:(=), issubtype_vnew, arg_T1) ]
arg_T1 = issubtype_vnew
end
issubtype_expr = Expr(:call, GlobalRef(Core, :issubtype), arg_T2, arg_T1)
issubtype_expr = Expr(:call, GlobalRef(Core, :(<:)), arg_T2, arg_T1)
issubtype_expr.typ = Bool
return (issubtype_expr, issubtype_stmts)
end
Expand Down
10 changes: 5 additions & 5 deletions base/int.jl
Original file line number Diff line number Diff line change
Expand Up @@ -431,8 +431,8 @@ end
for to in BitInteger_types, from in (BitInteger_types..., Bool)
if !(to === from)
if to.size < from.size
if issubtype(to, Signed)
if issubtype(from, Unsigned)
if to <: Signed
if from <: Unsigned
@eval convert(::Type{$to}, x::($from)) =
checked_trunc_sint($to, check_top_bit(x))
else
Expand All @@ -449,8 +449,8 @@ for to in BitInteger_types, from in (BitInteger_types..., Bool)
@eval convert(::Type{$to}, x::($from)) = zext_int($to, x) & $to(1)
@eval rem(x::($from), ::Type{$to}) = convert($to, x)
elseif from.size < to.size
if issubtype(from, Signed)
if issubtype(to, Unsigned)
if from <: Signed
if to <: Unsigned
@eval convert(::Type{$to}, x::($from)) =
sext_int($to, check_top_bit(x))
else
Expand All @@ -463,7 +463,7 @@ for to in BitInteger_types, from in (BitInteger_types..., Bool)
@eval rem(x::($from), ::Type{$to}) = convert($to, x)
end
else
if !(issubtype(from, Signed) === issubtype(to, Signed))
if !((from <: Signed) === (to <: Signed))
# raise InexactError if x's top bit is set
@eval convert(::Type{$to}, x::($from)) = bitcast($to, check_top_bit(x))
else
Expand Down
9 changes: 5 additions & 4 deletions base/operators.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@
"""
<:(T1, T2)
Subtype operator, equivalent to `issubtype(T1, T2)`.
Subtype operator: returns `true` if and only if all values of type `T1` are
also of type `T2`.
```jldoctest
julia> Float64 <: AbstractFloat
Expand All @@ -18,14 +19,14 @@ julia> Matrix{Float64} <: Matrix{AbstractFloat}
false
```
"""
const (<:) = issubtype
(<:)

"""
>:(T1, T2)
Supertype operator, equivalent to `issubtype(T2, T1)`.
Supertype operator, equivalent to `T2 <: T1`.
"""
const (>:)(@nospecialize(a), @nospecialize(b)) = issubtype(b, a)
const (>:)(@nospecialize(a), @nospecialize(b)) = (b <: a)

"""
supertype(T::DataType)
Expand Down
2 changes: 1 addition & 1 deletion base/rational.jl
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ function round(::Type{T}, x::Rational{Tr}, ::RoundingMode{:NearestTiesUp}) where
end

function round(::Type{T}, x::Rational{Bool}) where T
if denominator(x) == false && issubtype(T, Union{Integer, Bool})
if denominator(x) == false && (T <: Union{Integer, Bool})
throw(DivideError())
end
convert(T, x)
Expand Down
8 changes: 6 additions & 2 deletions base/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@ end

function showerror(io::IO, ex::TypeError)
print(io, "TypeError: ")
ctx = isempty(ex.context) ? "" : "in $(ex.context), "
if ex.expected === Bool
print(io, "non-boolean ($(typeof(ex.got))) used in boolean context")
else
Expand All @@ -206,7 +205,12 @@ function showerror(io::IO, ex::TypeError)
else
tstr = string(typeof(ex.got))
end
print(io, "$(ex.func): $(ctx)expected $(ex.expected), got $tstr")
if isempty(ex.context)
ctx = "in $(ex.func)"
else
ctx = "in $(ex.func), in $(ex.context)"
end
print(io, ctx, ", expected $(ex.expected), got ", tstr)
end
end

Expand Down
1 change: 0 additions & 1 deletion contrib/julia.lang
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,6 @@
<context id="builtin-function" style-ref="builtin-function">
<keyword>is</keyword>
<keyword>typeof</keyword>
<keyword>issubtype</keyword>
<keyword>isa</keyword>
<keyword>typeassert</keyword>
<keyword>apply</keyword>
Expand Down
2 changes: 1 addition & 1 deletion doc/src/devdocs/functions.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ a method table via special arrangement.
The "builtin" functions, defined in the `Core` module, are:
```
=== typeof sizeof issubtype isa typeassert throw tuple getfield setfield! fieldtype
=== typeof sizeof <: isa typeassert throw tuple getfield setfield! fieldtype
nfields isdefined arrayref arrayset arraysize applicable invoke apply_type _apply
_expr svec
```
Expand Down
2 changes: 1 addition & 1 deletion doc/src/devdocs/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -464,7 +464,7 @@ code get triggered often--it will be easiest if you make the following definitio
```julia-repl
julia> function mysubtype(a,b)
ccall(:jl_breakpoint, Void, (Any,), nothing)
issubtype(a, b)
a <: b
end
```

Expand Down
2 changes: 1 addition & 1 deletion doc/src/manual/style-guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -307,7 +307,7 @@ higher-level, Julia-friendly API.

## Be careful with type equality

You generally want to use [`isa()`](@ref) and `<:` ([`issubtype()`](@ref)) for testing types,
You generally want to use [`isa()`](@ref) and [`<:`](@ref) for testing types,
not `==`. Checking types for exact equality typically only makes sense when comparing to a known
concrete type (e.g. `T == Float64`), or if you *really, really* know what you're doing.

Expand Down
3 changes: 1 addition & 2 deletions doc/src/stdlib/base.md
Original file line number Diff line number Diff line change
Expand Up @@ -88,8 +88,7 @@ Base.identity

```@docs
Base.supertype
Core.issubtype
Base.:(<:)
Core.:(<:)
Base.:(>:)
Base.subtypes
Base.typemin
Expand Down
8 changes: 4 additions & 4 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -286,12 +286,12 @@ JL_CALLABLE(jl_f_sizeof)

JL_CALLABLE(jl_f_issubtype)
{
JL_NARGS(issubtype, 2, 2);
JL_NARGS(<:, 2, 2);
jl_value_t *a = args[0], *b = args[1];
if (jl_is_typevar(a)) a = ((jl_tvar_t*)a)->ub; // TODO should we still allow this?
if (jl_is_typevar(b)) b = ((jl_tvar_t*)b)->ub;
JL_TYPECHK(issubtype, type, a);
JL_TYPECHK(issubtype, type, b);
JL_TYPECHK(<:, type, a);
JL_TYPECHK(<:, type, b);
return (jl_subtype(a,b) ? jl_true : jl_false);
}

Expand Down Expand Up @@ -1083,7 +1083,7 @@ void jl_init_primitives(void)
add_builtin_func("===", jl_f_is);
add_builtin_func("typeof", jl_f_typeof);
add_builtin_func("sizeof", jl_f_sizeof);
add_builtin_func("issubtype", jl_f_issubtype);
add_builtin_func("<:", jl_f_issubtype);
add_builtin_func("isa", jl_f_isa);
add_builtin_func("typeassert", jl_f_typeassert);
add_builtin_func("throw", jl_f_throw);
Expand Down
2 changes: 1 addition & 1 deletion src/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -817,7 +817,7 @@ void jl_get_builtins(void)
{
jl_builtin_throw = core("throw"); jl_builtin_is = core("===");
jl_builtin_typeof = core("typeof"); jl_builtin_sizeof = core("sizeof");
jl_builtin_issubtype = core("issubtype"); jl_builtin_isa = core("isa");
jl_builtin_issubtype = core("<:"); jl_builtin_isa = core("isa");
jl_builtin_typeassert = core("typeassert"); jl_builtin__apply = core("_apply");
jl_builtin_isdefined = core("isdefined"); jl_builtin_nfields = core("nfields");
jl_builtin_tuple = core("tuple"); jl_builtin_svec = core("svec");
Expand Down
10 changes: 7 additions & 3 deletions src/module.c
Original file line number Diff line number Diff line change
Expand Up @@ -512,10 +512,14 @@ void jl_binding_deprecation_warning(jl_binding_t *b)
}
else {
jl_methtable_t *mt = jl_gf_mtable(v);
if (mt != NULL && mt->defs.unknown != jl_nothing) {
if (mt != NULL && (mt->defs.unknown != jl_nothing ||
jl_isa(v, (jl_value_t*)jl_builtin_type))) {
jl_printf(JL_STDERR, ", use ");
jl_static_show(JL_STDERR, (jl_value_t*)mt->module);
jl_printf(JL_STDERR, ".%s", jl_symbol_name(mt->name));
if (mt->module != jl_core_module) {
jl_static_show(JL_STDERR, (jl_value_t*)mt->module);
jl_printf(JL_STDERR, ".");
}
jl_printf(JL_STDERR, "%s", jl_symbol_name(mt->name));
jl_printf(JL_STDERR, " instead");
}
}
Expand Down
4 changes: 2 additions & 2 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1983,8 +1983,8 @@ mutable struct A7652
end
a7652 = A7652(0)
t_a7652 = A7652
f7652() = issubtype(fieldtype(t_a7652, :a), Int)
@test f7652() == issubtype(fieldtype(A7652, :a), Int) == true
f7652() = fieldtype(t_a7652, :a) <: Int
@test f7652() == (fieldtype(A7652, :a) <: Int) == true
g7652() = fieldtype(DataType, :types)
@test g7652() == fieldtype(DataType, :types) == SimpleVector
@test fieldtype(t_a7652, 1) == Int
Expand Down
12 changes: 6 additions & 6 deletions test/replutil.jl
Original file line number Diff line number Diff line change
Expand Up @@ -277,17 +277,17 @@ let undefvar
err_str = @except_str 0::Bool TypeError
@test err_str == "TypeError: non-boolean ($Int) used in boolean context"
err_str = @except_str 0::AbstractFloat TypeError
@test err_str == "TypeError: typeassert: expected AbstractFloat, got $Int"
@test err_str == "TypeError: in typeassert, expected AbstractFloat, got $Int"
err_str = @except_str 0::7 TypeError
@test err_str == "TypeError: typeassert: expected Type, got $Int"
@test err_str == "TypeError: in typeassert, expected Type, got $Int"
err_str = @except_str "" <: AbstractString TypeError
@test err_str == "TypeError: issubtype: expected Type, got String"
@test err_str == "TypeError: in <:, expected Type, got String"
err_str = @except_str AbstractString <: "" TypeError
@test err_str == "TypeError: issubtype: expected Type, got String"
@test err_str == "TypeError: in <:, expected Type, got String"
err_str = @except_str Type{""} TypeError
@test err_str == "TypeError: Type: in parameter, expected Type, got String"
@test err_str == "TypeError: in Type, in parameter, expected Type, got String"
err_str = @except_str TypeWithIntParam{Any} TypeError
@test err_str == "TypeError: TypeWithIntParam: in T, expected T<:Integer, got Type{Any}"
@test err_str == "TypeError: in TypeWithIntParam, in T, expected T<:Integer, got Type{Any}"

err_str = @except_str mod(1,0) DivideError
@test err_str == "DivideError: integer division error"
Expand Down
10 changes: 5 additions & 5 deletions test/subtype.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ macro UnionAll(var, expr)
Expr(:where, esc(expr), esc(var))
end

const issub = issubtype
const issub = (<:)
issub_strict(@nospecialize(x),@nospecialize(y)) = issub(x,y) && !issub(y,x)
isequal_type(@nospecialize(x),@nospecialize(y)) = issub(x,y) && issub(y,x)
notequal_type(@nospecialize(x),@nospecialize(y)) = !isequal_type(x, y)
Expand Down Expand Up @@ -501,13 +501,13 @@ function test_old()

# issue #6561
# TODO: note that NTuple now means "tuples of all the same type"
#@test issubtype(Array{Tuple}, Array{NTuple})
#@test (Array{Tuple} <: Array{NTuple})
@test issub_strict(NTuple, Tuple)
@test issub_strict(NTuple, Tuple{Vararg})
@test isequal_type(Tuple, Tuple{Vararg})
#@test issubtype(Array{Tuple{Vararg{Any}}}, Array{NTuple})
#@test issubtype(Array{Tuple{Vararg}}, Array{NTuple})
@test !issubtype(Type{Tuple{Void}}, Tuple{Type{Void}})
#@test (Array{Tuple{Vararg{Any}}} <: Array{NTuple})
#@test (Array{Tuple{Vararg}} <: Array{NTuple})
@test !(Type{Tuple{Void}} <: Tuple{Type{Void}})
end

const menagerie =
Expand Down

0 comments on commit 8df2070

Please sign in to comment.