Skip to content

Commit

Permalink
improve correctness of fieldtype_tfunc
Browse files Browse the repository at this point in the history
Vararg is only exact if in covariant position

also make getfield_tfunc monotonic for the case where the type has one
field, to avoid the same bug

fix #16530

(cherry picked from commit aeaff55)
ref #17953
  • Loading branch information
vtjnash authored and tkelman committed Aug 20, 2016
1 parent dcea839 commit 721c6b7
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 6 deletions.
21 changes: 18 additions & 3 deletions base/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -408,7 +408,7 @@ function limit_type_depth(t::ANY, d::Int, cov::Bool, vars)
else
return t
end
if inexact && !isvarargtype(R)
if inexact && (!cov || !isvarargtype(R))
R = TypeVar(:_,R)
push!(vars, R)
end
Expand Down Expand Up @@ -467,12 +467,15 @@ function getfield_tfunc(s0::ANY, name)
end
end
snames = s.name.names
for i=1:length(snames)
for i = 1:length(snames)
if is(snames[i],fld)
R = s.types[i]
if isempty(s.parameters)
return R, true
else
# conservatively limit the type depth here,
# since the UnionAll type bound is otherwise incorrect
# in the current type system
typ = limit_type_depth(R, 0, true,
filter!(x->isa(x,TypeVar), Any[s.parameters...]))
return typ, isleaftype(s) && typeseq(typ, R)
Expand All @@ -493,8 +496,20 @@ function getfield_tfunc(s0::ANY, name)
return Bottom, true
end
return s.types[i], false
elseif isempty(s.types)
return Bottom, true
elseif length(s.types) == 1 && isempty(s.parameters)
return s.types[1], true
else
return reduce(tmerge, Bottom, map(unwrapva,s.types)) #=Union{s.types...}=#, false
R = reduce(tmerge, Bottom, map(unwrapva,s.types)) #=Union{s.types...}=#
# do the same limiting as the known-symbol case to preserve type-monotonicity
if isempty(s.parameters)
return R, typeseq(R, s.types[1])
else
typ = limit_type_depth(R, 0, true,
filter!(x->isa(x,TypeVar), Any[s.parameters...]))
return typ, isleaftype(s) && typeseq(typ, R)
end
end
end
add_tfunc(getfield, 2, 2, (s,name)->getfield_tfunc(s,name)[1])
Expand Down
6 changes: 3 additions & 3 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ static int jl_has_typevars__(jl_value_t *v, int incl_wildcard, jl_value_t **p, s
jl_has_typevars__(((jl_tvar_t*)v)->lb, incl_wildcard, p, np))
return 1;
if (p != NULL) {
for(i=0; i < np; i++) {
for (i = 0; i < np; i++) {
if (v == p[i])
return 1;
}
Expand All @@ -102,7 +102,7 @@ static int jl_has_typevars__(jl_value_t *v, int incl_wildcard, jl_value_t **p, s
}
else if (jl_is_datatype(v)) {
if (is_unspec((jl_datatype_t*)v))
return 0;
return 0; // TODO: fix expect in this case
if (p == NULL) {
if (incl_wildcard)
expect = ((jl_datatype_t*)v)->haswildcard;
Expand All @@ -118,7 +118,7 @@ static int jl_has_typevars__(jl_value_t *v, int incl_wildcard, jl_value_t **p, s
return 0;
}
size_t l = jl_svec_len(t);
for(i=0; i < l; i++) {
for (i = 0; i < l; i++) {
jl_value_t *elt = jl_svecref(t, i);
if (elt != v) {
if (jl_has_typevars__(elt, incl_wildcard, p, np)) {
Expand Down
24 changes: 24 additions & 0 deletions test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -282,3 +282,27 @@ let I = Integer[]
push!(I, 1)
@test I == Any[1]
end

# issue #16530
type Foo16530a{dim}
c::Vector{NTuple{dim, Float64}}
d::Vector
end
type Foo16530b{dim}
c::Vector{NTuple{dim, Float64}}
end
f16530a() = fieldtype(Foo16530a, :c)
f16530a(c) = fieldtype(Foo16530a, c)
f16530b() = fieldtype(Foo16530b, :c)
f16530b(c) = fieldtype(Foo16530b, c)

let T = Array{Tuple{Vararg{Float64,TypeVar(:dim)}},1},
TTlim = Type{TypeVar(:_,Array{TypeVar(:_,Tuple),1})}

@test f16530a() == T
@test f16530a(:c) == T
@test Base.return_types(f16530a, ()) == Any[TTlim]
@test Base.return_types(f16530b, ()) == Any[TTlim]
@test Base.return_types(f16530b, (Symbol,)) == Any[TTlim]
end
@test f16530a(:d) == Vector

0 comments on commit 721c6b7

Please sign in to comment.