diff --git a/src/Unitful.jl b/src/Unitful.jl index 343f49b6..dac82934 100644 --- a/src/Unitful.jl +++ b/src/Unitful.jl @@ -53,7 +53,7 @@ end const basefactors = _basefactors(Unitful) include("types.jl") -const promotion = Dict{Symbol,Unit}() +const promotion = Dict{Symbol,FreeUnits}() include("user.jl") include("utils.jl") diff --git a/src/units.jl b/src/units.jl index d0aed6f9..a66a047d 100644 --- a/src/units.jl +++ b/src/units.jl @@ -302,6 +302,6 @@ factory defaults, this function will return a product of powers of base SI units (as [`Unitful.FreeUnits`](@ref)). """ @generated function upreferred(x::Dimensions{D}) where {D} - u = *(FreeUnits{((Unitful.promotion[name(z)]^z.power for z in D)...,),()}()) + u = prod((NoUnits, (promotion[name(z)]^z.power for z in D)...)) :($u) end diff --git a/src/user.jl b/src/user.jl index 50a62783..e3fb21a2 100644 --- a/src/user.jl +++ b/src/user.jl @@ -310,7 +310,28 @@ function preferunits(u0::Units, u::Units...) "For instance, it should not be used with units of dimension 𝐋^2.") end y = typeof(dim).parameters[1][1] - promotion[name(y)] = typeof(unit).parameters[1][1] + promotion[name(y)] = unit + end + + # Let's run a quick check for anything where, for instance, current was defined is C/ms and time + # was defined in ns. We'll give a warning if this is the case so the user knows they may get + # unexpected (though still correct) results. There may be cases where people would want to do this, + # so we won't stop them, just let them know they're doing it. + ulist = (typeof(i[2]).parameters[1] for i in promotion) + check = Dict{Dimensions, Unit}() + for a in ulist + ulistA = (i^(1/i.power) for i in a) + for i in ulistA + k = dimension(i) + if haskey(check, k) + if i!=check[k] + @warn "Preferred units contain complex units based on units of the same dimension but different scales: "*string(i)*" and "*string(check[k])* + "\nThis may be intentional, but otherwise could lead to redundant units, such as ms/s or kg/g" + end + else + check[k] = i + end + end end nothing diff --git a/test/runtests.jl b/test/runtests.jl index d1f21eab..59b226ea 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -14,7 +14,8 @@ import Unitful: J, A, N, mol, V, mW, W, dB, dB_rp, dB_p, dBm, dBV, dBSPL, Decibel, - Np, Np_rp, Np_p, Neper + Np, Np_rp, Np_p, Neper, + C import Unitful: 𝐋, 𝐓, 𝐍, 𝚯 @@ -320,6 +321,16 @@ Unitful.uconvert(U::Unitful.Units, q::QQQ) = uconvert(U, Quantity(q.val, cm)) @testset "Promotion" begin @testset "> Unit preferences" begin + # Should warn on possible redundant units issue (ms and s) + @test_logs (:warn, r"^Preferred units contain complex units") Unitful.preferunits(C/ms) + # Test for wacky prefered units functionality + Unitful.preferunits(C/s) + @test @inferred(upreferred(V/m)) == kg*m*C^-1*s^-2 + @test dimension(upreferred(V/m)) == dimension(V/m) + # Reset preferred units to default, except for units of dimension 𝐋*𝐌*𝐈^-1*𝐓^-3, + # because upreferred has already been called for that dimension + Unitful.preferunits(A) + # Only because we favor SI, we have the following: @test @inferred(upreferred(N)) === kg*m/s^2 @test @inferred(upreferred(dimension(N))) === kg*m/s^2