diff --git a/base/inference.jl b/base/inference.jl index 4022da0726a60..92874f6f7b813 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -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 @@ -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) @@ -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]) diff --git a/src/jltypes.c b/src/jltypes.c index 74f54e98eb768..c6eedef9f8b37 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -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; } @@ -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; @@ -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)) { diff --git a/test/inference.jl b/test/inference.jl index 2615e9cc4847a..1d99d6539bc14 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -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