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 Test.GenericDimensionful number type #39852

Open
wants to merge 23 commits into
base: master
Choose a base branch
from

Conversation

stevengj
Copy link
Member

@stevengj stevengj commented Feb 27, 2021

Closes #30692.

As commented in #27899 (comment), we had actually defined three four different unitful types for tests (Furlong, PhysQuantity, MeterUnits, and MockUnitful). This unifies them all into a single type GenericDimensionful that is exported from Test.

(This is analogous to GenericString, GenericDict, etcetera — the goal is to make it easy for package developers to test that their code is generic to new number types without having to think about which additional dependency to pull in.)

Along the way, I discovered a few bugs in the support of dimensionful types by Base and LinearAlgebra functions and I fixed them. (The basic issue is that you should not assume you can convert between types with different dimensions, and should only rely on constructors.)

  • For now, I left in a const Furlong = Test.GenericDimensionful stub definition because it is needed by the Statistics.jl tests. Once Statistics.jl is updated we can change this to a deprecation. (Or delete it — according to juliahub, no other packages use it?)

@stevengj stevengj added the testsystem The unit testing framework and Test stdlib label Feb 27, 2021
@stevengj
Copy link
Member Author

The remaining CI failures seem unrelated.

On package_linux32:

/buildworker/worker/package_linux32/build/usr/tools/llvm-size -A /buildworker/worker/package_linux32/build/usr/lib/julia/sys.so /buildworker/worker/package_linux32/build/usr/lib/libjulia.so /buildworker/worker/package_linux32/build/usr/bin/julia
Makefile:563: recipe for target 'build-stats' failed
make: *** [build-stats] Segmentation fault (core dumped)

on tester_linux64:

Error in testset SparseArrays/sparse:
Error During Test at none:1
  Got exception outside of a @test
  ProcessExitedException(7)
  Stacktrace:
    [1] try_yieldto(undo::typeof(Base.ensure_rescheduled))
      @ Base ./task.jl:705
    [2] wait
      @ ./task.jl:764 [inlined]
    [3] wait(c::Base.GenericCondition{ReentrantLock})
      @ Base ./condition.jl:113
    [4] take_buffered(c::Channel{Any})
      @ Base ./channels.jl:389
    [5] take!(c::Channel{Any})
      @ Base ./channels.jl:383
    [6] take!(::Distributed.RemoteValue)
      @ Distributed /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Distributed/src/remotecall.jl:599
    [7] remotecall_fetch(::Function, ::Distributed.Worker, ::String, ::Vararg{String}; kwargs::Base.Iterators.Pairs{Symbol, UInt128, Tuple{Symbol}, NamedTuple{(:seed,), Tuple{UInt128}}})
      @ Distributed /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Distributed/src/remotecall.jl:390
    [8] remotecall_fetch(::Function, ::Int64, ::String, ::Vararg{String}; kwargs::Base.Iterators.Pairs{Symbol, UInt128, Tuple{Symbol}, NamedTuple{(:seed,), Tuple{UInt128}}})
      @ Distributed /buildworker/worker/package_linux64/build/usr/share/julia/stdlib/v1.7/Distributed/src/remotecall.jl:421
    [9] macro expansion
      @ /buildworker/worker/tester_linux64/build/share/julia/test/runtests.jl:231 [inlined]
   [10] (::var"#29#39"{Vector{Task}, var"#print_testworker_errored#35"{ReentrantLock, Int64, Int64}, var"#print_testworker_stats#33"{ReentrantLock, Int64, Int64, Int64, Int64, Int64, Int64}, Vector{Any}, Dict{String, DateTime}})()
      @ Main ./task.jl:406

and on tester_freebsd64:

Error in testset Sockets:
Error During Test at none:1
  Got exception outside of a @test
  ProcessExitedException(4)
  Stacktrace:
    [1] try_yieldto(undo::typeof(Base.ensure_rescheduled))
      @ Base ./task.jl:705
    [2] wait
      @ ./task.jl:764 [inlined]
    [3] wait(c::Base.GenericCondition{ReentrantLock})
      @ Base ./condition.jl:113
    [4] take_buffered(c::Channel{Any})
      @ Base ./channels.jl:389
    [5] take!(c::Channel{Any})
      @ Base ./channels.jl:383
    [6] take!(::Distributed.RemoteValue)
      @ Distributed /usr~/worker/package_freebsd64/build/usr/share/julia/stdlib/v1.7/Distributed/src/remotecall.jl:599
    [7] remotecall_fetch(::Function, ::Distributed.Worker, ::String, ::Vararg{String}; kwargs::Base.Iterators.Pairs{Symbol, UInt128, Tuple{Symbol}, NamedTuple{(:seed,), Tuple{UInt128}}})
      @ Distributed /usr~/worker/package_freebsd64/build/usr/share/julia/stdlib/v1.7/Distributed/src/remotecall.jl:390
    [8] remotecall_fetch(::Function, ::Int64, ::String, ::Vararg{String}; kwargs::Base.Iterators.Pairs{Symbol, UInt128, Tuple{Symbol}, NamedTuple{(:seed,), Tuple{UInt128}}})
      @ Distributed /usr~/worker/package_freebsd64/build/usr/share/julia/stdlib/v1.7/Distributed/src/remotecall.jl:421
    [9] macro expansion
      @ /usr~/worker-tabularasa/tester_freebsd64/build/share/julia/test/runtests.jl:231 [inlined]
   [10] (::var"#29#39"{Vector{Task}, var"#print_testworker_errored#35"{ReentrantLock, Int64, Int64}, var"#print_testworker_stats#33"{ReentrantLock, Int64, Int64, Int64, Int64, Int64, Int64}, Vector{Any}, Dict{String, DateTime}})()
      @ Main ./task.jl:406

@sostock
Copy link
Contributor

sostock commented Feb 28, 2021

Do we know that there are packages that use Furlong and none that use PhysQuantity?

base/floatfuncs.jl Outdated Show resolved Hide resolved
base/floatfuncs.jl Outdated Show resolved Hide resolved
stdlib/Test/src/GenericDimensionfuls.jl Outdated Show resolved Hide resolved
stdlib/Test/src/GenericDimensionfuls.jl Outdated Show resolved Hide resolved
stdlib/Test/src/GenericDimensionfuls.jl Outdated Show resolved Hide resolved
stdlib/Test/src/GenericDimensionfuls.jl Outdated Show resolved Hide resolved
stdlib/Test/src/GenericDimensionfuls.jl Outdated Show resolved Hide resolved
@stevengj
Copy link
Member Author

Do we know that there are packages that use Furlong and none that use PhysQuantity?

According to juliahub.com, the only package that uses either one is Statistics.jl (which uses Furlong).

stevengj and others added 5 commits February 28, 2021 11:18
Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com>
Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com>
Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com>
@sostock
Copy link
Contributor

sostock commented Mar 2, 2021

Should we get a second opinion on the DimensionMismatch pun?

@sostock
Copy link
Contributor

sostock commented Mar 2, 2021

Should we have

GenericDimensionful{2}(1) == GenericDimensionful{2.0}(1) == GenericDimensionful{2//1}(1)

or should we expect that people only use the canonical form (Int for integer exponents, Rational{Int} for fractional exponents)? We could also enforce the canonical form in the constructor.

Edit: I see that the above equality should now hold via promotion.

Comment on lines +55 to +56
@test_throws DimensionMismatch x == GD{2}(4)
@test_throws ErrorException x == 3
Copy link
Contributor

Choose a reason for hiding this comment

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

IMO, these shouldn’t error, they should return false (I don’t think == ever errors). Unitful and Dates also return false in this case.

Adding equivalent tests for isequal would also be good.

stdlib/Test/src/GenericDimensionfuls.jl Outdated Show resolved Hide resolved
stdlib/Test/src/GenericDimensionfuls.jl Outdated Show resolved Hide resolved
stevengj and others added 3 commits March 2, 2021 13:33
Co-authored-by: Sebastian Stock <42280794+sostock@users.noreply.github.com>
@sostock
Copy link
Contributor

sostock commented Mar 2, 2021

I think a lot of things would be easier if we only allowed the canonical type for any p.

@sostock sostock closed this Mar 2, 2021
@sostock sostock reopened this Mar 2, 2021
@sostock
Copy link
Contributor

sostock commented Mar 2, 2021

Sorry, I closed it on accident.

@sostock
Copy link
Contributor

sostock commented Mar 2, 2021

Since we have a custom isequal method, we also need to add compatible hash methods. In particular, since GenericDimensionful{0}(x) is equal to x, they must have the same hash.

@sostock
Copy link
Contributor

sostock commented Mar 2, 2021

If we want to allow non-canonical exponents, we need to fix this method ambiguity:

julia> promote(GenericDimensionful{0}(2), GenericDimensionful{0.0}(2))
ERROR: MethodError: promote_rule(::Type{GenericDimensionful{0, Int64}}, ::Type{GenericDimensionful{0.0, Int64}}) is ambiguous. Candidates:
  promote_rule(::Type{GenericDimensionful{p, T}}, ::Type{GenericDimensionful{q, S}}) where {p, q, T, S} in Test.GenericDimensionfuls at /home/sebastian/Development/julia/usr/share/julia/stdlib/v1.7/Test/src/GenericDimensionfuls.jl:43
  promote_rule(::Type{GenericDimensionful{0, T}}, ::Type{S}) where {T, S<:Number} in Test.GenericDimensionfuls at /home/sebastian/Development/julia/usr/share/julia/stdlib/v1.7/Test/src/GenericDimensionfuls.jl:46
Possible fix, define
  promote_rule(::Type{GenericDimensionful{0, T}}, ::Type{GenericDimensionful{q, S}}) where {T, q, S}

end
GenericDimensionful(x::T) where {T<:Number} = GenericDimensionful{1,T}(x)
GenericDimensionful(x::GenericDimensionful) = x
(::Type{T})(x::GenericDimensionful) where {T<:Number} = T(x.val)::T
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
(::Type{T})(x::GenericDimensionful) where {T<:Number} = T(x.val)::T
(::Type{T})(x::GenericDimensionful{0}) where {T<:Number} = T(x.val)::T

So that we don’t convert dimensionful numbers to dimensionless ones.

@vtjnash
Copy link
Member

vtjnash commented Mar 28, 2022

Are we still interested in these fixes, or what stalled it? Furlong has picked up a few bugfixes, so those will need to be moved into the new type here

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
testsystem The unit testing framework and Test stdlib
Projects
None yet
Development

Successfully merging this pull request may close these issues.

incorporate testhelpers/Furlong.jl into Test package?
3 participants