-
Notifications
You must be signed in to change notification settings - Fork 983
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
[naga wgsl-in] Allow abstract literals to be used as return values #7035
base: trunk
Are you sure you want to change the base?
Conversation
1197e90
to
3ee156d
Compare
8b6fa54
to
1405042
Compare
naga/src/front/wgsl/lower/mod.rs
Outdated
let mut ctx = ctx.as_expression(block, &mut emitter); | ||
let mut expr_ty = resolve_inner!(ctx, expr); | ||
while let crate::TypeInner::Array { base, .. } = *expr_ty { | ||
expr_ty = &ctx.module.types[base].inner; | ||
} | ||
if expr_ty.scalar().is_some_and(|s| s.is_abstract()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jimblandy I'm avoiding calling try_automatic_conversions()
here for non-abstract types, as otherwise I saw in one of the tests that this code:
@group(0) @binding(0)
var<storage> atom: atomic<u32>;
fn return_atomic() -> atomic<u32> {
return atom;
}
used to fail with this error:
┌─ in.wgsl:4:1
│
4 │ ╭ fn return_atomic() -> atomic<u32> {
5 │ │ return atom;
│ ╰──────────────^ naga::Function [0]
│
= The function's given return type cannot be returned from functions
but would now fail with:
Could not parse WGSL:
error: automatic conversions cannot convert `u32` to `atomic<u32>`
┌─ in.wgsl:4:10
│
4 │ return atom;
│ ^^^^ this expression has type u32
which is less clear.
Would it make sense to have this check as part of try_automatic_conversions()
? Do we ever convert from things that are not abstract?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that's a nice kludge. Eventually we'll want to run constant evaluation after validation, which should simplify the code and allow the diagnostics to work out properly, too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Okay so I tried moving the kludge to inside try_automatic_conversions()
itself. It causes quite a few more test failures due to changing error messages. eg Anywhere that we call try_automatic_conversion()
then map_err()
from AutoConversionError
to IntializationTypeMismatch
.
Take for example:
fn main() {
var x: f32 = 1u;
}
This currently gives the error message:
Could not parse WGSL:
error: the type of `x` is expected to be `f32`, but got `u32`
┌─ in.wgsl:2:9
│
2 │ var x: f32 = 1u;
│ ^ definition of `x`
But with this kludge applied in try_automatic_conversions:
error: Function [0] 'foo' is invalid
┌─ in.wgsl:1:1
│
1 │ ╭ fn foo() {
2 │ │ var x: f32 = 1u;
│ │ ^^^^^^^^^^^^^^^^ naga::LocalVariable [0]
│ ╰────────────────────^ naga::Function [0]
│
= Local variable [0] 'x' is invalid
= Initializer doesn't match the variable type
Keeping the kludge only for return values seems wrong to me. So that leaves the options:
a) no kludge. Update one test. Make the error message worse for incorrect return types as mentioned above (perhaps other cases too that we don't know about)
b) kludge in try_automatic_conversion. update half a dozen tests. Make the error message arguably worse for several cases.
What do you think @jimblandy ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I updated the PR to avoid the kludge altogether, and update the test to expect the slightly less descriptive error message when the function has the atomic
return type.
I think that's the least bad option for now, and we can always iterate to improve on error messages. But let me know if you'd prefer I go another route in this PR.
1405042
to
07530bf
Compare
07530bf
to
5006ab6
Compare
When lowering a return statement, call expression_for_abstract() rather than expression() to avoid concretizing the return value. Then, if the function has a return type, call try_automatic_conversions() to attempt to convert our return value to the correct type. This has the unfortunate side effect that some errors that would have been caught by the validator are instead encountered as conversion errors by the parser. This may result in a slightly less descriptive error message in some cases. (See the change to the invalid_functions() test, for example.)
5006ab6
to
45dbeb6
Compare
Description
Currently we
concretize()
return values via callingexpression()
, meaning this works fine:as we concretize the
1
to ani32
, which is the function return type. But this does not:as we concretize the
1
to ani32
, which does not match thef32
return type.We can fix this by calling
expression_for_abstract()
which does not concretize, then callingtry_automatic_conversions()
to attempt to convert the abstract type to the return type.Testing
Added some snapshot tests
Checklist
cargo fmt
.cargo clippy
. If applicable, add:cargo xtask test
to run tests.CHANGELOG.md
. See simple instructions inside file.