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

Foo{<:Any} accepts non-type parameters #52201

Open
stevengj opened this issue Nov 17, 2023 · 12 comments
Open

Foo{<:Any} accepts non-type parameters #52201

stevengj opened this issue Nov 17, 2023 · 12 comments

Comments

@stevengj
Copy link
Member

This behavior, pointed out on discourse, seems like a bug (violating the documented meaning of <:):

julia> Val{<:Any} == (Val{T} where {T<:Any}) == Val{T} where T
true

julia> 1<:Any
ERROR: TypeError: in <:, expected Type, got a value of type Int64
...
julia> Val{1} <: Val{<:Any} # 1<:Any is not checked
true

julia> Val{1} <: Val{<:Number} # 1<:Number is checked
false
@stevengj stevengj changed the title Foo{<:Any} accepts non-type parameters in function arguments Foo{<:Any} accepts non-type parameters Nov 17, 2023
@DilumAluthge
Copy link
Member

Duplicate of #9580?

@stevengj
Copy link
Member Author

If we actually want(?) this behavior, it should be documented.

@DilumAluthge
Copy link
Member

Should we reopen #9580?

@mkitti
Copy link
Contributor

mkitti commented Nov 17, 2023

Why was the other issue closed? @vtjnash ? Did we fix it somehow on nightly?

@giordano
Copy link
Contributor

If we actually want(?) this behavior, it should be documented.

Isn't it documented at https://docs.julialang.org/en/v1/manual/types/

Both abstract and concrete types can be parameterized by other types. They can also be parameterized by symbols, by values of any type for which isbits returns true (essentially, things like numbers and bools that are stored like C types or structs with no pointers to other objects), and also by tuples thereof. Type parameters may be omitted when they do not need to be referenced or restricted.

? There are a few other references to the fact isbits values can be used as parameters throughout the page. Or am I missing what you're referring to?

@jishnub
Copy link
Contributor

jishnub commented Nov 17, 2023

I think the documentation refers to Foo{x} and doesn't adequately address Foo{x<:Any}. In fact, it shows that the following doesn't work:

julia> struct Foo2{x<:Real} end

julia> Foo2{2}()
ERROR: TypeError: in Foo2, in x, expected x<:Real, got a value of type Int64

so the fact that this works for Any may be a bit counterintuitive.

@mkitti
Copy link
Contributor

mkitti commented Nov 17, 2023

I believe the issue is that non-types will match <: Any.

For values, I think we should use type assertion syntax. ::Any.

struct Foo{::Any}
end

or

struct Foo2{::Real}
end

Of course we can already enforce this via an inner constructor using a type assertion.

struct Foo3{T}
    Foo3{T}() where T= new{T::Real}()
end

Foo2 should lower to Foo3.

<: Any as it works now should be documented and deprecated for allowing values.

@nsajko
Copy link
Contributor

nsajko commented Nov 17, 2023

Foo2 should lower to Foo3.

That would mislead users to think the constraint applies to the type itself, when it only applies to some of the type's instances.

@mkitti
Copy link
Contributor

mkitti commented Nov 17, 2023

Foo2 should lower to Foo3.

That would mislead users to think the constraint applies to the type itself, when it only applies to the type's instances.

I'm not sure I see your point. :: always applies to the types of instances.

@nsajko
Copy link
Contributor

nsajko commented Nov 17, 2023

The inner constructor can only enforce anything upon the instances of a type, not on the type itself. Furthermore, there are ways, such as similar or incomplete initialization, of bypassing an inner constructor completely.

@frankwswang
Copy link
Sponsor

frankwswang commented Mar 8, 2024

I don't know whether to laugh or cry that this fundamental issue of Julia's type system in the case of type parameters has been rediscovered by yet another user.

The initial issue #9580 is already more than 9 years old... I would love to help in any way I can to move things forward, but we need the core dev(s) to provide a unified and appropriate solution first. Otherwise, we are stuck with what we face.

Please at least reopen the issue so that people are properly exposed to it. Regardless of if it's considered a bug of the language, keeping the issue closed is a negative attitude.

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

7 participants