Skip to content

Commit 1d53232

Browse files
authored
fix fieldtype vararg and union handling (JuliaLang#27059)
* fix fieldtype vararg and union handling * add tests
1 parent b9b4da5 commit 1d53232

4 files changed

Lines changed: 31 additions & 12 deletions

File tree

base/compiler/tfuncs.jl

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -620,8 +620,8 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
620620
if s0 === Any || s0 === Type || DataType s0 || UnionAll s0
621621
return Type
622622
end
623-
# fieldtype only accepts DataType and UnionAll, errors on `Module`
624-
if isa(s0,Const) && (!(isa(s0.val,DataType) || isa(s0.val,UnionAll)) || s0.val === Module)
623+
# fieldtype only accepts Types, errors on `Module`
624+
if isa(s0, Const) && (!(isa(s0.val, DataType) || isa(s0.val, UnionAll) || isa(s0.val, Union)) || s0.val === Module)
625625
return Bottom
626626
end
627627
if s0 == Type{Module} || s0 == Type{Union{}} || isa(s0, Conditional)
@@ -631,12 +631,12 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
631631
s = instanceof_tfunc(s0)[1]
632632
u = unwrap_unionall(s)
633633

634-
if isa(u,Union)
635-
return tmerge(rewrap(fieldtype_tfunc(u.a, name),s),
636-
rewrap(fieldtype_tfunc(u.b, name),s))
634+
if isa(u, Union)
635+
return tmerge(rewrap(fieldtype_tfunc(u.a, name), s),
636+
rewrap(fieldtype_tfunc(u.b, name), s))
637637
end
638638

639-
if !isa(u,DataType) || u.abstract
639+
if !isa(u, DataType) || u.abstract
640640
return Type
641641
end
642642
if u.name === _NAMEDTUPLE_NAME && !isconcretetype(u)
@@ -656,7 +656,7 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
656656
end
657657

658658
fld = name.val
659-
if isa(fld,Symbol)
659+
if isa(fld, Symbol)
660660
fld = fieldindex(u, fld, false)
661661
end
662662
if !isa(fld, Int)
@@ -672,7 +672,7 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
672672
end
673673

674674
exact = (isa(s0, Const) || isType(s0)) && !has_free_typevars(s)
675-
ft = rewrap_unionall(ft,s)
675+
ft = rewrap_unionall(ft, s)
676676
if exact
677677
return Const(ft)
678678
end

src/builtins.c

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -791,9 +791,19 @@ static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f)
791791
JL_GC_POP();
792792
return u;
793793
}
794+
if (jl_is_uniontype(t)) {
795+
jl_value_t **u;
796+
jl_value_t *r;
797+
JL_GC_PUSHARGS(u, 2);
798+
u[0] = get_fieldtype(((jl_uniontype_t*)t)->a, f);
799+
u[1] = get_fieldtype(((jl_uniontype_t*)t)->b, f);
800+
r = jl_type_union(u, 2);
801+
JL_GC_POP();
802+
return r;
803+
}
804+
if (!jl_is_datatype(t))
805+
jl_type_error("fieldtype", (jl_value_t*)jl_datatype_type, t);
794806
jl_datatype_t *st = (jl_datatype_t*)t;
795-
if (!jl_is_datatype(st))
796-
jl_type_error("fieldtype", (jl_value_t*)jl_datatype_type, (jl_value_t*)st);
797807
int field_index;
798808
if (jl_is_long(f)) {
799809
field_index = jl_unbox_long(f) - 1;

src/codegen.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2809,8 +2809,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
28092809
const jl_cgval_t &typ = argv[1];
28102810
const jl_cgval_t &fld = argv[2];
28112811
if ((jl_is_type_type(typ.typ) && jl_is_concrete_type(jl_tparam0(typ.typ))) ||
2812-
(typ.constant && jl_is_datatype(typ.constant)) ||
2813-
typ.typ == (jl_value_t*)jl_datatype_type) {
2812+
(typ.constant && jl_is_concrete_type(typ.constant))) {
28142813
if (fld.typ == (jl_value_t*)jl_long_type) {
28152814
assert(typ.isboxed);
28162815
Value *tyv = boxed(ctx, typ);

test/compiler/compiler.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1562,3 +1562,13 @@ for stmt in typed_code
15621562
end
15631563

15641564
@test found_well_typed_getfield_call
1565+
1566+
# 27059 fix fieldtype vararg and union handling
1567+
1568+
f27059(::Type{T}) where T = i -> fieldtype(T, i)
1569+
T27059 = Tuple{Float64,Vararg{Float32}}
1570+
@test f27059(T27059)(2) === fieldtype(T27059, 2) === Float32
1571+
@test f27059(Union{T27059,Tuple{Vararg{Symbol}}})(2) === Union{Float32,Symbol}
1572+
@test fieldtype(Union{Tuple{Int,Symbol},Tuple{Float64,String}}, 1) === Union{Int,Float64}
1573+
@test fieldtype(Union{Tuple{Int,Symbol},Tuple{Float64,String}}, 2) === Union{Symbol,String}
1574+
@test fieldtype(Union{Tuple{T,Symbol},Tuple{S,String}} where {T<:Number,S<:T}, 1) === Union{S,T} where {T<:Number,S<:T}

0 commit comments

Comments
 (0)