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

Add a contract for Ordered and additional traits #37239

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
1 change: 1 addition & 0 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ module IteratorsMD

# comparison
@inline isless(I1::CartesianIndex{N}, I2::CartesianIndex{N}) where {N} = _isless(0, I1.I, I2.I)
Base.OrderStyle(::Type{<:Union{Missing,CartesianIndex}}) = Base.Ordered()
@inline function _isless(ret, I1::NTuple{N,Int}, I2::NTuple{N,Int}) where N
newret = ifelse(ret==0, icmp(I1[N], I2[N]), ret)
_isless(newret, Base.front(I1), Base.front(I2))
Expand Down
40 changes: 35 additions & 5 deletions base/traits.jl
Original file line number Diff line number Diff line change
@@ -1,17 +1,47 @@
# This file is a part of Julia. License is MIT: https://julialang.org/license

## numeric/object traits
# trait for objects that have an ordering

"""
OrderedStyle()

An abstract type of a trait that signals if some type `T` guarantees
that a call `isless(::T, ::T)` will return `true` or `false`.

It has two concrete subtypes [`Ordered`](@ref) and
[`Unordered`](@ref), which is the default.

Types supporting [`isless`](@ref) are recommended to support
[`Ordered`](@ref) trait to enable optimizations.
bkamins marked this conversation as resolved.
Show resolved Hide resolved
"""
abstract type OrderStyle end

"""
Ordered()

Indicate that a type `T` guarantees that a call `isless(::T, ::T)` will return `true` or `false`.
It is recommended that custom types defining `isless` implement this
trait as this information can be used to enable optimizations.
"""
bkamins marked this conversation as resolved.
Show resolved Hide resolved
struct Ordered <: OrderStyle end

"""
Unordered()

A default `OrderStyle` for any type `T` indicating that optimizations
cannot rely on the fact that it is guaranteed that a call `isless(::T, ::T)`
will return `true` or `false`.
"""
struct Unordered <: OrderStyle end
bkamins marked this conversation as resolved.
Show resolved Hide resolved

OrderStyle(instance) = OrderStyle(typeof(instance))
bkamins marked this conversation as resolved.
Show resolved Hide resolved
OrderStyle(::Type{<:Real}) = Ordered()
OrderStyle(::Type{<:AbstractString}) = Ordered()
OrderStyle(::Type{Symbol}) = Ordered()
OrderStyle(::Type{<:Any}) = Unordered()
OrderStyle(::Type{Union{}}) = Ordered()
OrderStyle(::Type{<:Union{Missing,Real}}) = Ordered()
OrderStyle(::Type{<:Union{Missing,AbstractString}}) = Ordered()
OrderStyle(::Type{<:Union{Missing,AbstractChar}}) = Ordered()
OrderStyle(::Type{<:Union{Missing,Symbol}}) = Ordered()
OrderStyle(::Type{<:Missing}) = Ordered()
OrderStyle(::Type{<:Any}) = Unordered()

# trait for objects that support arithmetic
abstract type ArithmeticStyle end
Expand Down
1 change: 1 addition & 0 deletions stdlib/Dates/src/periods.jl
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ default(p::Union{T,Type{T}}) where {T<:TimePeriod} = T(0)
==(x::Period, y::Period) = (==)(promote(x, y)...)
Base.isless(x::P, y::P) where {P<:Period} = isless(value(x), value(y))
Base.isless(x::Period, y::Period) = isless(promote(x, y)...)
Base.OrderStyle(::Type{<:Union{Missing,Period}}) = Base.Ordered()

# Period Arithmetic, grouped by dimensionality:
for op in (:+, :-, :lcm, :gcd)
Expand Down
1 change: 1 addition & 0 deletions stdlib/Dates/src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,7 @@ Base.typemin(::Union{Time, Type{Time}}) = Time(0)
Base.promote_rule(::Type{Date}, x::Type{DateTime}) = DateTime
Base.isless(x::T, y::T) where {T<:TimeType} = isless(value(x), value(y))
Base.isless(x::TimeType, y::TimeType) = isless(promote(x, y)...)
Base.OrderStyle(::Type{<:Union{Missing,TimeType}}) = Base.Ordered()
(==)(x::T, y::T) where {T<:TimeType} = (==)(value(x), value(y))
(==)(x::TimeType, y::TimeType) = (===)(promote(x, y)...)
Base.min(x::AbstractTime) = x
Expand Down
1 change: 1 addition & 0 deletions stdlib/Test/src/Test.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1647,6 +1647,7 @@ struct GenericOrder{T}
val::T
end
Base.isless(x::GenericOrder, y::GenericOrder) = isless(x.val,y.val)
Base.OrderStyle(::Type{<:Union{Missing,GenericOrder}}) = Base.Ordered()

Base.keys(a::GenericArray) = keys(a.a)
Base.axes(a::GenericArray) = axes(a.a)
Expand Down