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

Test.has_unbound_vars should show some respect for history #28086

Open
timholy opened this issue Jul 12, 2018 · 4 comments
Open

Test.has_unbound_vars should show some respect for history #28086

timholy opened this issue Jul 12, 2018 · 4 comments
Labels
domain:types and dispatch Types, subtyping and method dispatch testsystem The unit testing framework and Test stdlib

Comments

@timholy
Copy link
Sponsor Member

timholy commented Jul 12, 2018

EDIT: it's not entirely obvious this is a bug. Below the key comparison is reduced to

foo1(::Type{Tuple{R1,Vararg{R1,N}}}) where {N,T1,R1<:AbstractUnitRange{T1}}

vs

foo2(::Type{NTuple{N,R1}}) where {N,T1,R1<:AbstractUnitRange{T1}}

I think that what this really comes down to is

julia> Tuple{} <: NTuple{0, T} where T<:AbstractUnitRange
true

original post

julia> using Test

julia> foo(::Type{NTuple{N,R1}}, ::Type{NTuple{N,R2}}) where {N,R1<:AbstractUnitRange{T1},R2<:AbstractUnitRange{T2}} where {T1,T2} =
           NTuple{N,promote_type(R1,R2)}
foo (generic function with 1 method)

julia> m = first(Base.MethodList(typeof(foo).name.mt))
foo(::Type{Tuple{Vararg{R1,N}}}, ::Type{Tuple{Vararg{R2,N}}}) where {T1, T2, N, R1<:AbstractUnitRange{T1}, R2<:AbstractUnitRange{T2}} in Main at REPL[2]:1

julia> Test.has_unbound_vars(m.sig)
true

I think it's fair to say that method definition does not have unbound typevars. I am guessing this is a consequence of the loop dropping old typevars.

@vtjnash
Copy link
Sponsor Member

vtjnash commented Jul 12, 2018

I'm not entirely sure what you mean. The test is (correctly) detecting that the value of T1 and R1 are not necessarily known:

julia> foo(::Type{NTuple{N,R1}}) where {N, T1, R1<:AbstractUnitRange{T1}} = T1

julia> foo(Tuple{})
ERROR: UndefVarError: T1 not defined
Stacktrace:
 [1] foo(::Type{Tuple{}}) at ./REPL[1]:1
 [2] top-level scope at none:0

julia> foo2(::Type{NTuple{N,R1}}) where {N, R1<:AbstractUnitRange} = R1
foo2 (generic function with 1 method)

julia> foo2(Tuple{})
ERROR: UndefVarError: R1 not defined
Stacktrace:
 [1] foo2(::Type{Tuple{}}) at ./REPL[5]:1
 [2] top-level scope at none:0

A more relevant case might be:

julia> foo4(::Type{Tuple{R1}}) where {T1, R1<:AbstractUnitRange{T1}} = T1
foo4 (generic function with 1 method)

Since here, we know that T1 is constrained by UnionAll.var, as long as that R1 is constrained.

There does appear to be a possible dispatch bug here though:

julia> foo3(::Type{Tuple{R1}}) where {R1<:AbstractUnitRange} = R1

julia> foo3(Tuple{UnitRange{T}} where T<:Int)
ERROR: MethodError: no method matching foo3(::Type{Tuple{UnitRange{T}} where T<:Int64})
Closest candidates are:
  foo3(::Type{Tuple{R1<:AbstractUnitRange}}) where R1<:AbstractUnitRange at REPL[9]:1
Stacktrace:
 [1] top-level scope at none:0

julia> foo3(Tuple{UnitRange{T} where T<:Int})
UnitRange{#s1} where #s1<:Int64

@timholy
Copy link
Sponsor Member Author

timholy commented Jul 12, 2018

Note that in my example, I used that "more relevant case" since I had R1<:AbstractUnitRange{T1}. Let me write it differently:

julia> using Test

julia> foo1(::Type{Tuple{R1}}, ::Type{Tuple{R2}}) where {T1,T2,R1<:AbstractUnitRange{T1},R2<:AbstractUnitRange{T2}} = nothing
foo1 (generic function with 1 method)

julia> fooN(::Type{NTuple{N,R1}}, ::Type{NTuple{N,R2}}) where {N,T1,T2,R1<:AbstractUnitRange{T1},R2<:AbstractUnitRange{T2}} = nothing
fooN (generic function with 1 method)

julia> m1 = first(Base.MethodList(typeof(foo1).name.mt))
foo1(::Type{Tuple{R1}}, ::Type{Tuple{R2}}) where {T1, T2, R1<:AbstractUnitRange{T1}, R2<:AbstractUnitRange{T2}} in Main at REPL[2]:1

julia> Test.has_unbound_vars(m1.sig)
false

julia> mN = first(Base.MethodList(typeof(fooN).name.mt))
fooN(::Type{Tuple{Vararg{R1,N}}}, ::Type{Tuple{Vararg{R2,N}}}) where {N, T1, T2, R1<:AbstractUnitRange{T1}, R2<:AbstractUnitRange{T2}} in Main at REPL[3]:1

julia> Test.has_unbound_vars(mN.sig)
true

But it actually doesn't seem to have anything to do with multiple args:

julia> fooN1(::Type{NTuple{N,R1}}) where {N,T1,R1<:AbstractUnitRange{T1}} = nothing
fooN1 (generic function with 1 method)

julia> mN1 = first(Base.MethodList(typeof(fooN1).name.mt))
fooN1(::Type{Tuple{Vararg{R1,N}}}) where {N, T1, R1<:AbstractUnitRange{T1}} in Main at REPL[8]:1

julia> Test.has_unbound_vars(mN1.sig)
true

This fixes it:

julia> fooN1b(::Type{Tuple{R1,Vararg{R1,N}}}) where {N,T1,R1<:AbstractUnitRange{T1}} = nothing
fooN1b (generic function with 1 method)

julia> mN1b = first(Base.MethodList(typeof(fooN1b).name.mt))
fooN1b(::Type{Tuple{R1,Vararg{R1,N}}}) where {N, T1, R1<:AbstractUnitRange{T1}} in Main at REPL[16]:1

julia> Test.has_unbound_vars(mN1b.sig)
false

@timholy timholy added the domain:types and dispatch Types, subtyping and method dispatch label Jul 12, 2018
@timholy
Copy link
Sponsor Member Author

timholy commented Jul 12, 2018

I'm now thinking this isn't a bug (see edited OP). I'll close it, but re-open if you think there is still something here.

@timholy timholy closed this as completed Jul 12, 2018
@vtjnash
Copy link
Sponsor Member

vtjnash commented Jul 12, 2018

You're still right that my foo4 function isn't handled right by this

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
domain:types and dispatch Types, subtyping and method dispatch testsystem The unit testing framework and Test stdlib
Projects
None yet
Development

No branches or pull requests

2 participants