# This file is a part of Julia. License is MIT: http://julialang.org/license # tests for Core.Inference correctness and precision # issue 9770 @noinline x9770() = false function f9770(x) return if x9770() g9770(:a, :foo) else x end end function g9770(x,y) return if isa(y, Symbol) f9770(x) else g9770(:a, :foo) end end @test g9770(:a, "c") === :a @test g9770(:b, :c) === :b # issue #1628 type I1628{X} x::X end let # here the potential problem is that the run-time value of static # parameter X in the I1628 constructor is (DataType,DataType), # but type inference will track it more accurately as # (Type{Integer}, Type{Int}). f1628() = I1628((Integer,Int)) @test isa(f1628(), I1628{Tuple{DataType,DataType}}) end let fT{T}(x::T) = T @test fT(Any) === DataType @test fT(Int) === DataType @test fT(Type{Any}) === DataType @test fT(Type{Int}) === DataType ff{T}(x::Type{T}) = T @test ff(Type{Any}) === Type{Any} @test ff(Type{Int}) === Type{Int} @test ff(Any) === Any @test ff(Int) === Int end # issue #3182 f3182{T}(::Type{T}) = 0 f3182(x) = 1 function g3182(t::DataType) # tricky thing here is that DataType is a concrete type, and a # subtype of Type, but we cannot infer the T in Type{T} just # by knowing (at compile time) that the argument is a DataType. # however the ::Type{T} method should still match at run time. return f3182(t) end @test g3182(Complex.body) == 0 # issue #5906 abstract Outer5906{T} immutable Inner5906{T} a:: T end immutable Empty5906{T} <: Outer5906{T} end immutable Hanoi5906{T} <: Outer5906{T} a::T succ :: Outer5906{Inner5906{T}} Hanoi5906(a) = new(a, Empty5906{Inner5906{T}}()) end function f5906{T}(h::Hanoi5906{T}) if isa(h.succ, Empty5906) return end f5906(h.succ) end # can cause infinite recursion in type inference via instantiation of # the type of the `succ` field @test f5906(Hanoi5906{Int}(1)) === nothing # issue on the flight from DFW # (type inference deducing Type{:x} rather than Symbol) type FooBarDFW{s}; end fooDFW(p::Type{FooBarDFW}) = string(p.parameters[1]) fooDFW(p) = string(p.parameters[1]) @test fooDFW(FooBarDFW{:x}) == "x" # not ":x" # Type inference for tuple parameters immutable fooTuple{s}; end barTuple1() = fooTuple{(:y,)}() barTuple2() = fooTuple{tuple(:y)}() @test Base.return_types(barTuple1,Tuple{})[1] == Base.return_types(barTuple2,Tuple{})[1] == fooTuple{(:y,)} # issue #6050 @test Core.Inference.getfield_tfunc( Dict{Int64,Tuple{UnitRange{Int64},UnitRange{Int64}}}, Core.Inference.Const(:vals)) == Array{Tuple{UnitRange{Int64},UnitRange{Int64}},1} # issue #12476 function f12476(a) (k, v) = a return v end @inferred f12476(1.0 => 1) # issue #12551 (make sure these don't throw in inference) Base.return_types(unsafe_load, (Ptr{nothing},)) Base.return_types(getindex, (Vector{nothing},)) # issue #12636 module MyColors abstract Paint{T} immutable RGB{T<:AbstractFloat} <: Paint{T} r::T g::T b::T end myeltype{T}(::Type{Paint{T}}) = T myeltype{P<:Paint}(::Type{P}) = myeltype(supertype(P)) myeltype(::Type{Any}) = Any end @test @inferred(MyColors.myeltype(MyColors.RGB{Float32})) == Float32 @test @inferred(MyColors.myeltype(MyColors.RGB)) == Any # issue #12826 f12826{I<:Integer}(v::Vector{I}) = v[1] @test Base.return_types(f12826,Tuple{Array{I,1} where I<:Integer})[1] == Integer # non-terminating inference, issue #14009 # non-terminating codegen, issue #16201 type A14009{T}; end A14009{T}(a::T) = A14009{T}() f14009(a) = rand(Bool) ? f14009(A14009(a)) : a code_typed(f14009, (Int,)) code_llvm(DevNull, f14009, (Int,)) type B14009{T}; end g14009(a) = g14009(B14009{a}) code_typed(g14009, (Type{Int},)) code_llvm(DevNull, f14009, (Int,)) # issue #9232 arithtype9232{T<:Real}(::Type{T},::Type{T}) = arithtype9232(T) result_type9232{T1<:Number,T2<:Number}(::Type{T1}, ::Type{T2}) = arithtype9232(T1, T2) # this gave a "type too large", but not reliably @test length(code_typed(result_type9232, Tuple{(Type{_} where _<:Union{Float32,Float64}), Type{T2} where T2<:Number})) == 1 # issue #10878 function g10878(x; kw...); end invoke_g10878() = invoke(g10878, Tuple{Any}, 1) @code_typed invoke_g10878() code_llvm(DevNull, invoke_g10878, ()) # issue #10930 @test isa(code_typed(promote,(Any,Any,Vararg{Any})), Array) find_tvar10930{T<:Tuple}(sig::Type{T}) = 1 function find_tvar10930(arg) if arg<:Tuple find_tvar10930(arg[random_var_name]) end return 1 end @test find_tvar10930(Vararg{Int}) === 1 # issue #12474 @generated function f12474(::Any) :(for i in 1 end) end let ast12474 = code_typed(f12474, Tuple{Float64}) @test isleaftype(ast12474[1][2]) @test all(isleaftype, ast12474[1][1].slottypes) end # pr #15259 immutable A15259 x y end # check that allocation was ellided @eval f15259(x,y) = (a = $(Expr(:new, :A15259, :x, :y)); (a.x, a.y, getfield(a,1), getfield(a, 2))) @test isempty(filter(x -> isa(x,Expr) && x.head === :(=) && isa(x.args[2], Expr) && x.args[2].head === :new, code_typed(f15259, (Any,Int))[1][1].code)) @test f15259(1,2) == (1,2,1,2) # check that error cases are still correct @eval g15259(x,y) = (a = $(Expr(:new, :A15259, :x, :y)); a.z) @test_throws ErrorException g15259(1,1) @eval h15259(x,y) = (a = $(Expr(:new, :A15259, :x, :y)); getfield(a, 3)) @test_throws BoundsError h15259(1,1) # issue #7810 type Foo7810{T<:AbstractVector} v::T end bar7810() = [Foo7810([(a,b) for a in 1:2]) for b in 3:4] @test Base.return_types(bar7810,Tuple{})[1] == Array{Foo7810{Array{Tuple{Int,Int},1}},1} # issue #11366 f11366{T}(x::Type{Ref{T}}) = Ref{x} @test !isleaftype(Base.return_types(f11366, (Any,))[1]) let f(T) = Type{T} @test Base.return_types(f, Tuple{Type{Int}}) == [Type{Type{Int}}] end # issue #9222 function SimpleTest9222{T1<:Real}(pdedata, mu_actual::Vector{T1}, nu_actual::Vector{T1}, v0::Vector{T1}, epsilon::T1, beta::Vector{T1}, delta::T1, l::T1, R::T1, s0::T1, show_trace::Bool = true) return 0.0 end function SimpleTest9222{T1<:Real}(pdedata, mu_actual::Vector{T1}, nu_actual::Vector{T1}, v0::Vector{T1}, epsilon::T1, beta::Vector{T1}, delta::T1, l::T1, R::T1) return SimpleTest9222(pdedata, mu_actual, nu_actual, v0, epsilon, beta, delta, l, R, v0[1]) end function foo9222() v0 = rand(10) mu_actual = rand(10) nu_actual = rand(10) SimpleTest9222(0.0, mu_actual, nu_actual, v0, 0.0, [1.0,1.0], 0.5, 5.0, 20.0) end @test 0.0 == foo9222() # make sure none of the slottypes are left as Core.Inference.Const objects function f18679() for i = 1:2 if i == 1 a = ((),) else return a[1] end end end g18679(x::Tuple) = () g18679() = g18679(any_undef_global::Union{Int,Tuple{}}) for code in Any[ @code_typed(f18679())[1] @code_typed(g18679())[1]] @test all(x->isa(x, Type), code.slottypes) local notconst(other::ANY) = true notconst(slot::TypedSlot) = @test isa(slot.typ, Type) function notconst(expr::Expr) @test isa(expr.typ, Type) for a in expr.args notconst(a) end end for e in code.code notconst(e) end end # branching based on inferrable conditions let f(x) = isa(x,Int) ? 1 : "" @test Base.return_types(f, Tuple{Int}) == [Int] end let g() = Int <: Real ? 1 : "" @test Base.return_types(g, Tuple{}) == [Int] end typealias NInt{N} Tuple{Vararg{Int, N}} @test Base.eltype(NInt) === Int fNInt(x::NInt) = (x...) gNInt() = fNInt(x) @test Base.return_types(gNInt, ()) == Any[NInt] # issue #17572 function f17572{A}(::Type{Val{A}}) return Tuple{Int}(Tuple{A}((1,))) end # test that inference doesn't error @test isa(code_typed(f17572, (Type{Val{0}},)), Array) # === with singleton constants let f(x) = (x===nothing) ? 1 : 1.0 @test Base.return_types(f, (Void,)) == Any[Int] 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,dim}}, 1} where dim, TTlim = Type{_} where _<:T @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 let T1 = Tuple{Int, Float64}, T2 = Tuple{Int, Float32}, T = Tuple{T1, T2} global f18037 f18037() = fieldtype(T, 1) f18037(i) = fieldtype(T, i) @test f18037() === T1 @test f18037(1) === T1 @test f18037(2) === T2 @test Base.return_types(f18037, ()) == Any[Type{T1}] @test Base.return_types(f18037, (Int,)) == Any[Type{T} where T<:Tuple{Int, AbstractFloat}] end # issue #18015 type Triple18015 a::Int b::Int c::Int end a18015(tri) = tri.a b18015(tri) = tri.b c18015(tri) = tri.c setabc18015!(tri, a, b, c) = (tri.a = a; tri.b = b; tri.c = c) let tri = Triple18015(1, 2, 3) setabc18015!(tri, b18015(tri), c18015(tri), a18015(tri)) @test tri.a === 2 && tri.b === 3 && tri.c === 1 end # issue #18222 f18222{T<:AbstractFloat}(::Union{T, Int}) = false f18222(x) = true g18222(x) = f18222(x) @test f18222(1) == g18222(1) == true @test f18222(1.0) == g18222(1.0) == false # issue #18399 # TODO: this test is rather brittle type TSlow18399{T} x::T end function hvcat18399(as) cb = ri->as[ri] g = Base.Generator(cb, 1) return g.f(1) end function cat_t18399(X...) for i = 2:1 X[i] d->i end end C18399 = TSlow18399{Int}(1) GB18399 = TSlow18399{Int}(1) function test18399(C) B = GB18399::Union{TSlow18399{Int},TSlow18399{Any}} cat_t18399() cat_t18399(B, B, B) hvcat18399((C,)) return hvcat18399(((2, 3),)) end @test test18399(C18399) == (2, 3) # issue #18450 f18450() = ifelse(true, Tuple{Vararg{Int}}, Tuple{Vararg}) @test f18450() == Tuple{Vararg{Int}} # issue #18569 @test !Core.Inference.isconstType(Type{Tuple}) # ensure pure attribute applies correctly to all signatures of fpure Base.@pure function fpure(a=rand(); b=rand()) # use the `rand` function since it is known to be `@inline` # but would be too big to inline return a + b + rand() end gpure() = fpure() gpure(x::Irrational) = fpure(x) @test which(fpure, ()).source.pure @test which(fpure, (typeof(pi),)).source.pure @test !which(gpure, ()).source.pure @test !which(gpure, (typeof(pi),)).source.pure @test @code_typed(gpure())[1].pure @test @code_typed(gpure(π))[1].pure @test gpure() == gpure() == gpure() @test gpure(π) == gpure(π) == gpure(π) # issue #10880 function cat10880(a, b) Tuple{a.parameters..., b.parameters...} end @inferred cat10880(Tuple{Int8,Int16}, Tuple{Int32}) # issue #19348 function is_intrinsic_expr(e::Expr) if e.head === :call return Base.is_intrinsic_expr(e.args[1]) elseif e.head == :invoke return false elseif e.head === :new return false elseif e.head === :copyast return false elseif e.head === :inert return false end return true end test_inferred_static(other::ANY) = true test_inferred_static(slot::TypedSlot) = @test isleaftype(slot.typ) function test_inferred_static(expr::Expr) if !is_intrinsic_expr(expr) @test isleaftype(expr.typ) end for a in expr.args test_inferred_static(a) end end function test_inferred_static(arrow::Pair) code, rt = arrow @test isleaftype(rt) @test code.inferred @test all(x->isleaftype(x), code.slottypes) @test all(x->isleaftype(x), code.ssavaluetypes) for e in code.code test_inferred_static(e) end end function g19348(x) a, b = x return a + b end test_inferred_static(@code_typed g19348((1, 2.0))) # Issue 19641 foo19641() = let a = 1.0 Core.Inference.return_type(x -> x + a, Tuple{Float64}) end @inferred foo19641() test_fast_eq(a, b) = @fastmath a == b test_fast_ne(a, b) = @fastmath a != b test_fast_lt(a, b) = @fastmath a < b test_fast_le(a, b) = @fastmath a <= b @inferred test_fast_eq(1f0, 1f0) @inferred test_fast_ne(1f0, 1f0) @inferred test_fast_lt(1f0, 1f0) @inferred test_fast_le(1f0, 1f0) @inferred test_fast_eq(1.0, 1.0) @inferred test_fast_ne(1.0, 1.0) @inferred test_fast_lt(1.0, 1.0) @inferred test_fast_le(1.0, 1.0) abstract AbstractMyType18457{T,F,G} immutable MyType18457{T,F,G}<:AbstractMyType18457{T,F,G} end tpara18457{I}(::Type{AbstractMyType18457{I}}) = I tpara18457{A<:AbstractMyType18457}(::Type{A}) = tpara18457(supertype(A)) @test tpara18457(MyType18457{true}) === true