Skip to content

Commit 8aa3198

Browse files
Merge pull request #1001 from JuliaSymbolics/error_hint
Add error hint on implicit Float conversion from Num
2 parents dca7be4 + c2f9e66 commit 8aa3198

File tree

2 files changed

+54
-0
lines changed

2 files changed

+54
-0
lines changed

src/Symbolics.jl

+2
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,8 @@ export lambertw
143143
include("parsing.jl")
144144
export parse_expr_to_symbolic
145145

146+
include("error_hints.jl")
147+
146148
# Hacks to make wrappers "nicer"
147149
const NumberTypes = Union{AbstractFloat,Integer,Complex{<:AbstractFloat},Complex{<:Integer}}
148150
(::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."))

src/error_hints.jl

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
const FLOAT_NUM_CONVERSION_ERROR = """
2+
3+
An implict conversion of symbolic Num into a Float64 was encountered. Common causes for this error include:
4+
5+
1. A substitution resulted in numerical values, but is not automatically converted to numerical values. For example:
6+
7+
```julia
8+
@variables x y
9+
result = [1.0]
10+
A = [x x^2
11+
y+x 2x + y]
12+
sub = substitute(A, Dict([x=>2.0, y=>2]))
13+
result[1] = sub[1]
14+
```
15+
16+
The reason is because the result of `sub` is still symbolic:
17+
18+
```julia
19+
julia> sub = substitute(A, Dict([x=>2.0, y=>2]))
20+
2×2 Matrix{Num}:
21+
2.0 4.0
22+
4.0 6.0
23+
```
24+
25+
Notice that the return is a `Matrix{Num}`, not a `Matrix{Float64}`. To fix this, ensure that the type is converted, i.e.
26+
`sub = Symbolics.unwrap.(substitute(A, Dict([x=>2.0, y=>2])))`, or `result[1] = Symbolics.unwrap(sub[1])`.
27+
28+
2. Captured symbolic values inside of registered functions. An example of this version of the error is the following:
29+
30+
```julia
31+
@variables x y
32+
ff(x) = x + y
33+
@register_symbolic ff(x)
34+
result = [0.0]
35+
result[1] = eval(build_function(ff(x),[x,y]))(1.0) # Error
36+
```
37+
38+
Notice that the is the fact that the generated function call `eval(build_function(ff(x),x))(1.0)` returns a symbolic
39+
value (`1.0 + y`), not a numerical value. This is because the value `y` is a global symbol enclosed into `ff`. To fix
40+
this, ensure that any symbolic value that is used in registered functions is passed in, i.e. :
41+
42+
```julia
43+
ff(x) = x + y
44+
@register_symbolic ff(x)
45+
```
46+
"""
47+
48+
Base.Experimental.register_error_hint(MethodError) do io, e, args, kwargs
49+
if e isa MethodError && Num in args && e.f <: Number
50+
println(io, FLOAT_NUM_CONVERSION_ERROR)
51+
end
52+
end

0 commit comments

Comments
 (0)