Skip to content

Commit

Permalink
Add constraint check on b in intersect_typevar
Browse files Browse the repository at this point in the history
Fixes #11136
  • Loading branch information
timholy committed May 22, 2015
1 parent 9e8badc commit 682e6b1
Show file tree
Hide file tree
Showing 2 changed files with 73 additions and 48 deletions.
12 changes: 12 additions & 0 deletions src/jltypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -739,6 +739,18 @@ static jl_value_t *intersect_typevar(jl_tvar_t *a, jl_value_t *b,
break;
}
}
if (jl_is_typevar(b)) {
for(i=0; i < penv->n; i+=2) {
if (penv->data[i] == b && !jl_is_typevar(penv->data[i+1])) {
jl_value_t *ti = jl_type_intersection((jl_value_t*)a, penv->data[i+1]);
if (ti == (jl_value_t*)jl_bottom_type) {
JL_GC_POP();
return ti;
}
break;
}
}
}
extend((jl_value_t*)a, b, penv);
if (jl_is_typevar(b)) {
JL_GC_POP();
Expand Down
109 changes: 61 additions & 48 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@

const Bottom = Union()

function testintersect(a, b, result, cmp=is)
@test cmp(typeintersect(a, b), result)
@test cmp(typeintersect(b, a), result)
end
isnot(x,y) = !is(x,y)

# basic type relationships
@test Int8 <: Integer
@test Int32 <: Integer
Expand All @@ -23,96 +29,96 @@ const Bottom = Union()
@test Array{Int8,1} <: Array{Int8,1}
@test !(Type{Bottom} <: Type{Int32})
@test !(Vector{Float64} <: Vector{Union(Float64,Float32)})
@test is(Bottom, typeintersect(Vector{Float64},Vector{Union(Float64,Float32)}))
testintersect(Vector{Float64}, Vector{Union(Float64,Float32)}, Bottom)

@test !isa(Array,Type{Any})
@test Type{Complex} <: DataType
@test isa(Complex,Type{Complex})
@test !(Type{Ptr{Bottom}} <: Type{Ptr})
@test !(Type{Rational{Int}} <: Type{Rational})
let T = TypeVar(:T,true)
@test !is(Bottom, typeintersect(Array{Bottom},AbstractArray{T}))
@test is(Bottom, typeintersect(Tuple{Type{Ptr{UInt8}},Ptr{Bottom}},
Tuple{Type{Ptr{T}},Ptr{T}}))
testintersect(Array{Bottom},AbstractArray{T}, Bottom, isnot)
testintersect(Tuple{Type{Ptr{UInt8}},Ptr{Bottom}},
Tuple{Type{Ptr{T}},Ptr{T}}, Bottom)
@test !(Type{T} <: TypeVar)

@test isequal(typeintersect(Tuple{Range{Int},Tuple{Int,Int}},Tuple{AbstractArray{T},Dims}),
testintersect(Tuple{Range{Int},Tuple{Int,Int}},Tuple{AbstractArray{T},Dims},
Tuple{Range{Int},Tuple{Int,Int}})

@test isequal(typeintersect(Tuple{T, AbstractArray{T}}, Tuple{Number, Array{Int,1}}),
testintersect(Tuple{T, AbstractArray{T}}, Tuple{Number, Array{Int,1}},
Tuple{Int, Array{Int,1}})

@test isequal(typeintersect(Tuple{T, AbstractArray{T}}, Tuple{Int, Array{Number,1}}),
testintersect(Tuple{T, AbstractArray{T}}, Tuple{Int, Array{Number,1}},
Tuple{Int, Array{Number,1}})

@test isequal(typeintersect(Tuple{T, AbstractArray{T}},Tuple{Any, Array{Number,1}}),
Tuple{Number, Array{Number,1}})
@test !is(Bottom, typeintersect(Tuple{Array{T}, Array{T}}, Tuple{Array, Array{Any}}))
testintersect(Tuple{T, AbstractArray{T}},Tuple{Any, Array{Number,1}},
Tuple{Number, Array{Number,1}}, isequal)
testintersect(Tuple{Array{T}, Array{T}}, Tuple{Array, Array{Any}}, Bottom, isnot)
f47{T}(x::Vector{Vector{T}}) = 0
@test_throws MethodError f47(Array(Vector,0))
@test f47(Array(Vector{Int},0)) == 0
@test typeintersect(Tuple{T,T}, Tuple{Union(Float64,Int64),Int64}) == Tuple{Int64,Int64}
@test typeintersect(Tuple{T,T}, Tuple{Int64,Union(Float64,Int64)}) == Tuple{Int64,Int64}
testintersect(Tuple{T,T}, Tuple{Union(Float64,Int64),Int64}, Tuple{Int64,Int64})
testintersect(Tuple{T,T}, Tuple{Int64,Union(Float64,Int64)}, Tuple{Int64,Int64})

TT = TypeVar(:T)
S = TypeVar(:S,true); N = TypeVar(:N,true); SN = TypeVar(:S,Number,true)
@test typeintersect(Type{TypeVar(:T,Array{TT,1})},Type{Array{SN,N}}) == Type{Array{SN,1}}
testintersect(Type{TypeVar(:T,Array{TT,1})},Type{Array{SN,N}}, Type{Array{SN,1}})
# issue #5359
@test typeintersect(Tuple{Type{Array{T,1}},Array{T,1}},
Tuple{Type{AbstractVector},Vector{Int}}) === Bottom
testintersect(Tuple{Type{Array{T,1}},Array{T,1}},
Tuple{Type{AbstractVector},Vector{Int}}, Bottom)
# issue #5559
@test typeintersect(Tuple{Type{Vector{Complex128}}, AbstractVector},
Tuple{Type{Array{T,N}}, Array{S,N}}) == Tuple{Type{Vector{Complex128}},Vector}
@test typeintersect(Tuple{Type{Vector{Complex128}}, AbstractArray},
Tuple{Type{Array{T,N}}, Array{S,N}}) == Tuple{Type{Vector{Complex128}},Vector}
testintersect(Tuple{Type{Vector{Complex128}}, AbstractVector},
Tuple{Type{Array{T,N}}, Array{S,N}}, Tuple{Type{Vector{Complex128}},Vector}, isequal)
testintersect(Tuple{Type{Vector{Complex128}}, AbstractArray},
Tuple{Type{Array{T,N}}, Array{S,N}}, Tuple{Type{Vector{Complex128}},Vector}, isequal)

@test typeintersect(Type{Array{T}}, Type{AbstractArray{T}}) === Bottom
testintersect(Type{Array{T}}, Type{AbstractArray{T}}, Bottom)

@test typeintersect(Type{Tuple{Bool,Vararg{Int}}}, Type{Tuple{Vararg{T}}}) === Bottom
@test typeintersect(Type{Tuple{Bool,Vararg{Int}}}, Type{Tuple{T,Vararg{T}}}) === Bottom
testintersect(Type{Tuple{Bool,Vararg{Int}}}, Type{Tuple{Vararg{T}}}, Bottom)
testintersect(Type{Tuple{Bool,Vararg{Int}}}, Type{Tuple{T,Vararg{T}}}, Bottom)

@test typeintersect(Tuple{Rational{T},T}, Tuple{Rational{Integer},Int}) === Tuple{Rational{Integer},Int}
testintersect(Tuple{Rational{T},T}, Tuple{Rational{Integer},Int}, Tuple{Rational{Integer},Int})

@test typeintersect(Pair{T,Ptr{T}}, Pair{Ptr{S},S}) === Bottom
@test typeintersect(Tuple{T,Ptr{T}}, Tuple{Ptr{S},S}) === Bottom
testintersect(Pair{T,Ptr{T}}, Pair{Ptr{S},S}, Bottom)
testintersect(Tuple{T,Ptr{T}}, Tuple{Ptr{S},S}, Bottom)
end
let N = TypeVar(:N,true)
@test isequal(typeintersect(Tuple{NTuple{N,Integer},NTuple{N,Integer}},
Tuple{Tuple{Integer,Integer}, Tuple{Vararg{Integer}}}),
testintersect(Tuple{NTuple{N,Integer},NTuple{N,Integer}},
Tuple{Tuple{Integer,Integer}, Tuple{Vararg{Integer}}},
Tuple{Tuple{Integer,Integer}, Tuple{Integer,Integer}})
@test isequal(typeintersect(Tuple{NTuple{N,Integer},NTuple{N,Integer}},
Tuple{Tuple{Vararg{Integer}}, Tuple{Integer,Integer}}),
testintersect(Tuple{NTuple{N,Integer},NTuple{N,Integer}},
Tuple{Tuple{Vararg{Integer}}, Tuple{Integer,Integer}},
Tuple{Tuple{Integer,Integer}, Tuple{Integer,Integer}})
local A = typeintersect(Tuple{NTuple{N,Any},Array{Int,N}},
Tuple{Tuple{Int,Vararg{Int}},Array})
local B = Tuple{Tuple{Int,Vararg{Int}},Array{Int,N}}
@test A<:B && B<:A
@test isequal(typeintersect(Tuple{NTuple{N,Any},Array{Int,N}},
Tuple{Tuple{Int,Vararg{Int}},Array{Int,2}}),
testintersect(Tuple{NTuple{N,Any},Array{Int,N}},
Tuple{Tuple{Int,Vararg{Int}},Array{Int,2}},
Tuple{Tuple{Int,Int}, Array{Int,2}})
end
@test is(Bottom, typeintersect(Type{Any},Type{Complex}))
@test is(Bottom, typeintersect(Type{Any},Type{TypeVar(:T,Real)}))
testintersect(Type{Any},Type{Complex}, Bottom)
testintersect(Type{Any},Type{TypeVar(:T,Real)}, Bottom)
@test !(Type{Array{Integer}} <: Type{AbstractArray{Integer}})
@test !(Type{Array{Integer}} <: Type{Array{TypeVar(:T,Integer)}})
@test is(Bottom, typeintersect(Type{Function},UnionType))
@test is(Type{Int32}, typeintersect(Type{Int32},DataType))
testintersect(Type{Function},UnionType,Bottom)
testintersect(Type{Int32}, DataType, Type{Int32})
@test !(Type <: TypeVar)
@test !is(Bottom, typeintersect(DataType, Type))
@test !is(Bottom, typeintersect(UnionType, Type))
@test !is(Bottom, typeintersect(DataType, Type{Int}))
@test !is(Bottom, typeintersect(DataType, Type{TypeVar(:T,Int)}))
@test !is(Bottom, typeintersect(DataType, Type{TypeVar(:T,Integer)}))
testintersect(DataType, Type, Bottom, isnot)
testintersect(UnionType, Type, Bottom, isnot)
testintersect(DataType, Type{Int}, Bottom, isnot)
testintersect(DataType, Type{TypeVar(:T,Int)}, Bottom, isnot)
testintersect(DataType, Type{TypeVar(:T,Integer)}, Bottom, isnot)

@test typeintersect(Tuple{Vararg{Int}}, Tuple{Vararg{Bool}}) === Tuple{}
@test typeintersect(Type{Tuple{Vararg{Int}}}, Type{Tuple{Vararg{Bool}}}) === Bottom
@test typeintersect(Tuple{Bool,Vararg{Int}}, Tuple{Vararg{Bool}}) === Tuple{Bool,}
testintersect(Tuple{Vararg{Int}}, Tuple{Vararg{Bool}}, Tuple{})
testintersect(Type{Tuple{Vararg{Int}}}, Type{Tuple{Vararg{Bool}}}, Bottom)
testintersect(Tuple{Bool,Vararg{Int}}, Tuple{Vararg{Bool}}, Tuple{Bool,})

let T = TypeVar(:T,Union(Float32,Float64))
@test typeintersect(AbstractArray, Matrix{T}) == Matrix{T}
testintersect(AbstractArray, Matrix{T}, Matrix{T})
end
let T = TypeVar(:T,Union(Float32,Float64),true)
@test typeintersect(AbstractArray, Matrix{T}) == Matrix{T}
testintersect(AbstractArray, Matrix{T}, Matrix{T})
end

@test isa(Int,Type{TypeVar(:T,Number)})
Expand Down Expand Up @@ -146,7 +152,7 @@ end

# issue #2997
let T = TypeVar(:T,Union(Float64,Array{Float64,1}),true)
@test typeintersect(T,Real) === Float64
testintersect(T,Real,Float64)
end

# join
Expand Down Expand Up @@ -1361,7 +1367,7 @@ abstract IT4805{N, T}
let
T = TypeVar(:T,Int,true)
N = TypeVar(:N,true)
@test typeintersect(Type{IT4805{1,T}}, Type{TypeVar(:_,IT4805{N,Int})}) != Bottom
testintersect(Type{IT4805{1,T}}, Type{TypeVar(:_,IT4805{N,Int})}, Bottom, isnot)
end

let
Expand Down Expand Up @@ -2002,7 +2008,7 @@ abstract AbstractThing{T,N}
type ConcreteThing{T<:FloatingPoint,N} <: AbstractThing{T,N}
end

@test typeintersect(AbstractThing{TypeVar(:T,true),2}, ConcreteThing) == ConcreteThing{TypeVar(:T,FloatingPoint),2}
testintersect(AbstractThing{TypeVar(:T,true),2}, ConcreteThing, ConcreteThing{TypeVar(:T,FloatingPoint),2}, isequal)

# issue #8978
module I8978
Expand Down Expand Up @@ -2824,3 +2830,10 @@ function f11357()
x[i...]
end
@test f11357() === 1

# issue #11136
type A11136 end
type B11136 end
let T = TypeVar(:T, true), TB = TypeVar(:T, B11136, true)
testintersect(Tuple{T, T}, Tuple{A11136, TB}, Bottom)
end

0 comments on commit 682e6b1

Please sign in to comment.