Skip to content

Commit

Permalink
Merge pull request #1001 from JuliaSymbolics/error_hint
Browse files Browse the repository at this point in the history
Add error hint on implicit Float conversion from Num
  • Loading branch information
ChrisRackauckas authored Oct 16, 2023
2 parents dca7be4 + c2f9e66 commit 8aa3198
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
2 changes: 2 additions & 0 deletions src/Symbolics.jl
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ export lambertw
include("parsing.jl")
export parse_expr_to_symbolic

include("error_hints.jl")

# Hacks to make wrappers "nicer"
const NumberTypes = Union{AbstractFloat,Integer,Complex{<:AbstractFloat},Complex{<:Integer}}
(::Type{T})(x::SymbolicUtils.Symbolic) where {T<:NumberTypes} = throw(ArgumentError("Cannot convert Sym to $T since Sym is symbolic and $T is concrete. Use `substitute` to replace the symbolic unwraps."))
Expand Down
52 changes: 52 additions & 0 deletions src/error_hints.jl
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
const FLOAT_NUM_CONVERSION_ERROR = """
An implict conversion of symbolic Num into a Float64 was encountered. Common causes for this error include:
1. A substitution resulted in numerical values, but is not automatically converted to numerical values. For example:
```julia
@variables x y
result = [1.0]
A = [x x^2
y+x 2x + y]
sub = substitute(A, Dict([x=>2.0, y=>2]))
result[1] = sub[1]
```
The reason is because the result of `sub` is still symbolic:
```julia
julia> sub = substitute(A, Dict([x=>2.0, y=>2]))
2×2 Matrix{Num}:
2.0 4.0
4.0 6.0
```
Notice that the return is a `Matrix{Num}`, not a `Matrix{Float64}`. To fix this, ensure that the type is converted, i.e.
`sub = Symbolics.unwrap.(substitute(A, Dict([x=>2.0, y=>2])))`, or `result[1] = Symbolics.unwrap(sub[1])`.
2. Captured symbolic values inside of registered functions. An example of this version of the error is the following:
```julia
@variables x y
ff(x) = x + y
@register_symbolic ff(x)
result = [0.0]
result[1] = eval(build_function(ff(x),[x,y]))(1.0) # Error
```
Notice that the is the fact that the generated function call `eval(build_function(ff(x),x))(1.0)` returns a symbolic
value (`1.0 + y`), not a numerical value. This is because the value `y` is a global symbol enclosed into `ff`. To fix
this, ensure that any symbolic value that is used in registered functions is passed in, i.e. :
```julia
ff(x) = x + y
@register_symbolic ff(x)
```
"""

Base.Experimental.register_error_hint(MethodError) do io, e, args, kwargs
if e isa MethodError && Num in args && e.f <: Number
println(io, FLOAT_NUM_CONVERSION_ERROR)
end
end

0 comments on commit 8aa3198

Please sign in to comment.