Skip to content

Incorrectly Inferred Return type #30394

Closed
@JaredCrean2

Description

@JaredCrean2

From Discourse

Example code:

abstract type AbstractFoo end

mutable struct FooBase <: AbstractFoo
  a::Int
  # no foo_inner: terminates any recursion
end


mutable struct Foo1 <: AbstractFoo
  foo_inner::FooBase

  function Foo1()
    return new(FooBase(1))
  end
end

mutable struct Foo2 <: AbstractFoo
  foo_inner::Foo1

  function Foo2()
    return new(Foo1())
  end
end


mutable struct Foo3 <: AbstractFoo
  foo_inner::Foo2

  function Foo3()
    return new(Foo2())
  end
end


mutable struct Foo4 <: AbstractFoo
  foo_inner::Foo3

  function Foo4()
    return new(Foo3())
  end
end



# T1 <: T2 implies T1 == T2 as long as all T1 and T2 are concrete
function getInnerFoo(foo::T1, ::Type{T2}) where {T2 <: AbstractFoo, T1 <: T2}
  return foo
end

function getInnerFoo(foo::T1, ::Type{T2}) where {T1 <: AbstractFoo, T2 <: AbstractFoo}
  return getInnerFoo(foo.foo_inner, T2)
end

obj = Foo4()

obj2 = getInnerFoo(obj, Foo2)
println("typeof(obj2) = ", typeof(obj2))
@code_warntype getInnerFoo(obj, Foo2)

On Julia 0.6.2, the output is:

typeof(obj2) = Foo2
Variables:
  #self# <optimized out>
  foo::Foo4
  #unused# <optimized out>

Body:
  begin 
      return foo::Foo4
  end::Foo4
Variables:
  #self# <optimized out>
  foo::Foo4
  #unused# <optimized out>

Body:
  begin 
      return (Main.getInnerFoo)((Core.getfield)(foo::Foo4, :foo_inner)::Foo3, $(Expr(:static_parameter, 2)))::Foo3
  end::Foo3

The typeof line shows obj2 is of type Foo2, but code_warntype infers it to be Foo3. Similar result on Julia 1.0.1.

Metadata

Metadata

Assignees

Labels

bugIndicates an unexpected problem or unintended behavior

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions