Skip to content

Commit

Permalink
Merge branch 'master' into jb/splatnew
Browse files Browse the repository at this point in the history
  • Loading branch information
JeffBezanson authored Jan 4, 2019
2 parents 10ebb97 + cf404cf commit b45cfda
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 12 deletions.
7 changes: 6 additions & 1 deletion base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -789,14 +789,19 @@ function fieldtype_nothrow(@nospecialize(s0), @nospecialize(name))
return false
end

su = unwrap_unionall(s0)
if isa(su, Union)
return fieldtype_nothrow(rewrap_unionall(su.a, s0), name) && fieldtype_nothrow(rewrap_unionall(su.b, s0), name)
end

s = instanceof_tfunc(s0)[1]
u = unwrap_unionall(s)
return _fieldtype_nothrow(u, name)
end

function _fieldtype_nothrow(@nospecialize(u), name::Const)
if isa(u, Union)
return _fieldtype_nothrow(u.a, name) && _fieldtype_nothrow(u.b, name)
return _fieldtype_nothrow(u.a, name) || _fieldtype_nothrow(u.b, name)
end
fld = name.val
if isa(fld, Symbol)
Expand Down
37 changes: 26 additions & 11 deletions src/builtins.c
Original file line number Diff line number Diff line change
Expand Up @@ -699,12 +699,12 @@ JL_CALLABLE(jl_f_setfield)
return args[2];
}

static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f)
static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f, int dothrow)
{
if (jl_is_unionall(t)) {
jl_value_t *u = t;
JL_GC_PUSH1(&u);
u = get_fieldtype(((jl_unionall_t*)t)->body, f);
u = get_fieldtype(((jl_unionall_t*)t)->body, f, dothrow);
u = jl_type_unionall(((jl_unionall_t*)t)->var, u);
JL_GC_POP();
return u;
Expand All @@ -713,8 +713,13 @@ static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f)
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);
u[0] = get_fieldtype(((jl_uniontype_t*)t)->a, f, 0);
u[1] = get_fieldtype(((jl_uniontype_t*)t)->b, f, 0);
if (u[0] == jl_bottom_type && u[1] == jl_bottom_type && dothrow) {
// error if all types in the union might have
get_fieldtype(((jl_uniontype_t*)t)->a, f, 1);
get_fieldtype(((jl_uniontype_t*)t)->b, f, 1);
}
r = jl_type_union(u, 2);
JL_GC_POP();
return r;
Expand All @@ -729,28 +734,38 @@ static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f)
jl_value_t *nm = jl_tparam0(st);
if (jl_is_tuple(nm)) {
int nf = jl_nfields(nm);
if (field_index < 0 || field_index >= nf)
jl_bounds_error(t, f);
if (field_index < 0 || field_index >= nf) {
if (dothrow)
jl_bounds_error(t, f);
else
return jl_bottom_type;
}
}
jl_value_t *tt = jl_tparam1(st);
while (jl_is_typevar(tt))
tt = ((jl_tvar_t*)tt)->ub;
if (tt == (jl_value_t*)jl_any_type)
return (jl_value_t*)jl_any_type;
return get_fieldtype(tt, f);
return get_fieldtype(tt, f, dothrow);
}
int nf = jl_field_count(st);
if (nf > 0 && field_index >= nf-1 && st->name == jl_tuple_typename) {
jl_value_t *ft = jl_field_type(st, nf-1);
if (jl_is_vararg_type(ft))
return jl_unwrap_vararg(ft);
}
if (field_index < 0 || field_index >= nf)
jl_bounds_error(t, f);
if (field_index < 0 || field_index >= nf) {
if (dothrow)
jl_bounds_error(t, f);
else
return jl_bottom_type;
}
}
else {
JL_TYPECHK(fieldtype, symbol, f);
field_index = jl_field_index(st, (jl_sym_t*)f, 1);
field_index = jl_field_index(st, (jl_sym_t*)f, dothrow);
if (field_index == -1)
return jl_bottom_type;
}
return jl_field_type(st, field_index);
}
Expand All @@ -765,7 +780,7 @@ JL_CALLABLE(jl_f_fieldtype)
jl_datatype_t *st = (jl_datatype_t*)args[0];
if (st == jl_module_type)
jl_error("cannot assign variables in other modules");
return get_fieldtype(args[0], args[1]);
return get_fieldtype(args[0], args[1], 1);
}

JL_CALLABLE(jl_f_nfields)
Expand Down
2 changes: 2 additions & 0 deletions src/codegen.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4066,6 +4066,8 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
}
Value *typ = boxed(ctx, argv[0]);
Value *val = emit_jlcall(ctx, jlnew_func, typ, &argv[1], nargs - 1);
// temporarily mark as `Any`, expecting `emit_ssaval_assign` to update
// it to the inferred type.
return mark_julia_type(ctx, val, true, (jl_value_t*)jl_any_type);
}
else if (head == splatnew_sym) {
Expand Down
3 changes: 3 additions & 0 deletions test/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -234,6 +234,9 @@ tlayout = TLayout(5,7,11)
@test fieldtype(Tuple{Vararg{Int8}}, 1) === Int8
@test fieldtype(Tuple{Vararg{Int8}}, 10) === Int8
@test_throws BoundsError fieldtype(Tuple{Vararg{Int8}}, 0)
# issue #30505
@test fieldtype(Union{Tuple{Char},Tuple{Char,Char}},2) === Char
@test_throws BoundsError fieldtype(Union{Tuple{Char},Tuple{Char,Char}},3)

@test fieldnames(NTuple{3, Int}) == ntuple(i -> fieldname(NTuple{3, Int}, i), 3) == (1, 2, 3)
@test_throws ArgumentError fieldnames(Union{})
Expand Down
3 changes: 3 additions & 0 deletions test/show.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1432,3 +1432,6 @@ replstrcolor(x) = sprint((io, x) -> show(IOContext(io, :limit => true, :color =>

# issue #30303
@test repr(Symbol("a\$")) == "Symbol(\"a\\\$\")"

# issue #30505
@test repr(Union{Tuple{Char}, Tuple{Char, Char}}[('a','b')]) == "Union{Tuple{Char}, Tuple{Char,Char}}[('a', 'b')]"

0 comments on commit b45cfda

Please sign in to comment.