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

delete Bottom from Base #55293

Closed
wants to merge 2 commits into from
Closed
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
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ Language changes
expression within a given `:toplevel` expression to make use of macros
defined earlier in the same `:toplevel` expression. ([#53515])

- `Base.Bottom`, an alias for the `Union{}` type, is deleted.

Compiler/Runtime improvements
-----------------------------

Expand Down
2 changes: 1 addition & 1 deletion base/abstractarray.jl
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ UInt8
```
"""
eltype(::Type) = Any
eltype(::Type{Bottom}, slurp...) = throw(ArgumentError("Union{} does not have elements"))
eltype(::Type{Union{}}, slurp...) = throw(ArgumentError("Union{} does not have elements"))
eltype(x) = eltype(typeof(x))
eltype(::Type{<:AbstractArray{E}}) where {E} = @isdefined(E) ? E : Any

Expand Down
3 changes: 3 additions & 0 deletions base/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ const NUM_EFFECTS_OVERRIDES = 10 # sync with julia.h

# essential files and libraries
include("essentials.jl")

const Bottom = Union{}

include("ctypes.jl")
include("generator.jl")
include("reflection.jl")
Expand Down
7 changes: 4 additions & 3 deletions base/docs/basedocs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -3186,16 +3186,17 @@ Any
Union{}

`Union{}`, the empty [`Union`](@ref) of types, is the type that has no values. That is, it has the defining
property `isa(x, Union{}) == false` for any `x`. `Base.Bottom` is defined as its alias and the type of `Union{}`
is `Core.TypeofBottom`.
property `isa(x, Union{}) == false` for any `x`.

The type of `Union{}` is `Core.TypeofBottom`.

# Examples
```jldoctest
julia> isa(nothing, Union{})
false
```
"""
kw"Union{}", Base.Bottom
kw"Union{}"

"""
Union{Types...}
Expand Down
4 changes: 2 additions & 2 deletions base/error.jl
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,8 @@ exception will continue propagation as if it had not been caught.
`throw(e)` will preserve the root cause exception on the stack, as
described in [`current_exceptions`](@ref).
"""
rethrow() = ccall(:jl_rethrow, Bottom, ())
rethrow(@nospecialize(e)) = ccall(:jl_rethrow_other, Bottom, (Any,), e)
rethrow() = ccall(:jl_rethrow, Union{}, ())
rethrow(@nospecialize(e)) = ccall(:jl_rethrow_other, Union{}, (Any,), e)

struct InterpreterIP
code::Union{CodeInfo,Core.MethodInstance,Core.CodeInstance,Nothing}
Expand Down
2 changes: 0 additions & 2 deletions base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ using Core: CodeInfo, SimpleVector, donotdelete, compilerbarrier, memoryrefnew,

const Callable = Union{Function,Type}

const Bottom = Union{}

# Define minimal array interface here to help code used in macros:
length(a::Array{T, 0}) where {T} = 1
length(a::Array{T, 1}) where {T} = getfield(a, :size)[1]
Expand Down
38 changes: 19 additions & 19 deletions base/promotion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ julia> typejoin(Int, Float64, ComplexF32)
Number
```
"""
typejoin() = Bottom
typejoin() = Union{}
typejoin(@nospecialize(t)) = (@_nospecializeinfer_meta; t)
typejoin(@nospecialize(t), @nospecialize(s), @nospecialize(u)) = (@_foldable_meta; @_nospecializeinfer_meta; typejoin(typejoin(t, s), u))
typejoin(@nospecialize(t), @nospecialize(s), @nospecialize(u), ts...) = (@_foldable_meta; @_nospecializeinfer_meta; afoldl(typejoin, typejoin(t, s, u), ts...))
Expand Down Expand Up @@ -100,8 +100,8 @@ function typejoin(@nospecialize(a), @nospecialize(b))
if a.name === Type.body.name
ap = a.parameters[1]
bp = b.parameters[1]
if ((isa(ap,TypeVar) && ap.lb === Bottom && ap.ub === Any) ||
(isa(bp,TypeVar) && bp.lb === Bottom && bp.ub === Any))
if ((isa(ap,TypeVar) && ap.lb === Union{} && ap.ub === Any) ||
(isa(bp,TypeVar) && bp.lb === Union{} && bp.ub === Any))
# handle special Type{T} supertype
return Type
end
Expand Down Expand Up @@ -143,7 +143,7 @@ function typesplit(@nospecialize(a), @nospecialize(b))
@_foldable_meta
@_nospecializeinfer_meta
if a <: b
return Bottom
return Union{}
end
if isa(a, Union)
return Union{typesplit(a.a, b),
Expand Down Expand Up @@ -247,7 +247,7 @@ function tailjoin(A::SimpleVector, i::Int)
if i > length(A)
return unwrapva(A[end])
end
t = Bottom
t = Union{}
for j = i:length(A)
t = typejoin(t, unwrapva(A[j]))
end
Expand Down Expand Up @@ -298,23 +298,23 @@ UInt16
"""
function promote_type end

promote_type() = Bottom
promote_type() = Union{}
promote_type(T) = T
promote_type(T, S, U) = (@inline; promote_type(promote_type(T, S), U))
promote_type(T, S, U, V...) = (@inline; afoldl(promote_type, promote_type(T, S, U), V...))

promote_type(::Type{Bottom}, ::Type{Bottom}) = Bottom
promote_type(::Type{Union{}}, ::Type{Union{}}) = Union{}
promote_type(::Type{T}, ::Type{T}) where {T} = T
promote_type(::Type{T}, ::Type{Bottom}) where {T} = T
promote_type(::Type{Bottom}, ::Type{T}) where {T} = T
promote_type(::Type{T}, ::Type{Union{}}) where {T} = T
promote_type(::Type{Union{}}, ::Type{T}) where {T} = T

function promote_type(::Type{T}, ::Type{S}) where {T,S}
@inline
# Try promote_rule in both orders. Typically only one is defined,
# and there is a fallback returning Bottom below, so the common case is
# and there is a fallback returning `Union{}` below, so the common case is
# promote_type(T, S) =>
# promote_result(T, S, result, Bottom) =>
# typejoin(result, Bottom) => result
# promote_result(T, S, result, Union{}) =>
# typejoin(result, Union{}) => result
promote_result(T, S, promote_rule(T,S), promote_rule(S,T))
end

Expand All @@ -327,18 +327,18 @@ it for new types as appropriate.
"""
function promote_rule end

promote_rule(::Type, ::Type) = Bottom
promote_rule(::Type, ::Type) = Union{}
# Define some methods to avoid needing to enumerate unrelated possibilities when presented
# with Type{<:T}, and return a value in general accordance with the result given by promote_type
promote_rule(::Type{Bottom}, slurp...) = Bottom
promote_rule(::Type{Bottom}, ::Type{Bottom}, slurp...) = Bottom # not strictly necessary, since the next method would match unambiguously anyways
promote_rule(::Type{Bottom}, ::Type{T}, slurp...) where {T} = T
promote_rule(::Type{T}, ::Type{Bottom}, slurp...) where {T} = T
promote_rule(::Type{Union{}}, slurp...) = Union{}
promote_rule(::Type{Union{}}, ::Type{Union{}}, slurp...) = Union{} # not strictly necessary, since the next method would match unambiguously anyways
promote_rule(::Type{Union{}}, ::Type{T}, slurp...) where {T} = T
promote_rule(::Type{T}, ::Type{Union{}}, slurp...) where {T} = T

promote_result(::Type,::Type,::Type{T},::Type{S}) where {T,S} = (@inline; promote_type(T,S))
# If no promote_rule is defined, both directions give Bottom. In that
# If no promote_rule is defined, both directions give `Union{}`. In that
# case use typejoin on the original types instead.
promote_result(::Type{T},::Type{S},::Type{Bottom},::Type{Bottom}) where {T,S} = (@inline; typejoin(T, S))
promote_result(::Type{T},::Type{S},::Type{Union{}},::Type{Union{}}) where {T,S} = (@inline; typejoin(T, S))

"""
promote(xs...)
Expand Down
10 changes: 5 additions & 5 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -817,14 +817,14 @@ function isidentityfree(@nospecialize(t))
return false
end

iskindtype(@nospecialize t) = (t === DataType || t === UnionAll || t === Union || t === typeof(Bottom))
iskindtype(@nospecialize t) = (t === DataType || t === UnionAll || t === Union || t === typeof(Union{}))
isconcretedispatch(@nospecialize t) = isconcretetype(t) && !iskindtype(t)
has_free_typevars(@nospecialize(t)) = (@_total_meta; ccall(:jl_has_free_typevars, Cint, (Any,), t) != 0)

# equivalent to isa(v, Type) && isdispatchtuple(Tuple{v}) || v === Union{}
# and is thus perhaps most similar to the old (pre-1.0) `isleaftype` query
function isdispatchelem(@nospecialize v)
return (v === Bottom) || (v === typeof(Bottom)) || isconcretedispatch(v) ||
return (v === Union{}) || (v === typeof(Union{})) || isconcretedispatch(v) ||
(isType(v) && !has_free_typevars(v))
end

Expand Down Expand Up @@ -2513,9 +2513,9 @@ false
function isambiguous(m1::Method, m2::Method; ambiguous_bottom::Bool=false)
m1 === m2 && return false
ti = typeintersect(m1.sig, m2.sig)
ti === Bottom && return false
ti === Union{} && return false
function inner(ti)
ti === Bottom && return false
ti === Union{} && return false
if !ambiguous_bottom
has_bottom_parameter(ti) && return false
end
Expand Down Expand Up @@ -2623,7 +2623,7 @@ function has_bottom_parameter(t::DataType)
end
return false
end
has_bottom_parameter(t::typeof(Bottom)) = true
has_bottom_parameter(t::typeof(Union{})) = true
has_bottom_parameter(t::UnionAll) = has_bottom_parameter(unwrap_unionall(t))
has_bottom_parameter(t::Union) = has_bottom_parameter(t.a) & has_bottom_parameter(t.b)
has_bottom_parameter(t::TypeVar) = has_bottom_parameter(t.ub)
Expand Down
4 changes: 2 additions & 2 deletions base/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2781,7 +2781,7 @@ function show(io::IO, tv::TypeVar)
# If we are in the `unionall_env`, the type-variable is bound
# and the type constraints are already printed.
# We don't need to print it again.
# Otherwise, the lower bound should be printed if it is not `Bottom`
# Otherwise, the lower bound should be printed if it is not `Union{}`
# and the upper bound should be printed if it is not `Any`.
in_env = (:unionall_env => tv) in io
function show_bound(io::IO, @nospecialize(b))
Expand All @@ -2791,7 +2791,7 @@ function show(io::IO, tv::TypeVar)
parens && print(io, ")")
end
lb, ub = tv.lb, tv.ub
if !in_env && lb !== Bottom
if !in_env && lb !== Union{}
if ub === Any
show_unquoted(io, tv.name)
print(io, ">:")
Expand Down
2 changes: 1 addition & 1 deletion base/tuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -266,7 +266,7 @@ first(t::Tuple) = t[1]

# eltype

eltype(::Type{Tuple{}}) = Bottom
eltype(::Type{Tuple{}}) = Union{}
# the <: here makes the runtime a bit more complicated (needing to check isdefined), but really helps inference
eltype(t::Type{<:Tuple{Vararg{E}}}) where {E} = @isdefined(E) ? (E isa Type ? E : Union{}) : _compute_eltype(t)
eltype(t::Type{<:Tuple}) = _compute_eltype(t)
Expand Down
4 changes: 2 additions & 2 deletions stdlib/InteractiveUtils/src/InteractiveUtils.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export apropos, edit, less, code_warntype, code_llvm, code_native, methodswith,

import Base.Docs.apropos

using Base: unwrap_unionall, rewrap_unionall, isdeprecated, Bottom, summarysize,
using Base: unwrap_unionall, rewrap_unionall, isdeprecated, summarysize,
signature_type, format_bytes
using Base.Libc
using Markdown
Expand Down Expand Up @@ -268,7 +268,7 @@ function _subtypes_in!(mods::Array, x::Type)
if isa(dt, DataType)
if dt.name.name === s && dt.name.module == m && supertype(dt).name == xt.name
ti = typeintersect(t, x)
ti != Bottom && push!(sts, ti)
ti != Union{} && push!(sts, ti)
end
elseif isa(t, Module) && nameof(t) === s && parentmodule(t) === m && t !== m
t === Base || push!(mods, t) # exclude Base, since it also parented by Main
Expand Down
8 changes: 4 additions & 4 deletions stdlib/Serialization/src/Serialization.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Provide serialization of Julia objects via the functions
"""
module Serialization

import Base: Bottom, unsafe_convert
import Base: unsafe_convert
import Core: svec, SimpleVector
using Base: unaliascopy, unwrap_unionall, require_one_based_indexing, ntupleany
using Core.IR
Expand Down Expand Up @@ -62,7 +62,7 @@ const TAGS = Any[
ReturnNode, GotoIfNot,
fill(Symbol, n_reserved_tags)...,

(), Bool, Any, Bottom, Core.TypeofBottom, Type, svec(), Tuple{}, false, true, nothing,
(), Bool, Any, Union{}, Core.TypeofBottom, Type, svec(), Tuple{}, false, true, nothing,
:Any, :Array, :TypeVar, :Box, :Tuple, :Ptr, :return, :call, Symbol("::"), :Function,
:(=), :(==), :(===), :gotoifnot, :A, :B, :C, :M, :N, :T, :S, :X, :Y, :a, :b, :c, :d, :e, :f,
:g, :h, :i, :j, :k, :l, :m, :n, :o, :p, :q, :r, :s, :t, :u, :v, :w, :x, :y, :z, :add_int,
Expand Down Expand Up @@ -120,7 +120,7 @@ const TYPENAME_TAG = sertag(Core.TypeName)
const INT32_TAG = sertag(Int32)
const INT64_TAG = sertag(Int64)
const GLOBALREF_TAG = sertag(GlobalRef)
const BOTTOM_TAG = sertag(Bottom)
const BOTTOM_TAG = sertag(Union{})
const UNIONALL_TAG = sertag(UnionAll)
const STRING_TAG = sertag(String)
const o0 = sertag(SSAValue)
Expand Down Expand Up @@ -652,7 +652,7 @@ for i in 0:13
@eval serialize(s::AbstractSerializer, n::$ty) = (writetag(s.io, $tag); write(s.io, n); nothing)
end

serialize(s::AbstractSerializer, ::Type{Bottom}) = write_as_tag(s.io, BOTTOM_TAG)
serialize(s::AbstractSerializer, ::Type{Union{}}) = write_as_tag(s.io, BOTTOM_TAG)

function serialize(s::AbstractSerializer, u::UnionAll)
writetag(s.io, UNIONALL_TAG)
Expand Down
Loading