Skip to content

Commit c02e900

Browse files
committed
remove fallback constructor from Core.Inference
Instead, define explicit constructors for built-in integer types in boot.jl.
1 parent 5fd053f commit c02e900

File tree

5 files changed

+172
-62
lines changed

5 files changed

+172
-62
lines changed

base/array.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -449,7 +449,7 @@ for (fname, felt) in ((:zeros,:zero), (:ones,:one))
449449
$fname(a::AbstractArray, T::Type, dims...) = fill!(similar(a,T,dims...), $felt(T))
450450
$fname(a::AbstractArray, T::Type=eltype(a)) = fill!(similar(a,T), $felt(T))
451451

452-
$fname(T::Type, dims::Tuple) = fill!(Array{T}(Dims(dims)), $felt(T))
452+
$fname(T::Type, dims::Tuple) = fill!(Array{T}(convert(Dims, dims)::Dims), $felt(T))
453453
$fname(dims::Tuple) = ($fname)(Float64, dims)
454454
$fname(T::Type, dims...) = $fname(T, dims)
455455
$fname(dims...) = $fname(dims)

base/boot.jl

Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,10 @@ mutable struct ErrorException <: Exception
200200
ErrorException(msg::AbstractString) = new(msg)
201201
end
202202

203+
macro _inline_meta()
204+
Expr(:meta, :inline)
205+
end
206+
203207
macro _noinline_meta()
204208
Expr(:meta, :noinline)
205209
end
@@ -437,4 +441,167 @@ show(@nospecialize a) = show(STDOUT, a)
437441
print(@nospecialize a...) = print(STDOUT, a...)
438442
println(@nospecialize a...) = println(STDOUT, a...)
439443

444+
# constructors for built-in types
445+
446+
import .Intrinsics: eq_int, trunc_int, lshr_int, sub_int, shl_int, bitcast, sext_int, zext_int, and_int
447+
448+
throw_inexacterror(f::Symbol, T::Type, val) = (@_noinline_meta; throw(InexactError(f, T, val)))
449+
450+
function is_top_bit_set(x)
451+
@_inline_meta
452+
eq_int(trunc_int(Int8, lshr_int(x, sub_int(shl_int(sizeof(x), 3), 1))), trunc_int(Int8, 1))
453+
end
454+
455+
function check_top_bit(x)
456+
@_inline_meta
457+
is_top_bit_set(x) && throw_inexacterror(:check_top_bit, typeof(x), x)
458+
x
459+
end
460+
461+
function checked_trunc_sint(::Type{To}, x::From) where {To,From}
462+
@_inline_meta
463+
y = trunc_int(To, x)
464+
back = sext_int(From, y)
465+
eq_int(x, back) || throw_inexacterror(:trunc, To, x)
466+
y
467+
end
468+
469+
function checked_trunc_uint(::Type{To}, x::From) where {To,From}
470+
@_inline_meta
471+
y = trunc_int(To, x)
472+
back = zext_int(From, y)
473+
eq_int(x, back) || throw_inexacterror(:trunc, To, x)
474+
y
475+
end
476+
477+
toInt8(x::Int8) = x
478+
toInt8(x::Int16) = checked_trunc_sint(Int8, x)
479+
toInt8(x::Int32) = checked_trunc_sint(Int8, x)
480+
toInt8(x::Int64) = checked_trunc_sint(Int8, x)
481+
toInt8(x::Int128) = checked_trunc_sint(Int8, x)
482+
toInt8(x::UInt8) = bitcast(Int8, check_top_bit(x))
483+
toInt8(x::UInt16) = checked_trunc_sint(Int8, check_top_bit(x))
484+
toInt8(x::UInt32) = checked_trunc_sint(Int8, check_top_bit(x))
485+
toInt8(x::UInt64) = checked_trunc_sint(Int8, check_top_bit(x))
486+
toInt8(x::UInt128) = checked_trunc_sint(Int8, check_top_bit(x))
487+
toInt8(x::Bool) = and_int(zext_int(Int8, x), Int8(1))
488+
toInt16(x::Int8) = sext_int(Int16, x)
489+
toInt16(x::Int16) = x
490+
toInt16(x::Int32) = checked_trunc_sint(Int16, x)
491+
toInt16(x::Int64) = checked_trunc_sint(Int16, x)
492+
toInt16(x::Int128) = checked_trunc_sint(Int16, x)
493+
toInt16(x::UInt8) = zext_int(Int16, x)
494+
toInt16(x::UInt16) = bitcast(Int16, check_top_bit(x))
495+
toInt16(x::UInt32) = checked_trunc_sint(Int16, check_top_bit(x))
496+
toInt16(x::UInt64) = checked_trunc_sint(Int16, check_top_bit(x))
497+
toInt16(x::UInt128) = checked_trunc_sint(Int16, check_top_bit(x))
498+
toInt16(x::Bool) = and_int(zext_int(Int16, x), Int16(1))
499+
toInt32(x::Int8) = sext_int(Int32, x)
500+
toInt32(x::Int16) = sext_int(Int32, x)
501+
toInt32(x::Int32) = x
502+
toInt32(x::Int64) = checked_trunc_sint(Int32, x)
503+
toInt32(x::Int128) = checked_trunc_sint(Int32, x)
504+
toInt32(x::UInt8) = zext_int(Int32, x)
505+
toInt32(x::UInt16) = zext_int(Int32, x)
506+
toInt32(x::UInt32) = bitcast(Int32, check_top_bit(x))
507+
toInt32(x::UInt64) = checked_trunc_sint(Int32, check_top_bit(x))
508+
toInt32(x::UInt128) = checked_trunc_sint(Int32, check_top_bit(x))
509+
toInt32(x::Bool) = and_int(zext_int(Int32, x), Int32(1))
510+
toInt64(x::Int8) = sext_int(Int64, x)
511+
toInt64(x::Int16) = sext_int(Int64, x)
512+
toInt64(x::Int32) = sext_int(Int64, x)
513+
toInt64(x::Int64) = x
514+
toInt64(x::Int128) = checked_trunc_sint(Int64, x)
515+
toInt64(x::UInt8) = zext_int(Int64, x)
516+
toInt64(x::UInt16) = zext_int(Int64, x)
517+
toInt64(x::UInt32) = zext_int(Int64, x)
518+
toInt64(x::UInt64) = bitcast(Int64, check_top_bit(x))
519+
toInt64(x::UInt128) = checked_trunc_sint(Int64, check_top_bit(x))
520+
toInt64(x::Bool) = and_int(zext_int(Int64, x), Int64(1))
521+
toInt128(x::Int8) = sext_int(Int128, x)
522+
toInt128(x::Int16) = sext_int(Int128, x)
523+
toInt128(x::Int32) = sext_int(Int128, x)
524+
toInt128(x::Int64) = sext_int(Int128, x)
525+
toInt128(x::Int128) = x
526+
toInt128(x::UInt8) = zext_int(Int128, x)
527+
toInt128(x::UInt16) = zext_int(Int128, x)
528+
toInt128(x::UInt32) = zext_int(Int128, x)
529+
toInt128(x::UInt64) = zext_int(Int128, x)
530+
toInt128(x::UInt128) = bitcast(Int128, check_top_bit(x))
531+
toInt128(x::Bool) = and_int(zext_int(Int128, x), Int128(1))
532+
toUInt8(x::Int8) = bitcast(UInt8, check_top_bit(x))
533+
toUInt8(x::Int16) = checked_trunc_uint(UInt8, x)
534+
toUInt8(x::Int32) = checked_trunc_uint(UInt8, x)
535+
toUInt8(x::Int64) = checked_trunc_uint(UInt8, x)
536+
toUInt8(x::Int128) = checked_trunc_uint(UInt8, x)
537+
toUInt8(x::UInt8) = x
538+
toUInt8(x::UInt16) = checked_trunc_uint(UInt8, x)
539+
toUInt8(x::UInt32) = checked_trunc_uint(UInt8, x)
540+
toUInt8(x::UInt64) = checked_trunc_uint(UInt8, x)
541+
toUInt8(x::UInt128) = checked_trunc_uint(UInt8, x)
542+
toUInt8(x::Bool) = and_int(zext_int(UInt8, x), UInt8(1))
543+
toUInt16(x::Int8) = sext_int(UInt16, check_top_bit(x))
544+
toUInt16(x::Int16) = bitcast(UInt16, check_top_bit(x))
545+
toUInt16(x::Int32) = checked_trunc_uint(UInt16, x)
546+
toUInt16(x::Int64) = checked_trunc_uint(UInt16, x)
547+
toUInt16(x::Int128) = checked_trunc_uint(UInt16, x)
548+
toUInt16(x::UInt8) = zext_int(UInt16, x)
549+
toUInt16(x::UInt16) = x
550+
toUInt16(x::UInt32) = checked_trunc_uint(UInt16, x)
551+
toUInt16(x::UInt64) = checked_trunc_uint(UInt16, x)
552+
toUInt16(x::UInt128) = checked_trunc_uint(UInt16, x)
553+
toUInt16(x::Bool) = and_int(zext_int(UInt16, x), UInt16(1))
554+
toUInt32(x::Int8) = sext_int(UInt32, check_top_bit(x))
555+
toUInt32(x::Int16) = sext_int(UInt32, check_top_bit(x))
556+
toUInt32(x::Int32) = bitcast(UInt32, check_top_bit(x))
557+
toUInt32(x::Int64) = checked_trunc_uint(UInt32, x)
558+
toUInt32(x::Int128) = checked_trunc_uint(UInt32, x)
559+
toUInt32(x::UInt8) = zext_int(UInt32, x)
560+
toUInt32(x::UInt16) = zext_int(UInt32, x)
561+
toUInt32(x::UInt32) = x
562+
toUInt32(x::UInt64) = checked_trunc_uint(UInt32, x)
563+
toUInt32(x::UInt128) = checked_trunc_uint(UInt32, x)
564+
toUInt32(x::Bool) = and_int(zext_int(UInt32, x), UInt32(1))
565+
toUInt64(x::Int8) = sext_int(UInt64, check_top_bit(x))
566+
toUInt64(x::Int16) = sext_int(UInt64, check_top_bit(x))
567+
toUInt64(x::Int32) = sext_int(UInt64, check_top_bit(x))
568+
toUInt64(x::Int64) = bitcast(UInt64, check_top_bit(x))
569+
toUInt64(x::Int128) = checked_trunc_uint(UInt64, x)
570+
toUInt64(x::UInt8) = zext_int(UInt64, x)
571+
toUInt64(x::UInt16) = zext_int(UInt64, x)
572+
toUInt64(x::UInt32) = zext_int(UInt64, x)
573+
toUInt64(x::UInt64) = x
574+
toUInt64(x::UInt128) = checked_trunc_uint(UInt64, x)
575+
toUInt64(x::Bool) = and_int(zext_int(UInt64, x), UInt64(1))
576+
toUInt128(x::Int8) = sext_int(UInt128, check_top_bit(x))
577+
toUInt128(x::Int16) = sext_int(UInt128, check_top_bit(x))
578+
toUInt128(x::Int32) = sext_int(UInt128, check_top_bit(x))
579+
toUInt128(x::Int64) = sext_int(UInt128, check_top_bit(x))
580+
toUInt128(x::Int128) = bitcast(UInt128, check_top_bit(x))
581+
toUInt128(x::UInt8) = zext_int(UInt128, x)
582+
toUInt128(x::UInt16) = zext_int(UInt128, x)
583+
toUInt128(x::UInt32) = zext_int(UInt128, x)
584+
toUInt128(x::UInt64) = zext_int(UInt128, x)
585+
toUInt128(x::UInt128) = x
586+
toUInt128(x::Bool) = and_int(zext_int(UInt128, x), UInt128(1))
587+
588+
# TODO: this is here to work around the 4 method limit in inference (#23210).
589+
const BuiltinInts = Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8, Bool}
590+
Int8(x::BuiltinInts) = toInt8(x)::Int8
591+
Int16(x::BuiltinInts) = toInt16(x)::Int16
592+
Int32(x::BuiltinInts) = toInt32(x)::Int32
593+
Int64(x::BuiltinInts) = toInt64(x)::Int64
594+
Int128(x::BuiltinInts) = toInt128(x)::Int128
595+
UInt8(x::BuiltinInts) = toUInt8(x)::UInt8
596+
UInt16(x::BuiltinInts) = toUInt16(x)::UInt16
597+
UInt32(x::BuiltinInts) = toUInt32(x)::UInt32
598+
UInt64(x::BuiltinInts) = toUInt64(x)::UInt64
599+
UInt128(x::BuiltinInts) = toUInt128(x)::UInt128
600+
601+
Bool(x::Bool) = x
602+
603+
Int(x::Ptr) = bitcast(Int, x)
604+
UInt(x::Ptr) = bitcast(UInt, x)
605+
Ptr{T}(x::Union{Int,UInt,Ptr}) where {T} = bitcast(Ptr{T}, x)
606+
440607
ccall(:jl_set_istopmod, Void, (Any, Bool), Core, true)

base/coreimg.jl

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,6 @@ eval(m, x) = Core.eval(m, x)
1212
include(x) = Core.include(Inference, x)
1313
include(mod, x) = Core.include(mod, x)
1414

15-
# conditional to allow redefining Core.Inference after base exists
16-
isdefined(Main, :Base) || ((::Type{T})(arg) where {T} = convert(T, arg)::T)
17-
1815
function return_type end
1916

2017
## Load essential files and libraries

base/int.jl

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -31,8 +31,8 @@ const BitUnsigned64T = Union{Type{UInt8}, Type{UInt16}, Type{UInt32}, Type{UIn
3131

3232
const BitIntegerType = Union{map(T->Type{T}, BitInteger_types)...}
3333

34-
throw_inexacterror(f::Symbol, ::Type{T}, val) where T =
35-
(@_noinline_meta; throw(InexactError(f, T, val)))
34+
# calls constructors defined in boot.jl
35+
convert(T::BitIntegerType, x::Union{BitInteger, Bool}) = T(x)
3636

3737
## integer comparisons ##
3838

@@ -420,75 +420,19 @@ trailing_ones(x::Integer) = trailing_zeros(~x)
420420
>>>(x::BitInteger, y::Int) =
421421
select_value(0 <= y, x >>> unsigned(y), x << unsigned(-y))
422422

423-
function is_top_bit_set(x::BitInteger)
424-
@_inline_meta
425-
lshr_int(x, (sizeof(x) << 0x03) - 1) == rem(0x01, typeof(x))
426-
end
427-
function check_top_bit(x::BitInteger)
428-
@_inline_meta
429-
is_top_bit_set(x) && throw_inexacterror(:check_top_bit, typeof(x), x)
430-
x
431-
end
432-
433-
## integer conversions ##
434-
435-
function checked_trunc_sint(::Type{To}, x::From) where {To,From}
436-
@_inline_meta
437-
y = trunc_int(To, x)
438-
back = sext_int(From, y)
439-
x == back || throw_inexacterror(:trunc, To, x)
440-
y
441-
end
442-
443-
function checked_trunc_uint(::Type{To}, x::From) where {To,From}
444-
@_inline_meta
445-
y = trunc_int(To, x)
446-
back = zext_int(From, y)
447-
x == back || throw_inexacterror(:trunc, To, x)
448-
y
449-
end
450-
451423
for to in BitInteger_types, from in (BitInteger_types..., Bool)
452424
if !(to === from)
453425
if to.size < from.size
454-
if to <: Signed
455-
if from <: Unsigned
456-
@eval convert(::Type{$to}, x::($from)) =
457-
checked_trunc_sint($to, check_top_bit(x))
458-
else
459-
@eval convert(::Type{$to}, x::($from)) =
460-
checked_trunc_sint($to, x)
461-
end
462-
else
463-
@eval convert(::Type{$to}, x::($from)) =
464-
checked_trunc_uint($to, x)
465-
end
466426
@eval rem(x::($from), ::Type{$to}) = trunc_int($to, x)
467427
elseif from === Bool
468-
# Bools use i8 storage and may have garbage in their 7 high bits
469-
@eval convert(::Type{$to}, x::($from)) = zext_int($to, x) & $to(1)
470428
@eval rem(x::($from), ::Type{$to}) = convert($to, x)
471429
elseif from.size < to.size
472430
if from <: Signed
473-
if to <: Unsigned
474-
@eval convert(::Type{$to}, x::($from)) =
475-
sext_int($to, check_top_bit(x))
476-
else
477-
@eval convert(::Type{$to}, x::($from)) =
478-
sext_int($to, x)
479-
end
480431
@eval rem(x::($from), ::Type{$to}) = sext_int($to, x)
481432
else
482-
@eval convert(::Type{$to}, x::($from)) = zext_int($to, x)
483433
@eval rem(x::($from), ::Type{$to}) = convert($to, x)
484434
end
485435
else
486-
if !((from <: Signed) === (to <: Signed))
487-
# raise InexactError if x's top bit is set
488-
@eval convert(::Type{$to}, x::($from)) = bitcast($to, check_top_bit(x))
489-
else
490-
@eval convert(::Type{$to}, x::($from)) = bitcast($to, x)
491-
end
492436
@eval rem(x::($from), ::Type{$to}) = bitcast($to, x)
493437
end
494438
end

src/jltypes.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -403,6 +403,8 @@ static void flatten_type_union(jl_value_t **types, size_t n, jl_value_t **out, s
403403

404404
STATIC_INLINE const char *datatype_module_name(jl_value_t *t)
405405
{
406+
if (((jl_datatype_t*)t)->name->module == NULL)
407+
return NULL;
406408
return jl_symbol_name(((jl_datatype_t*)t)->name->module->name);
407409
}
408410

0 commit comments

Comments
 (0)