`tanh` rule in v1.74.11 fails on symbolic inputs ("non-boolean (Num) used in boolean context")

Open Beginner friendly
#871 1 comment 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

Nobody has claimed this yet.

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
72/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Domain
tooling

Research direction

The failing tanh rule is defined in src/rulesets/Base/fastmath_able.jl, where derivatives_given_output (around line 42) uses a ternary on abs(real(x)) < 1. Start by running the reproducer with Symbolics @variables x and frule((NoTangent(), true), tanh, x) to confirm the TypeError. Done means the symbolic call no longer throws, numeric results are unchanged, and the other rules changed in #864 have been checked for the same non-Bool condition.

Written by the indexing model from the issue text.

Description

Since v1.74.11 (#864), the tanh rule picks between two formulas with a ternary:

@scalar_rule tanh(x) abs(real(x)) < 1 ? 1 - Ω ^ 2 : sech(x) ^ 2

The ternary needs a Bool. For a symbolic x (e.g. Symbolics.Num), abs(real(x)) < 1 is a symbolic expression, so frule / derivatives_given_output throws.

Reproducer
using ChainRules, ChainRulesCore, Symbolics
@variables x
frule((NoTangent(), true), tanh, x)
ERROR: TypeError: non-boolean (Symbolics.Num) used in boolean context
Stacktrace:
 [1] derivatives_given_output(Ω::Num, ::typeof(tanh), x::Num)
   @ ChainRules ~/.julia/packages/ChainRules/.../src/rulesets/Base/fastmath_able.jl:42
 [2] frule(::Tuple{NoTangent, Bool}, ::typeof(tanh), x::Num)
   @ ChainRules ~/.julia/packages/ChainRules/.../src/rulesets/Base/fastmath_able.jl:42

The stack trace is from a CI failure in which TaylorDiff.jl hit this while precompiling (log). The snippet above reconstructs that call and hasn't been run on its own.

Impact

TaylorDiff.jl (v0.3.5) evaluates ChainRules rules on Symbolics variables while it precompiles, so it now fails to precompile. That in turn breaks everything that depends on it, e.g. NonlinearSolveHomotopyContinuation and the ModelingToolkit HomotopyContinuation extension tests. We see this in downstream CI: v1.74.10 passes, v1.74.11 and later fail, and v1.74.13 still has the ternary.

Suggested fix

Use ifelse instead of the ternary. Symbolics and similar packages overload it for symbolic conditions:

@scalar_rule tanh(x) ifelse(abs(real(x)) < 1, 1 - Ω ^ 2, sech(x) ^ 2)

ifelse always computes both branches, which costs one extra sech for ordinary numbers, but gives the same result. The other rules changed in #864 may be worth checking for the same problem with non-Bool comparisons.

(Diagnosed with the help of Claude Code.)

Dominant language
Julia
Stars
479
Forks
100
Avg merge
1d 4h
Merged PRs (30d)
14

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from JuliaDiff/ChainRules.jl

All issues in JuliaDiff/ChainRules.jl

Similar issues

More Julia issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.