JuliaDebug / JuliaDebug/Cthulhu.jl

Variable with two different type-annotations in a function

Open
#480 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Julia
Stars
709
Forks
46
Avg merge
1d 13h
Merged PRs (30d)
2

Description

julia> using ApproxFunOrthogonalPolynomials

julia> f = Fun((x,y)->x*y, Ultraspherical(1) ⊗ Chebyshev());

julia> @descend_code_warntype ApproxFunBase.standardLowRankFun(f, NormalizedUltraspherical(1), Ultraspherical(1))
standardLowRankFun(f::Function, dx::Space, dy::Space; tolerance, gridx, gridy, maxrank) @ ApproxFunBase ~/Dropbox/JuliaPackages/ApproxFunBase/src/Multivariate/LowRankFun.jl:113
[ Info: This method only fills in default arguments; descend into the body method to see the full source.
113 function standardLowRankFun(f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64, Vector{Float64}}::Function, dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}::Space, dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}::Space;
114         tolerance::Union{Symbol,Tuple{Symbol,Number}}=:relative,
115         gridx::Integer=64,
116         gridy::Integer=64,
117         maxrank::Integer=100
118         )::Tuple{Any, Float64}
Select a call to descend into or ↩ to ascend. [q]uit. [b]ookmark.
Toggles: [w]arn, [h]ide type-stable statements, [t]ype annotations, [s]yntax highlight for Source/LLVM/Native.
Show: [S]ource code, [A]ST, [T]yped code, [L]LVM IR, [N]ative code
Actions: [E]dit source code, [R]evise and redisplay
 • %1 = #standardLowRankFun#92(::Symbol,::Int64,::Int64,::Int64,::#standardLowRankFun,::Fun{…},::NormalizedPolynomialSpace{…},::Ultraspherical{…})::Tuple{Any, Float64}
   ↩
var"#standardLowRankFun#92"(tolerance::Union{Symbol, Tuple{Symbol, Number}}, gridx::Integer, gridy::Integer, maxrank::Integer, ::typeof(ApproxFunBase.standardLowRankFun), f::Function, dx::Space, dy::Space) @ ApproxFunBase ~/Dropbox/JuliaPackages/ApproxFunBase/src/Multivariate/LowRankFun.jl:113
113 function standardLowRankFun(f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64, Vector{Float64}}::Function, dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}::Space, dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}::Space;
114         tolerance::Symbol::Union{Symbol,Tuple{Symbol,Number}}=:relative,
115         gridx::Int64::Integer=64,
116         gridy::Int64::Integer=64,
117         maxrank::Int64::Integer=100
118         )::Tuple{Any, Float64}
119 
120     xy::Vector{StaticArraysCore.SVector{2, Float64}} = checkpoints((dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}⊗dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64})::TensorSpace{Tuple{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64})::Vector{StaticArraysCore.SVector{2, Float64}}
121     T::Core.Const(Float64) = promote_type(eltype(f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64, Vector{Float64}}(first(xy::Vector{StaticArraysCore.SVector{2, Float64}})::StaticArraysCore.SVector{2, Float64}...)::Float64)::Type{Float64},prectype(dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64})::Type{Float64},prectype(dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64})::Type{Float64})::Type{Float64}
122 
123     # We start by sampling on the given grid, find the approximate maximum and create the first rank-one approximation.
124     ptsx::FastTransforms.ChebyshevGrid{1, Float64},ptsy::FastTransforms.ChebyshevGrid{1, Float64}=points(dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64},gridx::Int64)::FastTransforms.ChebyshevGrid{1, Float64},points(dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64},gridy::Int64)::FastTransforms.ChebyshevGrid{1, Float64}
125     X::Matrix{Float64} = zeros(T::Type{Float64},gridx::Int64,gridy::Int64)::Matrix{Float64}
126     maxabsf::Float64,r::Vector{Float64}=findapproxmax!(f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64, Vector{Float64}},X::Matrix{Float64},ptsx::FastTransforms.ChebyshevGrid{1, Float64},ptsy::FastTransforms.ChebyshevGrid{1, Float64},gridx::Int64,gridy::Int64)::Tuple{Vector{Float64}, Int64}::Vector{Float64}
127     if (maxabsf::Float64 < (eps(zero(T::Type{Float64})::Float64)::Float64/eps(T::Type{Float64})::Float64)::Float64)::Bool
128         return LowRankFun::Type{LowRankFun}([Fun::Type{Fun}(dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64},[zero(T)])::Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}]::Vector{Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}},[Fun::Type{Fun}(dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64},[zero(T)])::Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}]::Vector{Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}})::LowRankFun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, TensorSpace{Tuple{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64}, maxabsf::Float64::Tuple{LowRankFun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, TensorSpace{Tuple{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64}, Float64}
129     end
130 
131     a::Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}},b::Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}=let r1::Float64=r::Vector{Float64}[1]::Float64, r2::Float64=r::Vector{Float64}[2]::Float64 # avoid boxing r
132         Fun::Type{Fun}(x->f(x,r2),dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64})::Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}},Fun::Type{Fun}(y->f(r1,y),dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64})::Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}::Tuple{Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}, Int64}
133     ::Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}end
134 
135     # If necessary, we resize the grid to be at least as large as the
136     # lengths of the first row and column Funs and we recompute the values of X.
137     if (gridx::Int64 < ncoefficients(a::Any)::Int64)::Bool || (gridy::Int64 < ncoefficients(b::Any)::Int64)::Bool
138         gridx::Int64,gridy::Int64 = max(gridx,ncoefficients(a::Any)::Int64)::Int64,max(gridy,ncoefficients(b::Any)::Int64)::Int64
139         ptsx::FastTransforms.ChebyshevGrid{1, Float64},ptsy::FastTransforms.ChebyshevGrid{1, Float64}=points(dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64},gridx::Int64)::FastTransforms.ChebyshevGrid{1, Float64},points(dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64},gridy::Int64)::FastTransforms.ChebyshevGrid{1, Float64}
140         X::Matrix{Float64} = zeros(T::Type{Float64},gridx::Int64,gridy::Int64)::Matrix{Float64}
141         maxabsf::Float64,r::Vector{Float64}=findapproxmax!(f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64, Vector{Float64}},X::Matrix{Float64},ptsx::FastTransforms.ChebyshevGrid{1, Float64},ptsy::FastTransforms.ChebyshevGrid{1, Float64},gridx::Int64,gridy::Int64)::Tuple{Vector{Float64}, Int64}::Vector{Float64}
142         a::Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}},b::Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}=let r1::Float64=r::Vector{Float64}[1]::Float64, r2::Float64=r::Vector{Float64}[2]::Float64
143             Fun::Type{Fun}(x->f(x,r2),dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64})::Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}},Fun::Type{Fun}(y->f(r1,y),dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64})::Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}::Tuple{Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}, Int64}
144         ::Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}end
145     end
146 
147     A::Vector{Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}},B::Vector{Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}}=typeof(a::Any)::Type{Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}}[]::Vector{Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}},typeof(b::Any)::Type{Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}}[]::Vector{Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}}
148     if (tolerance::Symbol == :relative)::Bool
149         tol::Float64 = (100maxabsf::Float64::Float64*eps(T::Type{Float64})::Float64)::Float64
150     elseif tolerance::Symbol[1] == :absolute
151         tol = 100*tolerance[2]*eps(T)
152     end
153     tol10::Float64 = (tol::Float64/10)::Float64
154     Avals::Vector{Float64},Bvals::Vector{Float64} = zeros(T::Type{Float64},gridx::Int64)::Vector{Float64},zeros(T::Type{Float64},gridy::Int64)::Vector{Float64}
155     p₁::ApproxFunBase.CanonicalTransformPlan{Float64, NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, ApproxFunBase.CanonicalTransformPlan{Float64, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, FastTransforms.ChebyshevTransformPlan{Float64, 1, Vector{Int32}, false, 1, Tuple{Int64}}, Chebyshev{ChebyshevInterval{Float64}, Float64}, false}, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, false},p₂::ApproxFunBase.CanonicalTransformPlan{Float64, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, FastTransforms.ChebyshevTransformPlan{Float64, 1, Vector{Int32}, false, 1, Tuple{Int64}}, Chebyshev{ChebyshevInterval{Float64}, Float64}, false} = plan_transform(dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64},Avals::Vector{Float64})::ApproxFunBase.CanonicalTransformPlan{Float64, NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, ApproxFunBase.CanonicalTransformPlan{Float64, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, FastTransforms.ChebyshevTransformPlan{Float64, 1, Vector{Int32}, false, 1, Tuple{Int64}}, Chebyshev{ChebyshevInterval{Float64}, Float64}, false}, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, false},plan_transform(dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64},Bvals::Vector{Float64})::ApproxFunBase.CanonicalTransformPlan{Float64, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, FastTransforms.ChebyshevTransformPlan{Float64, 1, Vector{Int32}, false, 1, Tuple{Int64}}, Chebyshev{ChebyshevInterval{Float64}, Float64}, false}
156 
157     # Eat, drink, subtract rank-one, repeat.
158     for k::Int64=(1:maxrank::Int64)::Int64::Union{Nothing, Tuple{Int64, Int64}}
159         if ((norm(a::Any.coefficients::Any,Inf::Float64)::Any < tol::Float64)::Any || (norm(b::Any.coefficients::Any,Inf::Float64)::Any < tol::Float64)::Any)
160             return LowRankFun::Type{LowRankFun}(A::Any,B::Any)::Any,maxabsf::Float64::Tuple{Any, Float64}
161         end
162         A::Any,B::Any =[A;(a/sqrt(abs(a::Any(r::Vector{Float64}[1]::Float64)::Any)::Any)::Any)::Any]::Any,[B;(b/((sqrt(abs(b(r[2]))::Any)::Any*sign(b(r[2]))::Any)::Any))::Any]::Any
163         r::Vector{Float64}=findapproxmax!(A::Any[k::Int64]::Any,B::Any[k::Int64]::Any,X::Matrix{Float64},ptsx::FastTransforms.ChebyshevGrid{1, Float64},ptsy::FastTransforms.ChebyshevGrid{1, Float64},gridx::Int64,gridy::Int64)::Vector{Float64}
164         Ar::Any,Br::Any=evaluate(A::Any,r::Vector{Float64}[1]::Float64)::Any,evaluate(B::Any,r::Vector{Float64}[2]::Float64)::Any
165         for i::Int64=(1:gridx::Int64)::Int64::Union{Nothing, Tuple{Int64, Int64}}
166             @inbounds Avals[i] = f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64, Vector{Float64}}(ptsx::FastTransforms.ChebyshevGrid{1, Float64}[i::Int64]::Float64,r::Vector{Float64}[2]::Float64)::Float64
167         end
168         for j::Int64=(1:gridy::Int64)::Int64::Union{Nothing, Tuple{Int64, Int64}}
169             @inbounds Bvals[j] = f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, ChebyshevInterval{Float64}}, Float64}, Float64, Vector{Float64}}(r::Vector{Float64}[1]::Float64,ptsy::FastTransforms.ChebyshevGrid{1, Float64}[j::Int64]::Float64)::Float64
170         end
171         a::Any,b::Any = (Fun::Type{Fun}(dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64},(p₁::ApproxFunBase.CanonicalTransformPlan{Float64, NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, ApproxFunBase.CanonicalTransformPlan{Float64, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, FastTransforms.ChebyshevTransformPlan{Float64, 1, Vector{Int32}, false, 1, Tuple{Int64}}, Chebyshev{ChebyshevInterval{Float64}, Float64}, false}, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, false}*Avals::Vector{Float64})::Vector{Float64})::Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}} - dotu(Br::Any,A::Any)::Any)::Any,(Fun::Type{Fun}(dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64},(p₂::ApproxFunBase.CanonicalTransformPlan{Float64, Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, FastTransforms.ChebyshevTransformPlan{Float64, 1, Vector{Int32}, false, 1, Tuple{Int64}}, Chebyshev{ChebyshevInterval{Float64}, Float64}, false}*Bvals::Vector{Float64})::Vector{Float64})::Fun{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}} - dotu(Ar::Any,B::Any)::Any)::Any
172         chop!(a::Any,tol10::Float64)::Any,chop!(b::Any,tol10::Float64)::Any
173     end
174     @warn "Maximum rank of " * string(maxrank::Int64)::String * " reached"
175     return LowRankFun::Type{LowRankFun}(A::Any,B::Any)::Any,maxabsf::Float64::Tuple{Any, Float64}
176 end
Select a call to descend into or ↩ to ascend. [q]uit. [b]ookmark.
Toggles: [w]arn, [h]ide type-stable statements, [t]ype annotations, [s]yntax highlight for Source/LLVM/Native.
Show: [S]ource code, [A]ST, [T]yped code, [L]LVM IR, [N]ative code
Actions: [E]dit source code, [R]evise and redisplay
 • dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}⊗dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}
   checkpoints((dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}⊗dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64})::TensorSpace{Tuple{NormalizedUlt…
   first(xy::Vector{StaticArraysCore.SVector{2, Float64}})
   f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float64, Cheb…
   eltype(f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProduct{2, Float6…
   prectype(dx::NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64})
   prectype(dy::Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64})
   promote_type(eltype(f::Fun{TensorSpace{Tuple{Ultraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Chebyshev{ChebyshevInterval{Float64}, Float64}}, DomainSets.FixedIntervalProd…
   points(dx,gridx)
v  points(dy,gridy)

On line 131, the variables a and b are annotated with concrete types, but from line 137 onwards, a and b are annotated with Any. It's unclear which one represents the actual inferred type. However, the function call ncoefficients(a::Any) on line 137 is annotated with Int64, so perhaps the type of a isn't inferred to be Any?

Looking into the typed code, I find

│    %74  = Base.indexed_iterate(%73, 1)::Core.PartialStruct(Tuple{Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}, Int64}, Any[Fun{NormalizedUltraspherical{Int64, ChebyshevInterval{Float64}, Float64}, Float64, Vector{Float64}}, Core.Const(2)])
│           (a = Core.getfield(%74, 1))

and this call seems to be inferred concretely, but overall the variable is inferred to be of type Any. I guess the concrete type arises from the call, and is not the inferred type of the variable being assigned to?

This is using ApproxFunBase v0.9.7 and ApproxFunOrthogonalPolynomials v0.6.44.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Reproduce the @descend_code_warntype session shown in the issue, then compare the displayed typed code with ApproxFunBase/src/Multivariate/LowRankFun.jl around lines 113-155. Trace how Cthulhu renders variable type annotations and verify the reported variable is displayed consistently without duplicate annotations.

Written by the indexing model from the issue text.

Assessment

Tech stack
julia
Domain
devtools
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Needs clarification
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.