# Why is the type of factors not being inferred while multiplying an AbstractQ with a vector?

**URL:** <https://discourse.julialang.org/t/why-is-the-type-of-factors-not-being-inferred-while-multiplying-an-abstractq-with-a-vector/68981>\
**Category:** General Usage\
**Tags:** question, inference, linearalgebra\
**Created:** [September 30, 2021, 7:56am UTC](https://discourse.julialang.org/t/why-is-the-type-of-factors-not-being-inferred-while-multiplying-an-abstractq-with-a-vector/68981 "2021-09-30T07:56:36Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [September 30, 2021, 7:56am UTC](https://discourse.julialang.org/t/why-is-the-type-of-factors-not-being-inferred-while-multiplying-an-abstractq-with-a-vector/68981/1 "2021-09-30T07:56:36Z")

</div>

```julia
julia> using LinearAlgebra

julia> Q = qr(rand(30,30));

julia> Q2 = Q.Q;

julia> @code_warntype Q2 * rand(size(Q2,2))
MethodInstance for *(::LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}}, ::Vector{Float64})
  from *(A::LinearAlgebra.AbstractQ, b::StridedVector{T} where T) in LinearAlgebra at /home/jb6888/julia/julia-c8b5904991/share/julia/stdlib/v1.8/LinearAlgebra/src/qr.jl:635
Arguments
  #self#::Core.Const(*)
  A::LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}}
  b::Vector{Float64}
Locals
  bnew::Vector{Float64}
  Anew::LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}}
  TAb::Type{Float64}
Body::Vector{Float64}
1 ─ Core.NewvarNode(:(bnew))
│ %2 = LinearAlgebra.eltype(A)::Core.Const(Float64)
│ %3 = LinearAlgebra.eltype(b)::Core.Const(Float64)
│ (TAb = LinearAlgebra.promote_type(%2, %3))
│ %5 = Core.apply_type(LinearAlgebra.AbstractMatrix, TAb::Core.Const(Float64))::Core.Const(AbstractMatrix{Float64})
│ (Anew = LinearAlgebra.convert(%5, A))
│ %7 = Base.getproperty(A, :factors)::Matrix{Float64}
│ %8 = LinearAlgebra.size(%7, 1)::Int64
│ %9 = LinearAlgebra.length(b)::Int64
│ %10 = (%8 == %9)::Bool
└── goto #3 if not %10
2 ─ (bnew = LinearAlgebra.copy_oftype(b, TAb::Core.Const(Float64)))
└── goto #6
3 ─ %14 = Base.getproperty(A, :factors)::Matrix{Float64}
│ %15 = LinearAlgebra.size(%14, 2)::Int64
│ %16 = LinearAlgebra.length(b)::Int64
│ %17 = (%15 == %16)::Bool
└── goto #5 if not %17
4 ─ %19 = TAb::Core.Const(Float64)
│ %20 = Base.getproperty(A, :factors)::Matrix{Float64}
│ %21 = LinearAlgebra.size(%20, 1)::Int64
│ %22 = LinearAlgebra.length(b)::Int64
│ %23 = (%21 - %22)::Int64
│ %24 = LinearAlgebra.zeros(%19, %23)::Vector{Float64}
│ (bnew = Base.vcat(b, %24))
└── goto #6
5 ─ %27 = Base.getproperty(A, :factors)::Any
│ %28 = LinearAlgebra.size(%27, 1)::Any
│ %29 = Base.getproperty(A, :factors)::Any
│ %30 = LinearAlgebra.size(%29, 2)::Any
│ %31 = Base.string("vector must have length either ", %28, " or ", %30)::Any
│ %32 = LinearAlgebra.DimensionMismatch(%31)::Any
└── LinearAlgebra.throw(%32)
6 ┄ %34 = LinearAlgebra.lmul!(Anew, bnew)::Vector{Float64}
└── return %34

```

while the overall operation is type-stable, there are several `Any` around %27 where `Q2.factors` is used. For some reason the type of `Q2.factors` is not being inferred, which is strange since

```julia
julia> typeof(Q2)
LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}}

```

and the struct is defined as

```julia
struct QRCompactWYQ{S, M<:AbstractMatrix{S}} <: AbstractQ{S}
    factors::M
    T::Matrix{S}

    function QRCompactWYQ{S,M}(factors, T) where {S,M<:AbstractMatrix{S}}
        require_one_based_indexing(factors)
        new{S,M}(factors, T)
    end
end

```

and the type of `factors` should be inferred from the type of `Q2`. I can see this when I check

```julia
julia> @code_warntype Q2.factors
MethodInstance for getproperty(::LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}}, ::Symbol)
  from getproperty(x, f::Symbol) in Base at Base.jl:38
Arguments
  #self#::Core.Const(getproperty)
  x::LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}}
  f::Symbol
Body::Matrix{Float64}
1 ─ nothing
│ %2 = Base.getfield(x, f)::Matrix{Float64}
└── return %2

```

but I’m not sure why it’s not inferred in the multiplication.

---

<div class="post-metadata">

**Author:** ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)\
**Post date:** [September 30, 2021, 11:10am UTC](https://discourse.julialang.org/t/why-is-the-type-of-factors-not-being-inferred-while-multiplying-an-abstractq-with-a-vector/68981/2 "2021-09-30T11:10:07Z")

</div>

I imagine this is from running in global scope with global variables. If you put it inside a function it seems to infer it all fine.

```julia
f(q,a) = q.Q * a
@code_warntype f(Q,rand(size(Q.Q,2))
       )
MethodInstance for f(::LinearAlgebra.QRCompactWY{Float64, Matrix{Float64}}, ::Vector{Float64})
  from f(q, a) in Main at REPL[4]:1
Arguments
  #self#::Core.Const(f)
  q::LinearAlgebra.QRCompactWY{Float64, Matrix{Float64}}
  a::Vector{Float64}
Body::Vector{Float64}
1 ─ %1 = Base.getproperty(q, :Q)::LinearAlgebra.QRCompactWYQ{Float64, Matrix{Float64}}
│ %2 = (%1 * a)::Vector{Float64}
└── return %2

```

---

<div class="post-metadata">

**Author:** ![jishnub](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/jishnub/32/33620_2.png) [@jishnub](https://discourse.julialang.org/u/jishnub)\
**Post date:** [September 30, 2021, 11:14am UTC](https://discourse.julialang.org/t/why-is-the-type-of-factors-not-being-inferred-while-multiplying-an-abstractq-with-a-vector/68981/3 "2021-09-30T11:14:45Z")

</div>

I’m not sure if this is doing anything different, as the result of the multiplication is inferred anyway and the intermediate steps are hidden here.

---

<div class="post-metadata">

**Author:** ![gbaraldi](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/gbaraldi/32/22101_2.png) [@gbaraldi](https://discourse.julialang.org/u/gbaraldi)\
**Post date:** [September 30, 2021, 11:39am UTC](https://discourse.julialang.org/t/why-is-the-type-of-factors-not-being-inferred-while-multiplying-an-abstractq-with-a-vector/68981/4 "2021-09-30T11:39:00Z")

</div>

Sorry, it’s a bit early, I checked with Cthulu and it’s the same for my `f` but then I looked correctly, the place where it isn’t inferring is the error handling. If you check the lines with `::Any` they are a part of `5` block. and on the block 3 there is a `goto #5` if there is a dimension mismatch, so it shouldn’t matter.
