@@ -282,32 +282,27 @@ end
282
282
@inline broadcast_elwise_op (f, As... ) =
283
283
broadcast! (f, similar (Array{promote_eltype_op (f, As... )}, broadcast_indices (As... )), As... )
284
284
285
- ftype (f, A) = typeof (f)
286
- ftype (f, A... ) = typeof (a -> f (a... ))
287
- ftype (T:: Type , A... ) = Type{T}
288
285
289
- # nullables need to be treated like scalars sometimes and like containers
290
- # other times, so there are two variants of typestuple.
286
+ # _broadcast_eltype is broadcast's primary result-eltype promotion mechanism.
287
+ # _broadcast_eltype uses eltypestuple to construct a tuple type of the eltypes
288
+ # of the input-array arguments passed to _broadcast_eltype (from an upstream broacast).
289
+ _broadcast_eltype {S} (:: Type{S} , f, As... ) = Base. _return_type (f, eltypestuple (S, As... ))
290
+ _broadcast_eltype {S} (:: Type{S} , f, T:: Type , As... ) = Base. _return_type (f, eltypestuple (S, T, As... )) # 19419 workaround
291
+ eltypestuple (:: Type , a) = (Base. @_pure_meta ; Tuple{eltype (a)})
292
+ eltypestuple (:: Type , T:: Type ) = (Base. @_pure_meta ; Tuple{Type{T}})
293
+ eltypestuple {S} (:: Type{S} , a, b... ) = (Base. @_pure_meta ; Tuple{eltypestuple (S, a). types... , eltypestuple (S, b... ). types... })
294
+ # nullables need special handling: in some cases they behave like scalars, and in others
295
+ # like containers. _broadcast_eltype and eltypestuple presently handles this via its first
296
+ # (type) argument, through which callers provide the context in which the nullable
297
+ # input-argument appears (and hence how it should be treated). specifically, if the
298
+ # first argument is Any, then nullables are treated as scalars, whereas otherwise
299
+ # (i.e. if the first argument is not Any), then nullables are treated as containers.
300
+ eltypestuple (:: Type{Any} , a:: Nullable ) = (Base. @_pure_meta ; Tuple{typeof (a)})
291
301
292
- # if the first argument is Any, then Nullable should be treated like a
293
- # scalar; if the first argument is Array, then Nullable should be treated
294
- # like a container.
295
- typestuple (:: Type , a) = (Base. @_pure_meta ; Tuple{eltype (a)})
296
- typestuple (:: Type{Any} , a:: Nullable ) = (Base. @_pure_meta ; Tuple{typeof (a)})
297
- typestuple (:: Type , T:: Type ) = (Base. @_pure_meta ; Tuple{Type{T}})
298
- typestuple {T} (:: Type{T} , a, b... ) = (Base. @_pure_meta ; Tuple{typestuple (T, a). types... , typestuple (T, b... ). types... })
299
-
300
- # these functions take the variant of typestuple to be used as first argument
301
- ziptype {T} (:: Type{T} , A) = typestuple (T, A)
302
- ziptype {T} (:: Type{T} , A, B) = (Base. @_pure_meta ; Iterators. Zip2{typestuple (T, A), typestuple (T, B)})
303
- @inline ziptype {T} (:: Type{T} , A, B, C, D... ) = Iterators. Zip{typestuple (T, A), ziptype (T, B, C, D... )}
304
-
305
- _broadcast_type {S} (:: Type{S} , f, T:: Type , As... ) = Base. _return_type (f, typestuple (S, T, As... ))
306
- _broadcast_type {T} (:: Type{T} , f, A, Bs... ) = Base. _default_eltype (Base. Generator{ziptype (T, A, Bs... ), ftype (f, A, Bs... )})
307
302
308
303
# broadcast methods that dispatch on the type of the final container
309
304
@inline function broadcast_c (f, :: Type{Array} , A, Bs... )
310
- T = _broadcast_type (Any, f, A, Bs... )
305
+ T = _broadcast_eltype (Any, f, A, Bs... )
311
306
shape = broadcast_indices (A, Bs... )
312
307
iter = CartesianRange (shape)
313
308
if isleaftype (T)
@@ -332,7 +327,7 @@ function broadcast_c(f, ::Type{Tuple}, As...)
332
327
end
333
328
@inline function broadcast_c (f, :: Type{Nullable} , a... )
334
329
nonnull = all (hasvalue, a)
335
- S = _broadcast_type (Array, f, a... )
330
+ S = _broadcast_eltype (Array, f, a... )
336
331
if isleaftype (S) && null_safe_eltype_op (f, a... )
337
332
Nullable {S} (f (map (unsafe_get, a)... ), nonnull)
338
333
else
0 commit comments