Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RFC: replace ANY with @nospecialize annotation #22666

Merged
merged 2 commits into from
Jul 14, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,9 @@ Language changes
* In string and character literals, backslash `\` may no longer
precede unrecognized escape characters ([#22800]).

* Declaring arguments as `x::ANY` to avoid specialization has been replaced
by `@nospecialize x`, which needs to be imported from `Base`. ([#22666]).

Breaking changes
----------------

Expand Down
8 changes: 4 additions & 4 deletions base/array.jl
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ getindex(::Type{T}, x) where {T} = (@_inline_meta; a = Array{T,1}(1); @inbounds
getindex(::Type{T}, x, y) where {T} = (@_inline_meta; a = Array{T,1}(2); @inbounds (a[1] = x; a[2] = y); a)
getindex(::Type{T}, x, y, z) where {T} = (@_inline_meta; a = Array{T,1}(3); @inbounds (a[1] = x; a[2] = y; a[3] = z); a)

function getindex(::Type{Any}, vals::ANY...)
function getindex(::Type{Any}, @nospecialize vals...)
a = Array{Any,1}(length(vals))
@inbounds for i = 1:length(vals)
a[i] = vals[i]
Expand Down Expand Up @@ -486,9 +486,9 @@ function _collect_indices(indsA, A)
end

if isdefined(Core, :Inference)
_default_eltype(itrt::ANY) = Core.Inference.return_type(first, Tuple{itrt})
_default_eltype(@nospecialize itrt) = Core.Inference.return_type(first, Tuple{itrt})
else
_default_eltype(itr::ANY) = Any
_default_eltype(@nospecialize itr) = Any
end

_array_for(::Type{T}, itr, ::HasLength) where {T} = Array{T,1}(Int(length(itr)::Integer))
Expand Down Expand Up @@ -694,7 +694,7 @@ function push!(a::Array{T,1}, item) where T
return a
end

function push!(a::Array{Any,1}, item::ANY)
function push!(a::Array{Any,1}, @nospecialize item)
_growend!(a, 1)
arrayset(a, item, length(a))
return a
Expand Down
10 changes: 5 additions & 5 deletions base/associative.jl
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ function sizehint!(t::ObjectIdDict, newsz)
rehash!(t, newsz)
end

function setindex!(t::ObjectIdDict, v::ANY, k::ANY)
function setindex!(t::ObjectIdDict, @nospecialize(v), @nospecialize(k))
if t.ndel >= ((3*length(t.ht))>>2)
rehash!(t, max(length(t.ht)>>1, 32))
t.ndel = 0
Expand All @@ -470,22 +470,22 @@ function setindex!(t::ObjectIdDict, v::ANY, k::ANY)
return t
end

get(t::ObjectIdDict, key::ANY, default::ANY) =
get(t::ObjectIdDict, @nospecialize(key), @nospecialize(default)) =
ccall(:jl_eqtable_get, Any, (Any, Any, Any), t.ht, key, default)

function pop!(t::ObjectIdDict, key::ANY, default::ANY)
function pop!(t::ObjectIdDict, @nospecialize(key), @nospecialize(default))
val = ccall(:jl_eqtable_pop, Any, (Any, Any, Any), t.ht, key, default)
# TODO: this can underestimate `ndel`
val === default || (t.ndel += 1)
return val
end

function pop!(t::ObjectIdDict, key::ANY)
function pop!(t::ObjectIdDict, @nospecialize(key))
val = pop!(t, key, secret_table_token)
val !== secret_table_token ? val : throw(KeyError(key))
end

function delete!(t::ObjectIdDict, key::ANY)
function delete!(t::ObjectIdDict, @nospecialize(key))
pop!(t, key, secret_table_token)
t
end
Expand Down
10 changes: 5 additions & 5 deletions base/base.jl
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,9 @@ mutable struct MethodError <: Exception
f
args
world::UInt
MethodError(f::ANY, args::ANY, world::UInt) = new(f, args, world)
MethodError(@nospecialize(f), @nospecialize(args), world::UInt) = new(f, args, world)
end
MethodError(f::ANY, args::ANY) = MethodError(f, args, typemax(UInt))
MethodError(@nospecialize(f), @nospecialize(args)) = MethodError(f, args, typemax(UInt))

"""
EOFError()
Expand Down Expand Up @@ -122,7 +122,7 @@ ccall(:jl_get_system_hooks, Void, ())
==(w::WeakRef, v) = isequal(w.value, v)
==(w, v::WeakRef) = isequal(w, v.value)

function finalizer(o::ANY, f::ANY)
function finalizer(@nospecialize(o), @nospecialize(f))
if isimmutable(o)
error("objects of type ", typeof(o), " cannot be finalized")
end
Expand All @@ -138,8 +138,8 @@ function finalizer(o::T, f::Ptr{Void}) where T
Core.getptls(), o, f)
end

finalize(o::ANY) = ccall(:jl_finalize_th, Void, (Ptr{Void}, Any,),
Core.getptls(), o)
finalize(@nospecialize(o)) = ccall(:jl_finalize_th, Void, (Ptr{Void}, Any,),
Core.getptls(), o)

gc(full::Bool=true) = ccall(:jl_gc_collect, Void, (Int32,), full)
gc_enable(on::Bool) = ccall(:jl_gc_enable, Int32, (Int32,), on) != 0
Expand Down
75 changes: 41 additions & 34 deletions base/boot.jl
Original file line number Diff line number Diff line change
Expand Up @@ -183,16 +183,23 @@ else
end

function Typeof end
(f::typeof(Typeof))(x::ANY) = isa(x,Type) ? Type{x} : typeof(x)
ccall(:jl_toplevel_eval_in, Any, (Any, Any),
Core, quote
(f::typeof(Typeof))(x) = ($(_expr(:meta,:nospecialize,:x)); isa(x,Type) ? Type{x} : typeof(x))
end)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why does this still need the more complex form? Also, why does it need f::typeof(Typeof) – could we just use Typeof(@nospecialize x) = ...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because Typeof itself is used to lower method definitions not of the form (f::T)(...) = ....


macro nospecialize(x)
_expr(:meta, :nospecialize, x)
end

Expr(@nospecialize args...) = _expr(args...)

abstract type Exception end
mutable struct ErrorException <: Exception
msg::AbstractString
ErrorException(msg::AbstractString) = new(msg)
end

Expr(args::ANY...) = _expr(args...)

macro _noinline_meta()
Expr(:meta, :noinline)
end
Expand All @@ -201,8 +208,8 @@ struct BoundsError <: Exception
a::Any
i::Any
BoundsError() = new()
BoundsError(a::ANY) = (@_noinline_meta; new(a))
BoundsError(a::ANY, i) = (@_noinline_meta; new(a,i))
BoundsError(@nospecialize(a)) = (@_noinline_meta; new(a))
BoundsError(@nospecialize(a), i) = (@_noinline_meta; new(a,i))
end
struct DivideError <: Exception end
struct OverflowError <: Exception end
Expand All @@ -218,8 +225,8 @@ struct InterruptException <: Exception end
struct DomainError <: Exception
val
msg
DomainError(val::ANY) = (@_noinline_meta; new(val))
DomainError(val::ANY, msg::ANY) = (@_noinline_meta; new(val, msg))
DomainError(@nospecialize(val)) = (@_noinline_meta; new(val))
DomainError(@nospecialize(val), @nospecialize(msg)) = (@_noinline_meta; new(val, msg))
end
mutable struct TypeError <: Exception
func::Symbol
Expand All @@ -232,7 +239,7 @@ struct InexactError <: Exception
T::Type
val

InexactError(f::Symbol, T::ANY, val::ANY) = (@_noinline_meta; new(f, T, val))
InexactError(f::Symbol, @nospecialize(T), @nospecialize(val)) = (@_noinline_meta; new(f, T, val))
end

abstract type DirectIndexString <: AbstractString end
Expand All @@ -244,16 +251,16 @@ getptls() = ccall(:jl_get_ptls_states, Ptr{Void}, ())

include(m::Module, fname::String) = ccall(:jl_load_, Any, (Any, Any), m, fname)

eval(e::ANY) = eval(Main, e)
eval(m::Module, e::ANY) = ccall(:jl_toplevel_eval_in, Any, (Any, Any), m, e)
eval(@nospecialize(e)) = eval(Main, e)
eval(m::Module, @nospecialize(e)) = ccall(:jl_toplevel_eval_in, Any, (Any, Any), m, e)

kwfunc(f::ANY) = ccall(:jl_get_keyword_sorter, Any, (Any,), f)
kwfunc(@nospecialize(f)) = ccall(:jl_get_keyword_sorter, Any, (Any,), f)

kwftype(t::ANY) = typeof(ccall(:jl_get_kwsorter, Any, (Any,), t))
kwftype(@nospecialize(t)) = typeof(ccall(:jl_get_kwsorter, Any, (Any,), t))

mutable struct Box
contents::Any
Box(x::ANY) = new(x)
Box(@nospecialize(x)) = new(x)
Box() = new()
end

Expand All @@ -262,18 +269,18 @@ end
mutable struct WeakRef
value
WeakRef() = WeakRef(nothing)
WeakRef(v::ANY) = ccall(:jl_gc_new_weakref_th, Ref{WeakRef},
(Ptr{Void}, Any), getptls(), v)
WeakRef(@nospecialize(v)) = ccall(:jl_gc_new_weakref_th, Ref{WeakRef},
(Ptr{Void}, Any), getptls(), v)
end

TypeVar(n::Symbol) =
ccall(:jl_new_typevar, Ref{TypeVar}, (Any, Any, Any), n, Union{}, Any)
TypeVar(n::Symbol, ub::ANY) =
TypeVar(n::Symbol, @nospecialize(ub)) =
ccall(:jl_new_typevar, Ref{TypeVar}, (Any, Any, Any), n, Union{}, ub)
TypeVar(n::Symbol, lb::ANY, ub::ANY) =
TypeVar(n::Symbol, @nospecialize(lb), @nospecialize(ub)) =
ccall(:jl_new_typevar, Ref{TypeVar}, (Any, Any, Any), n, lb, ub)

UnionAll(v::TypeVar, t::ANY) = ccall(:jl_type_unionall, Any, (Any, Any), v, t)
UnionAll(v::TypeVar, @nospecialize(t)) = ccall(:jl_type_unionall, Any, (Any, Any), v, t)

Void() = nothing

Expand All @@ -288,26 +295,26 @@ VecElement(arg::T) where {T} = VecElement{T}(arg)
# used by lowering of splicing unquote
splicedexpr(hd::Symbol, args::Array{Any,1}) = (e=Expr(hd); e.args=args; e)

_new(typ::Symbol, argty::Symbol) = eval(:((::Type{$typ})(n::$argty) = $(Expr(:new, typ, :n))))
_new(typ::Symbol, argty::Symbol) = eval(Core, :((::Type{$typ})(@nospecialize n::$argty) = $(Expr(:new, typ, :n))))
_new(:LabelNode, :Int)
_new(:GotoNode, :Int)
_new(:NewvarNode, :SlotNumber)
_new(:QuoteNode, :ANY)
_new(:QuoteNode, :Any)
_new(:SSAValue, :Int)
eval(:((::Type{LineNumberNode})(l::Int) = $(Expr(:new, :LineNumberNode, :l, nothing))))
eval(:((::Type{LineNumberNode})(l::Int, f::ANY) = $(Expr(:new, :LineNumberNode, :l, :f))))
eval(:((::Type{GlobalRef})(m::Module, s::Symbol) = $(Expr(:new, :GlobalRef, :m, :s))))
eval(:((::Type{SlotNumber})(n::Int) = $(Expr(:new, :SlotNumber, :n))))
eval(:((::Type{TypedSlot})(n::Int, t::ANY) = $(Expr(:new, :TypedSlot, :n, :t))))
eval(Core, :((::Type{LineNumberNode})(l::Int) = $(Expr(:new, :LineNumberNode, :l, nothing))))
eval(Core, :((::Type{LineNumberNode})(l::Int, @nospecialize(f)) = $(Expr(:new, :LineNumberNode, :l, :f))))
eval(Core, :((::Type{GlobalRef})(m::Module, s::Symbol) = $(Expr(:new, :GlobalRef, :m, :s))))
eval(Core, :((::Type{SlotNumber})(n::Int) = $(Expr(:new, :SlotNumber, :n))))
eval(Core, :((::Type{TypedSlot})(n::Int, @nospecialize(t)) = $(Expr(:new, :TypedSlot, :n, :t))))

Module(name::Symbol=:anonymous, std_imports::Bool=true) = ccall(:jl_f_new_module, Ref{Module}, (Any, Bool), name, std_imports)

Task(f::ANY) = ccall(:jl_new_task, Ref{Task}, (Any, Int), f, 0)
Task(@nospecialize(f)) = ccall(:jl_new_task, Ref{Task}, (Any, Int), f, 0)

# simple convert for use by constructors of types in Core
# note that there is no actual conversion defined here,
# so the methods and ccall's in Core aren't permitted to use convert
convert(::Type{Any}, x::ANY) = x
convert(::Type{Any}, @nospecialize(x)) = x
convert(::Type{T}, x::T) where {T} = x
cconvert(::Type{T}, x) where {T} = convert(T, x)
unsafe_convert(::Type{T}, x::T) where {T} = x
Expand Down Expand Up @@ -382,16 +389,16 @@ function write(io::IO, x::String)
return nb
end

show(io::IO, x::ANY) = ccall(:jl_static_show, Void, (Ptr{Void}, Any), io_pointer(io), x)
show(io::IO, @nospecialize x) = ccall(:jl_static_show, Void, (Ptr{Void}, Any), io_pointer(io), x)
print(io::IO, x::Char) = ccall(:jl_uv_putc, Void, (Ptr{Void}, Char), io_pointer(io), x)
print(io::IO, x::String) = (write(io, x); nothing)
print(io::IO, x::ANY) = show(io, x)
print(io::IO, x::ANY, a::ANY...) = (print(io, x); print(io, a...))
print(io::IO, @nospecialize x) = show(io, x)
print(io::IO, @nospecialize(x), @nospecialize a...) = (print(io, x); print(io, a...))
println(io::IO) = (write(io, 0x0a); nothing) # 0x0a = '\n'
println(io::IO, x::ANY...) = (print(io, x...); println(io))
println(io::IO, @nospecialize x...) = (print(io, x...); println(io))

show(a::ANY) = show(STDOUT, a)
print(a::ANY...) = print(STDOUT, a...)
println(a::ANY...) = println(STDOUT, a...)
show(@nospecialize a) = show(STDOUT, a)
print(@nospecialize a...) = print(STDOUT, a...)
println(@nospecialize a...) = println(STDOUT, a...)

ccall(:jl_set_istopmod, Void, (Any, Bool), Core, true)
2 changes: 1 addition & 1 deletion base/client.jl
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ end
display_error(er, bt) = display_error(STDERR, er, bt)
display_error(er) = display_error(er, [])

function eval_user_input(ast::ANY, show_value)
function eval_user_input(@nospecialize(ast), show_value)
errcount, lasterr, bt = 0, (), nothing
while true
try
Expand Down
2 changes: 1 addition & 1 deletion base/dates/adjusters.jl
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ lastdayofquarter(dt::DateTime) = DateTime(lastdayofquarter(Date(dt)))
struct DateFunction
f::Function
# validate boolean, single-arg inner constructor
function DateFunction(f::ANY, dt::TimeType)
function DateFunction(@nospecialize(f), dt::TimeType)
isa(f(dt), Bool) || throw(ArgumentError("Provided function must take a single TimeType argument and return true or false"))
return new(f)
end
Expand Down
4 changes: 2 additions & 2 deletions base/deepcopy.jl
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ function deepcopy_internal(x::String, stackdict::ObjectIdDict)
return y
end

function deepcopy_internal(x::ANY, stackdict::ObjectIdDict)
function deepcopy_internal(@nospecialize(x), stackdict::ObjectIdDict)
T = typeof(x)::DataType
nf = nfields(x)
(isbits(T) || nf == 0) && return x
Expand All @@ -78,7 +78,7 @@ function deepcopy_internal(x::Array, stackdict::ObjectIdDict)
_deepcopy_array_t(x, eltype(x), stackdict)
end

function _deepcopy_array_t(x::ANY, T, stackdict::ObjectIdDict)
function _deepcopy_array_t(@nospecialize(x), T, stackdict::ObjectIdDict)
if isbits(T)
return (stackdict[x]=copy(x))
end
Expand Down
9 changes: 6 additions & 3 deletions base/deprecated.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1114,7 +1114,7 @@ end
@deprecate(SharedArray(filename::AbstractString, ::Type{T}, dims::NTuple, offset; kwargs...) where {T},
SharedArray{T}(filename, dims, offset; kwargs...))

@noinline function is_intrinsic_expr(x::ANY)
@noinline function is_intrinsic_expr(@nospecialize(x))
Base.depwarn("is_intrinsic_expr is deprecated. There are no intrinsic functions anymore.", :is_intrinsic_expr)
return false
end
Expand Down Expand Up @@ -1372,11 +1372,11 @@ _current_module() = ccall(:jl_get_current_module, Ref{Module}, ())
depwarn("binding_module(symbol) is deprecated, use `binding_module(module, symbol)` instead.", :binding_module)
return binding_module(_current_module(), s)
end
@noinline function expand(x::ANY)
@noinline function expand(@nospecialize(x))
depwarn("expand(x) is deprecated, use `expand(module, x)` instead.", :expand)
return expand(_current_module(), x)
end
@noinline function macroexpand(x::ANY)
@noinline function macroexpand(@nospecialize(x))
depwarn("macroexpand(x) is deprecated, use `macroexpand(module, x)` instead.", :macroexpand)
return macroexpand(_current_module(), x)
end
Expand Down Expand Up @@ -1576,6 +1576,9 @@ end
# nfields(::Type) deprecation in builtins.c: update nfields tfunc in inference.jl when it is removed.
# also replace `_nfields` with `nfields` in summarysize.c when this is removed.

# ::ANY is deprecated in src/method.c
# also remove all instances of `jl_ANY_flag` in src/

# PR #22182
@deprecate is_apple Sys.isapple
@deprecate is_bsd Sys.isbsd
Expand Down
2 changes: 1 addition & 1 deletion base/distributed/clusterserialize.jl
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ function lookup_object_number(s::ClusterSerializer, n::UInt64)
return get(known_object_data, n, nothing)
end

function remember_object(s::ClusterSerializer, o::ANY, n::UInt64)
function remember_object(s::ClusterSerializer, @nospecialize(o), n::UInt64)
known_object_data[n] = o
if isa(o, TypeName) && !haskey(object_numbers, o)
# set up reverse mapping for serialize
Expand Down
2 changes: 1 addition & 1 deletion base/distributed/remotecall.jl
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ Waits and fetches a value from `x` depending on the type of `x`:

Does not remove the item fetched.
"""
fetch(x::ANY) = x
fetch(@nospecialize x) = x

isready(rv::RemoteValue, args...) = isready(rv.c, args...)

Expand Down
4 changes: 2 additions & 2 deletions base/docs/Docs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ mutable struct DocStr
data :: Dict{Symbol, Any}
end

function docstr(binding::Binding, typesig::ANY = Union{})
function docstr(binding::Binding, @nospecialize typesig = Union{})
for m in modules
dict = meta(m)
if haskey(dict, binding)
Expand Down Expand Up @@ -229,7 +229,7 @@ end

Adds a new docstring `str` to the docsystem of `__module__` for `binding` and signature `sig`.
"""
function doc!(__module__::Module, b::Binding, str::DocStr, sig::ANY = Union{})
function doc!(__module__::Module, b::Binding, str::DocStr, @nospecialize sig = Union{})
initmeta(__module__)
m = get!(meta(__module__), b, MultiDoc())
if haskey(m.docs, sig)
Expand Down
8 changes: 0 additions & 8 deletions base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -689,14 +689,6 @@ The singleton instance of type `Void`, used by convention when there is no value
"""
nothing

"""
ANY

Equivalent to `Any` for dispatch purposes, but signals the compiler to skip code
generation specialization for that field.
"""
ANY

"""
Core.TypeofBottom

Expand Down
Loading