Skip to content

Commit

Permalink
fix fieldtype vararg and union handling (JuliaLang#27059)
Browse files Browse the repository at this point in the history
* fix fieldtype vararg and union handling

* add tests
  • Loading branch information
jrevels committed May 11, 2018
1 parent b9b4da5 commit 1d53232
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 12 deletions.
16 changes: 8 additions & 8 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,8 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
if s0 === Any || s0 === Type || DataType s0 || UnionAll s0
return Type
end
# fieldtype only accepts DataType and UnionAll, errors on `Module`
if isa(s0,Const) && (!(isa(s0.val,DataType) || isa(s0.val,UnionAll)) || s0.val === Module)
# fieldtype only accepts Types, errors on `Module`
if isa(s0, Const) && (!(isa(s0.val, DataType) || isa(s0.val, UnionAll) || isa(s0.val, Union)) || s0.val === Module)
return Bottom
end
if s0 == Type{Module} || s0 == Type{Union{}} || isa(s0, Conditional)
Expand All @@ -631,12 +631,12 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
s = instanceof_tfunc(s0)[1]
u = unwrap_unionall(s)

if isa(u,Union)
return tmerge(rewrap(fieldtype_tfunc(u.a, name),s),
rewrap(fieldtype_tfunc(u.b, name),s))
if isa(u, Union)
return tmerge(rewrap(fieldtype_tfunc(u.a, name), s),
rewrap(fieldtype_tfunc(u.b, name), s))
end

if !isa(u,DataType) || u.abstract
if !isa(u, DataType) || u.abstract
return Type
end
if u.name === _NAMEDTUPLE_NAME && !isconcretetype(u)
Expand All @@ -656,7 +656,7 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
end

fld = name.val
if isa(fld,Symbol)
if isa(fld, Symbol)
fld = fieldindex(u, fld, false)
end
if !isa(fld, Int)
Expand All @@ -672,7 +672,7 @@ function fieldtype_tfunc(@nospecialize(s0), @nospecialize(name))
end

exact = (isa(s0, Const) || isType(s0)) && !has_free_typevars(s)
ft = rewrap_unionall(ft,s)
ft = rewrap_unionall(ft, s)
if exact
return Const(ft)
end
Expand Down
14 changes: 12 additions & 2 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -791,9 +791,19 @@ static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f)
JL_GC_POP();
return u;
}
if (jl_is_uniontype(t)) {
jl_value_t **u;
jl_value_t *r;
JL_GC_PUSHARGS(u, 2);
u[0] = get_fieldtype(((jl_uniontype_t*)t)->a, f);
u[1] = get_fieldtype(((jl_uniontype_t*)t)->b, f);
r = jl_type_union(u, 2);
JL_GC_POP();
return r;
}
if (!jl_is_datatype(t))
jl_type_error("fieldtype", (jl_value_t*)jl_datatype_type, t);
jl_datatype_t *st = (jl_datatype_t*)t;
if (!jl_is_datatype(st))
jl_type_error("fieldtype", (jl_value_t*)jl_datatype_type, (jl_value_t*)st);
int field_index;
if (jl_is_long(f)) {
field_index = jl_unbox_long(f) - 1;
Expand Down
3 changes: 1 addition & 2 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2809,8 +2809,7 @@ static bool emit_builtin_call(jl_codectx_t &ctx, jl_cgval_t *ret, jl_value_t *f,
const jl_cgval_t &typ = argv[1];
const jl_cgval_t &fld = argv[2];
if ((jl_is_type_type(typ.typ) && jl_is_concrete_type(jl_tparam0(typ.typ))) ||
(typ.constant && jl_is_datatype(typ.constant)) ||
typ.typ == (jl_value_t*)jl_datatype_type) {
(typ.constant && jl_is_concrete_type(typ.constant))) {
if (fld.typ == (jl_value_t*)jl_long_type) {
assert(typ.isboxed);
Value *tyv = boxed(ctx, typ);
Expand Down
10 changes: 10 additions & 0 deletions test/compiler/compiler.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1562,3 +1562,13 @@ for stmt in typed_code
end

@test found_well_typed_getfield_call

# 27059 fix fieldtype vararg and union handling

f27059(::Type{T}) where T = i -> fieldtype(T, i)
T27059 = Tuple{Float64,Vararg{Float32}}
@test f27059(T27059)(2) === fieldtype(T27059, 2) === Float32
@test f27059(Union{T27059,Tuple{Vararg{Symbol}}})(2) === Union{Float32,Symbol}
@test fieldtype(Union{Tuple{Int,Symbol},Tuple{Float64,String}}, 1) === Union{Int,Float64}
@test fieldtype(Union{Tuple{Int,Symbol},Tuple{Float64,String}}, 2) === Union{Symbol,String}
@test fieldtype(Union{Tuple{T,Symbol},Tuple{S,String}} where {T<:Number,S<:T}, 1) === Union{S,T} where {T<:Number,S<:T}

0 comments on commit 1d53232

Please sign in to comment.