Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

splatting is type-unstable with parametric type argument #22327

Closed
cstjean opened this issue Jun 10, 2017 · 6 comments
Closed

splatting is type-unstable with parametric type argument #22327

cstjean opened this issue Jun 10, 2017 · 6 comments

Comments

@cstjean
Copy link
Contributor

cstjean commented Jun 10, 2017

Perhaps that's not its strictly-intended usage, but I've found it useful to temporarily pepper my code with @inferred to catch type-instabilities. Unfortunately, it seems that the output of @inferred can be type-unstable (0.6, rc2), which is an issue for checking the type-stability of heterogeneous tree traversal algorithms.

struct AA{A}
   a::A
end

struct CC{A}
    a::A
end

my_construct(::Type{AA}, a) = 1
my_construct(::Type{CC}, a) = 1.0

foo(x) = @inferred my_construct(CC, x.a)

@inferred foo(CC(2))   #return type Float64 does not match inferred return type Union{Float64, Int64}
@yuyichao yuyichao changed the title @inferred is type-unstable with parametric type argument splatting is type-unstable with parametric type argument Jun 10, 2017
@yuyichao
Copy link
Contributor

yuyichao commented Jun 10, 2017

my_construct(::Type{Complex}, a) = 1
my_construct(::Type{Array}, a) = 1.0

function foo(x)
    args = (Array, x)
    my_construct(args...)
end

@code_warntype foo(1)

@JeffBezanson
Copy link
Member

@inferred is not really designed for this; for this use I think we'd want something that's a no-op at run time but that throws an error at compile time if the wrapped expression couldn't be precisely inferred.

@cstjean
Copy link
Contributor Author

cstjean commented Jun 10, 2017

That would be great!

@tkelman
Copy link
Contributor

tkelman commented Jun 10, 2017

aka #10980 ?

@martinholters
Copy link
Member

martinholters commented Jun 12, 2017

julia> function foo(x)
           args = (Array, x)
           args[1]
       end
foo (generic function with 1 method)

julia> @code_warntype foo(1)
Variables:
  #self#::#foo
  x::Int64
  args::Any

Body:
  begin
      SSAValue(0) = Main.Array
      SSAValue(1) = x::Int64
      #= line 3 =#
      return SSAValue(0)
  end::UnionAll

julia> function foo(x)
           args = (Array, 1)
           args[1]
       end
foo (generic function with 1 method)

julia> @code_warntype foo(1)
Variables:
  #self#::#foo
  x::Int64
  args::Any

Body:
  begin
      SSAValue(0) = Main.Array
      #= line 3 =#
      return SSAValue(0)
  end::Type{Array}

So unless args can be inferred as Const, args[1] is inferred as typeof(Array) == UnionAll instead of Type{Array}. That's because of the check in this line. Unfortunately, the reason it was introduced back in afd4eb0 is anything but clear to me. Do we actually still need that?

EDIT:
We do:

julia> typeof((Array,1))
Tuple{UnionAll,Int64}

Inferring that as Type{Tuple{Type{Array}, Int64} is obviously a bad idea.

@Keno
Copy link
Member

Keno commented Jul 15, 2020

This is fixed.

@Keno Keno closed this as completed Jul 15, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants