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
Requiring integral-valued float literals to have .0 seems gratuitous #739
Comments
With #723 this would require a suffix on int and uint literals ( |
cc #575 |
Also GLSL requires . or .0 on floats. |
What does it mean if I do I believe you can do |
This restriction reduces the attack surface. |
There is a tricky conflation getting missed here between:
Constructors are explicit conversions, between the arguments and the result type. So, even in flavors of GLSL that disallow implicit conversions, you can still make a float vector from integers:
You need to address the subject of implicit conversions outside of constructors separately from whether they are allowed inside constructors. In trying to be lower-level, with fewer complexities to impact portability, I assume WGSL will not allow implicit conversions in general, but must then still state exactly what operations are counted as being explicit conversions. This gets more tricky when you want to start saying that some constructors count as explicit converters and some do not. That's why GLSL just says all constructors request explicit conversions. |
A compromise with usability, BTW, has often been requested, which is to treat literals differently:
|
There’s another possible solution here Edit: looks like @kainino0x already listed this |
Really? Is that from the tokenizer (meaning standalone versus accounting for context) saying it's a float?
[edited due to premature send] |
My intent was that it would be from the tokenizer. |
If undecorated numbers are always 32-bit floats, we should probably disallow integer-style literals of magnitude greater than 224 − 1 = |
On the topic of having a "special" literal type, FWIW here's what Rust does: fn use_i32(x: i32) {}
fn use_u32(x: u32) {}
fn main() {
{
let x = 1; // x has no concrete type yet
use_i32(x); // causes x to be inferred as i32
use_u32(x); // error (expected u32, found i32)
}
{
let x = 1; // x has no concrete type yet
use_u32(x); // causes x to be inferred as u32
use_i32(x); // error (expected i32, found u32)
}
} Obviously I don't support doing this in WGSL since it's quite complicated. |
This was discussed at the 2020-05-12 meeting. |
In Go, this discussion of literals extends to constants. Both literals and constants are untyped and evaluations take place in an infinite-precision context. See https://blog.golang.org/constants |
Here's a proposal for generic literals: Goals
TypesSome literals have a generic type, and some literals have a concrete type.
Every generic type has an associated “preferred” concrete type. The preferred type for GenericLooksLikeInt is “32-bit signed integer.” The preferred type for GenericLooksLikeFloat is “float.” Unification RulesThere are a few specific situations, listed below, where a generic type may be unified with a concrete type. There is no situation where a generic type can be unified with a generic type. Here are the unification rules:
As a general principle, for every literal of generic type G, for every concrete type C, if G can unify with C, then it should be possible to add a suffix (or prefix??) to that literal to cause it to have concrete type C. Unification SituationsAssuming
After performing all the unifications possible in the above situations, if a generic type remains in the program, it assumes its preferred type. For example, This last rule about a literal assuming its preferred type may be confusing to authors - it means that Unification Non-situationsI went through the grammar and found all the places where a literal can show up. The remaining places where a literal won’t be unified are:
|
I don't understand this line; if you don't perform the unification then the variable now has type GenericLooksLikeX? But it sounds like we don't want that to be possible (for very good reason). Overall, while, for usability, I generally like when a language has this feature, I think it's much too complex for WGSL (especially the (very important) rules on unifications with overloads/operators). I really don't think typing |
Implicit typing is something I'd like us to steer away as much as possible. The proposed integer and float literals are useful though, for using in contexts where their expected types are well known and understood, i.e. I don't think it's worth trying to support |
The key is this part:
It means if the program says |
@kvark I don't think there's value in adding an inference mechanism to the language just to allow |
@kainino0x
I expressed concerns over complicating the notion of "context", e.g for arithmetic expressions of literals ( |
Sorry, what I'm proposing is that literals' types never depend on context.
|
@kainino0x that would be wonderful. I just cringe a little bit at the |
Discussed at the 2020-06-16 meeting. |
Resolution: General agreement to the proposal above. @litherum will turn it into a PR. |
I am not in "general agreement".
To me the cost and potential for confusion outweighs the purported benefits. For lots of other reasons, users have to understand that values belong to specific types. Forcing you to write what you mean, explicitly, is highly beneficial to clarity. And the short letter suffixes that we seem to be assuming, seems to me very cheap. |
This is a complex topic and is taking a lot of time. I don't think it ought to be a blocker for MVP. Can we come up with a futureproof middle ground for now so we can make progress on actual functionality? Here's a proposal:
|
+1 to Kai's suggestion. It seems like a solid base that could be expanded after MVP but without the possibility we'd have to walk anything back. |
I like the follow Kai's suggestion as well. It has a problem though: it introduces the type suffixes. They duplicate the semantic of the types. |
That's only a problem if (1) we don't want to have type suffixes at all (why wouldn't we?) and (2) we end up with a solution where |
Well, that's something to consider (not necessarily my position!). The question should be the opposite: why having the suffixes if we don't have to? Removing them later would be more difficult.
I don't see it as an overload. It's just a generic function, |
If you treat it like a regular templated function, it is overloaded on the input type ( |
|
It seems like there's still significant more discussion to be had here; I'll hold off on making a pull request until we (the CG) know the direction we'd like to be heading. |
They are the suffixes found in Rust. The slightly inconvenient spelling is why I suggested, "Optionally, We're talking about an explicit syntax for users to use when they want it, and also for making WGSL possible to use before we have a nicer solution. I am not worried about it being a little verbose. |
WGSL meeting minutes 2021-06-29
|
One of our internal teams is hitting this, for both |
fixed by #2227 |
…web#739) * Add operation tests on CopyTextureToTexture with multisampled color textures * Add comments * Address reviewer's comments * Fix [[builtin(position)]] in fragment shader * Revert "Fix [[builtin(position)]] in fragment shader" This reverts commit 39719ab2273e1bc4b6446c1ce80262742fac15db.
It's really common for shaders to have things like
float4(1, 2, 3, 4)
rather thanfloat4(1.0, 2.0, 3.0, 4.0)
. Given that most operations in shaders are floating point operations, it seems gratuitous to require the extra two characters.The text was updated successfully, but these errors were encountered: