Preventing dispatch on val not bits

Val is mainly use to dispatch on bits type with static optimization.

It’s rather simple to do a coding error and dispatch on Val(:foo) that is not a bits type instance.

Is it possible that the compiler emits a warning in such case ?

Are you asking about doing this in general or doing it for your code?

In general, no, it won’t be done since how you use it is definately the only way it can be used.

For you code, well, sure, just check if it’s a symbol and throw an error or print a warning.

FWIW though, this kind of warning are the most useless. If this should never be done then it should be an error and if it could be done it must not be an warning at all unless there’s a way to explicitly disable the warning in the code.

1 Like

Typical functions all have their own types. sin is the only instance of typeof(sin); it’s a singleton. The value contains no data (sizeof(sin) == 0) and is immutable, so it’s a bits type.

Interesting clarification @ https://github.com/JuliaLang/julia/issues/32541#issuecomment-510179255

In fact Val is not a bits type by itself

@test isbitstype(Val{T} where T) == false

But becomes one when is arg is specified (even with a non bits param like a symbol)

@test sizeof(Val{:a}) == 0                                  # has no data
@test Val{:a}() == Val{:a}()                                # is singleton
@test Base.unwrap_unionall(Val).mutable == false            # is immutable

@test isbitstype(Val{:a})

@test isbits(:a) == false                                   # param is not bits

So the compiler could statically optimize dispatch
That has puzzled me times ago

Well, I’m not sure what you are trying to say here… But a few things to clarify.

Val is not a concrete type so it cannot be a bits type. In fact, anything that you can apply type arguments to aren’t bits type.

The type parameter never has any effect on the isbit-ness of a type. Only the fields do. You can add unused type parameters to types and you can put whatever you want that’s allowed as type parameters in there without any effect on the isbit-ness of the type. Also note that a type (DataType) itself is not isbit anyway.

And finally,

Actually has nothing to do with the isbit-ness of anything.

3 Likes

Actually has nothing to do with the isbit-ness of anything.

Your comment belong to you in regard to the definition of Val in docs

Val(c)

Return Val{c}(), which contains no run-time data. Types like this can be used to pass the information between functions through the value c, which must be an isbits value. The intent of this construct is to be able to dispatch on constants directly (at compile time) without having to test the value of the constant at run time.

https://docs.julialang.org/en/v1/base/base/#Base.Val

Please read the doc string you pasted carefully. It seems that you made a lot of assumptions when reading it which is why you are confused.

This is wrong (over-simplified). As you see above, c does not have to be a isbit value. (Notet that here I belive the “which” is talking about c.) This point is related to this thread but isn’t realted to what I meant by “Actually has nothing to do with the isbit-ness of anything.”

And still, this is a specific document about Val and whatever it says should have no significance regarding why some properties are related to optimization or not. In particuclar, even though it happens to be a isbit type and the compiler could sometimes “statically optimize dispatch” when passing it around, the two have absolutely no relation with each other.

Also, the doc doesn’t even say the isbit-ness has anything to do with any optimization. It mentions two properties of the type and you shouldn’t assume one of them causes another. The two sentence didn’t imply that and it’s also not the case.

1 Like