@@ -141,16 +141,42 @@ end
141
141
# dx::AbstractArray (when both are possible), or the reverse. So for now we just pass them through:
142
142
(:: ProjectTo{T} )(dx:: Tangent{<:T} ) where {T} = dx
143
143
144
+ # ####
145
+ # #### A related utility which wants to live nearby
146
+ # ####
147
+
148
+ """
149
+ is_non_differentiable(x) == is_non_differentiable(typeof(x))
150
+
151
+ Returns `true` if `x` is known from its type not to have derivatives, else `false`.
152
+
153
+ Should mostly agree with whether `ProjectTo(x)` maps to `AbstractZero`,
154
+ which is what the fallback method checks. The exception is that it will not look
155
+ inside abstractly typed containers like `x = Any[true, false]`.
156
+ """
157
+ is_non_differentiable (x) = is_non_differentiable (typeof (x))
158
+
159
+ is_non_differentiable (:: Type{<:Number} ) = false
160
+ is_non_differentiable (:: Type{<:NTuple{N,T}} ) where {N,T} = is_non_differentiable (T)
161
+ is_non_differentiable (:: Type{<:AbstractArray{T}} ) where {T} = is_non_differentiable (T)
162
+
163
+ function is_non_differentiable (:: Type{T} ) where {T} # fallback
164
+ PT = Base. _return_type (ProjectTo, Tuple{T}) # might be Union{} if unstable
165
+ return isconcretetype (PT) && PT <: ProjectTo{<:AbstractZero}
166
+ end
167
+
144
168
# ####
145
169
# #### `Base`
146
170
# ####
147
171
148
172
# Bool
149
173
ProjectTo (:: Bool ) = ProjectTo {NoTangent} () # same projector as ProjectTo(::AbstractZero) above
174
+ is_non_differentiable (:: Type{Bool} ) = true
150
175
151
176
# Other never-differentiable types
152
177
for T in (:Symbol , :Char , :AbstractString , :RoundingMode , :IndexStyle )
153
178
@eval ProjectTo (:: $T ) = ProjectTo {NoTangent} ()
179
+ @eval is_non_differentiable (:: Type{<:$T} ) = true
154
180
end
155
181
156
182
# Numbers
0 commit comments