Skip to content

Commit b45cfda

Browse files
authored
Merge branch 'master' into jb/splatnew
2 parents 10ebb97 + cf404cf commit b45cfda

File tree

5 files changed

+40
-12
lines changed

5 files changed

+40
-12
lines changed

base/compiler/tfuncs.jl

+6-1
Original file line numberDiff line numberDiff line change
@@ -789,14 +789,19 @@ function fieldtype_nothrow(@nospecialize(s0), @nospecialize(name))
789789
return false
790790
end
791791

792+
su = unwrap_unionall(s0)
793+
if isa(su, Union)
794+
return fieldtype_nothrow(rewrap_unionall(su.a, s0), name) && fieldtype_nothrow(rewrap_unionall(su.b, s0), name)
795+
end
796+
792797
s = instanceof_tfunc(s0)[1]
793798
u = unwrap_unionall(s)
794799
return _fieldtype_nothrow(u, name)
795800
end
796801

797802
function _fieldtype_nothrow(@nospecialize(u), name::Const)
798803
if isa(u, Union)
799-
return _fieldtype_nothrow(u.a, name) && _fieldtype_nothrow(u.b, name)
804+
return _fieldtype_nothrow(u.a, name) || _fieldtype_nothrow(u.b, name)
800805
end
801806
fld = name.val
802807
if isa(fld, Symbol)

src/builtins.c

+26-11
Original file line numberDiff line numberDiff line change
@@ -699,12 +699,12 @@ JL_CALLABLE(jl_f_setfield)
699699
return args[2];
700700
}
701701

702-
static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f)
702+
static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f, int dothrow)
703703
{
704704
if (jl_is_unionall(t)) {
705705
jl_value_t *u = t;
706706
JL_GC_PUSH1(&u);
707-
u = get_fieldtype(((jl_unionall_t*)t)->body, f);
707+
u = get_fieldtype(((jl_unionall_t*)t)->body, f, dothrow);
708708
u = jl_type_unionall(((jl_unionall_t*)t)->var, u);
709709
JL_GC_POP();
710710
return u;
@@ -713,8 +713,13 @@ static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f)
713713
jl_value_t **u;
714714
jl_value_t *r;
715715
JL_GC_PUSHARGS(u, 2);
716-
u[0] = get_fieldtype(((jl_uniontype_t*)t)->a, f);
717-
u[1] = get_fieldtype(((jl_uniontype_t*)t)->b, f);
716+
u[0] = get_fieldtype(((jl_uniontype_t*)t)->a, f, 0);
717+
u[1] = get_fieldtype(((jl_uniontype_t*)t)->b, f, 0);
718+
if (u[0] == jl_bottom_type && u[1] == jl_bottom_type && dothrow) {
719+
// error if all types in the union might have
720+
get_fieldtype(((jl_uniontype_t*)t)->a, f, 1);
721+
get_fieldtype(((jl_uniontype_t*)t)->b, f, 1);
722+
}
718723
r = jl_type_union(u, 2);
719724
JL_GC_POP();
720725
return r;
@@ -729,28 +734,38 @@ static jl_value_t *get_fieldtype(jl_value_t *t, jl_value_t *f)
729734
jl_value_t *nm = jl_tparam0(st);
730735
if (jl_is_tuple(nm)) {
731736
int nf = jl_nfields(nm);
732-
if (field_index < 0 || field_index >= nf)
733-
jl_bounds_error(t, f);
737+
if (field_index < 0 || field_index >= nf) {
738+
if (dothrow)
739+
jl_bounds_error(t, f);
740+
else
741+
return jl_bottom_type;
742+
}
734743
}
735744
jl_value_t *tt = jl_tparam1(st);
736745
while (jl_is_typevar(tt))
737746
tt = ((jl_tvar_t*)tt)->ub;
738747
if (tt == (jl_value_t*)jl_any_type)
739748
return (jl_value_t*)jl_any_type;
740-
return get_fieldtype(tt, f);
749+
return get_fieldtype(tt, f, dothrow);
741750
}
742751
int nf = jl_field_count(st);
743752
if (nf > 0 && field_index >= nf-1 && st->name == jl_tuple_typename) {
744753
jl_value_t *ft = jl_field_type(st, nf-1);
745754
if (jl_is_vararg_type(ft))
746755
return jl_unwrap_vararg(ft);
747756
}
748-
if (field_index < 0 || field_index >= nf)
749-
jl_bounds_error(t, f);
757+
if (field_index < 0 || field_index >= nf) {
758+
if (dothrow)
759+
jl_bounds_error(t, f);
760+
else
761+
return jl_bottom_type;
762+
}
750763
}
751764
else {
752765
JL_TYPECHK(fieldtype, symbol, f);
753-
field_index = jl_field_index(st, (jl_sym_t*)f, 1);
766+
field_index = jl_field_index(st, (jl_sym_t*)f, dothrow);
767+
if (field_index == -1)
768+
return jl_bottom_type;
754769
}
755770
return jl_field_type(st, field_index);
756771
}
@@ -765,7 +780,7 @@ JL_CALLABLE(jl_f_fieldtype)
765780
jl_datatype_t *st = (jl_datatype_t*)args[0];
766781
if (st == jl_module_type)
767782
jl_error("cannot assign variables in other modules");
768-
return get_fieldtype(args[0], args[1]);
783+
return get_fieldtype(args[0], args[1], 1);
769784
}
770785

771786
JL_CALLABLE(jl_f_nfields)

src/codegen.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -4066,6 +4066,8 @@ static jl_cgval_t emit_expr(jl_codectx_t &ctx, jl_value_t *expr, ssize_t ssaval)
40664066
}
40674067
Value *typ = boxed(ctx, argv[0]);
40684068
Value *val = emit_jlcall(ctx, jlnew_func, typ, &argv[1], nargs - 1);
4069+
// temporarily mark as `Any`, expecting `emit_ssaval_assign` to update
4070+
// it to the inferred type.
40694071
return mark_julia_type(ctx, val, true, (jl_value_t*)jl_any_type);
40704072
}
40714073
else if (head == splatnew_sym) {

test/reflection.jl

+3
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,9 @@ tlayout = TLayout(5,7,11)
234234
@test fieldtype(Tuple{Vararg{Int8}}, 1) === Int8
235235
@test fieldtype(Tuple{Vararg{Int8}}, 10) === Int8
236236
@test_throws BoundsError fieldtype(Tuple{Vararg{Int8}}, 0)
237+
# issue #30505
238+
@test fieldtype(Union{Tuple{Char},Tuple{Char,Char}},2) === Char
239+
@test_throws BoundsError fieldtype(Union{Tuple{Char},Tuple{Char,Char}},3)
237240

238241
@test fieldnames(NTuple{3, Int}) == ntuple(i -> fieldname(NTuple{3, Int}, i), 3) == (1, 2, 3)
239242
@test_throws ArgumentError fieldnames(Union{})

test/show.jl

+3
Original file line numberDiff line numberDiff line change
@@ -1432,3 +1432,6 @@ replstrcolor(x) = sprint((io, x) -> show(IOContext(io, :limit => true, :color =>
14321432

14331433
# issue #30303
14341434
@test repr(Symbol("a\$")) == "Symbol(\"a\\\$\")"
1435+
1436+
# issue #30505
1437+
@test repr(Union{Tuple{Char}, Tuple{Char, Char}}[('a','b')]) == "Union{Tuple{Char}, Tuple{Char,Char}}[('a', 'b')]"

0 commit comments

Comments
 (0)