@@ -302,52 +302,38 @@ promote_type(T) = T
302
302
promote_type (T, S, U) = (@inline ; promote_type (promote_type (T, S), U))
303
303
promote_type (T, S, U, V... ) = (@inline ; afoldl (promote_type, promote_type (T, S, U), V... ))
304
304
305
+ function _promote_type_binary (:: Type , :: Type , :: Tuple{} )
306
+ @noinline
307
+ s = " `promote_type`: recursion depth limit reached, giving up; check for faulty/conflicting/missing `promote_rule` methods"
308
+ throw (ArgumentError (s))
309
+ end
310
+ function _promote_type_binary (:: Type{Bottom} , :: Type{Bottom} , :: Tuple{Nothing,Vararg{Nothing}} )
311
+ Bottom
312
+ end
313
+ function _promote_type_binary (:: Type{T} , :: Type{T} , :: Tuple{Nothing,Vararg{Nothing}} ) where {T}
314
+ T
315
+ end
316
+ function _promote_type_binary (:: Type{T} , :: Type{Bottom} , :: Tuple{Nothing,Vararg{Nothing}} ) where {T}
317
+ T
318
+ end
319
+ function _promote_type_binary (:: Type{Bottom} , :: Type{T} , :: Tuple{Nothing,Vararg{Nothing}} ) where {T}
320
+ T
321
+ end
322
+ function _promote_type_binary (:: Type{T} , :: Type{S} , recursion_depth_limit:: Tuple{Nothing,Vararg{Nothing}} ) where {T,S}
323
+ # Try promote_rule in both orders.
324
+ promote_result (T, S, promote_rule (T,S), promote_rule (S,T), recursion_depth_limit)
325
+ end
326
+
327
+ const _promote_type_binary_recursion_depth_limit = ((nothing for _ in 1 : 28 ). .. ,) # recursion depth limit to prevent stack overflow
328
+
305
329
function promote_type (:: Type{T} , :: Type{S} ) where {T,S}
306
- @_terminates_locally_meta
307
- normalized_type (:: Type{Typ} ) where {Typ} = Typ
308
- types_are_equal (:: Type , :: Type ) = false
309
- types_are_equal (:: Type{Typ} , :: Type{Typ} ) where {Typ} = true
310
- is_bottom (:: Type ) = false
311
- is_bottom (:: Type{Bottom} ) = true
312
- function throw_conflicting_promote_rules ((@nospecialize i1:: Type ), (@nospecialize i2:: Type ), (@nospecialize left:: Type ), (@nospecialize right:: Type ))
313
- @noinline
314
- s = LazyString (" `promote_type(" , i1, " , " , i2, " )` failed, there are conflicting `promote_rule` definitions for types " , left, " , " , right)
315
- throw (ArgumentError (s))
316
- end
317
- function throw_gave_up ((@nospecialize i1:: Type ), (@nospecialize i2:: Type ), (@nospecialize left:: Type ), (@nospecialize right:: Type ))
318
- @noinline
319
- s = LazyString (" `promote_type(" , i1, " , " , i2, " )` failed, ended up with (" , left, " , " , right, " ), check for faulty `promote_rule` methods" )
320
- throw (ArgumentError (s))
321
- end
322
- left = T
323
- right = S
324
- for _ ∈ 1 : 1000 # guarantee local termination
325
- if types_are_equal (left, right) || is_bottom (left) || is_bottom (right)
326
- break
327
- end
328
- # Try `promote_rule` in both orders.
329
- a = normalized_type (promote_rule (left, right))
330
- b = normalized_type (promote_rule (right, left))
331
- loop_is_detected_1 = types_are_equal (left, a) && types_are_equal (right, b)
332
- loop_is_detected_2 = types_are_equal (left, b) && types_are_equal (right, a)
333
- if loop_is_detected_1 || loop_is_detected_2
334
- throw_conflicting_promote_rules (T, S, left, right)
335
- end
336
- if is_bottom (a) && is_bottom (b)
337
- # If no `promote_rule` is defined, both directions give `Bottom`. In that
338
- # case use `typejoin` on the original types.
339
- return typejoin (left, right)
340
- end
341
- left = a
342
- right = b
343
- end
344
- if types_are_equal (left, right) || is_bottom (left)
345
- right
346
- elseif is_bottom (right)
347
- left
348
- else
349
- throw_gave_up (T, S, left, right)
350
- end
330
+ @inline
331
+ # Try promote_rule in both orders. Typically only one is defined,
332
+ # and there is a fallback returning Bottom below, so the common case is
333
+ # promote_type(T, S) =>
334
+ # promote_result(T, S, result, Bottom) =>
335
+ # typejoin(result, Bottom) => result
336
+ _promote_type_binary (T, S, _promote_type_binary_recursion_depth_limit)
351
337
end
352
338
353
339
"""
@@ -367,6 +353,11 @@ promote_rule(::Type{Bottom}, ::Type{Bottom}, slurp...) = Bottom # not strictly n
367
353
promote_rule (:: Type{Bottom} , :: Type{T} , slurp... ) where {T} = T
368
354
promote_rule (:: Type{T} , :: Type{Bottom} , slurp... ) where {T} = T
369
355
356
+ promote_result (:: Type ,:: Type ,:: Type{T} ,:: Type{S} ,l:: Tuple{Vararg{Nothing}} ) where {T,S} = (@inline ; _promote_type_binary (T,S,l))
357
+ # If no promote_rule is defined, both directions give Bottom. In that
358
+ # case use typejoin on the original types instead.
359
+ promote_result (:: Type{T} ,:: Type{S} ,:: Type{Bottom} ,:: Type{Bottom} ,:: Tuple{Vararg{Nothing}} ) where {T,S} = (@inline ; typejoin (T, S))
360
+
370
361
"""
371
362
promote(xs...)
372
363
0 commit comments