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

[naga] parse and validate @must_use attribute #6801

Open
wants to merge 7 commits into
base: trunk
Choose a base branch
from

Conversation

turbocrime
Copy link
Contributor

@turbocrime turbocrime commented Dec 21, 2024

ready for review

to be revised now that i can run conformance tests

not worrying about conformance tests, as cts_runner seems disused.


Connections

initial work on #5186

Description

When the wgsl parser encounters the @must_use function attribute, it should not error.

This PR will recognize the attribute and emit a new field in function AST. Both the parser and the validator stage will use this attribute.

The parser requires that the annotated function should return a value, and requires that the function call appears in an expression.

The validator requires that return value is referenced or assigned.

A few tests are added covering these behaviors and more.

Testing

  • tested with wgpu test suite
  • tested by building Firefox nightly with this change

Checklist

  • Run cargo fmt.
  • Run taplo format.
  • Run cargo clippy. If applicable, add:
    • --target wasm32-unknown-unknown
    • --target wasm32-unknown-emscripten
  • Run cargo xtask test to run tests.
  • Add change to CHANGELOG.md. See simple instructions inside file.

@turbocrime turbocrime force-pushed the turbocrime/must_use branch 2 times, most recently from 17da613 to 1331f0f Compare December 22, 2024 00:00
@turbocrime turbocrime changed the title parse @must_use attribute [naga] parse @must_use attribute Dec 22, 2024
@turbocrime
Copy link
Contributor Author

Looking at discussion in the gpuweb repository linked in the issue, it seems like

  • wgsl builtins may have the attribute must_use
  • a wgsl compiler should reject bare calls to must_use
  • must_use validation should happen at compile-time and not at run-time

I expect that many particularities may complicate validation, so tests are provided for slightly complex valid examples.

I'm unfamiliar with how naga's AST behaves, and looking through the validation code, it didn't seem obvious where/how to validate that a CallResult is 'used', and what qualifies as 'used'.

@turbocrime turbocrime marked this pull request as ready for review December 22, 2024 00:32
@turbocrime turbocrime requested a review from a team as a code owner December 22, 2024 00:32
@turbocrime
Copy link
Contributor Author

turbocrime commented Dec 22, 2024

Are there likely to be important validation differences between constant and variable values?

Copy link
Contributor Author

@turbocrime turbocrime left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

some commentary

Comment on lines 114 to 118
pub struct FunctionResult<'a> {
pub ty: Handle<Type<'a>>,
pub binding: Option<Binding<'a>>,
pub must_use: bool,
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

must_use is a required member of wgsl ast FunctionResult.

Comment on lines +2386 to +2392
Some(ast::FunctionResult {
ty,
binding,
must_use,
})
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ast::FunctionResult creations are updated

@@ -2455,6 +2460,7 @@ impl Parser {
let (mut bind_index, mut bind_group) =
(ParsedAttribute::default(), ParsedAttribute::default());
let mut id = ParsedAttribute::default();
let mut must_use = ParsedAttribute::default();
Copy link
Contributor Author

@turbocrime turbocrime Dec 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

attribute is handled in global_decl

is there another location in which @must_use might validly appear?

should invalid locations recognize the attribute at all?

possibly, some global declarations should not have the @must_use attribute. no checks are performed.

@@ -2333,6 +2333,7 @@ impl Parser {
diagnostic_filter_leaf: Option<Handle<DiagnosticFilterNode>>,
out: &mut ast::TranslationUnit<'a>,
dependencies: &mut FastIndexSet<ast::Dependency<'a>>,
must_use: bool,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

i added a parameter to function_decl for this attribute.

naga/tests/in/must-use-questionable.wgsl Outdated Show resolved Hide resolved
@turbocrime turbocrime marked this pull request as draft December 24, 2024 19:26
@ErichDonGubler ErichDonGubler self-assigned this Dec 28, 2024
@ErichDonGubler ErichDonGubler self-requested a review December 28, 2024 13:05
@turbocrime
Copy link
Contributor Author

i'm going to revise this now that i can run conformance tests after #6840

it is not presently ready for review

sagudev added a commit to sagudev/servo that referenced this pull request Jan 1, 2025
Signed-off-by: sagudev <[email protected]>
sagudev added a commit to sagudev/servo that referenced this pull request Jan 1, 2025
{"fail_fast": false, "matrix": [{"name": "WebGPU CTS", "workflow": "linux", "wpt_layout": "2020", "profile": "production", "unit_tests": false, "bencher": false, "wpt_args": "_webgpu"}]}
@sagudev
Copy link
Contributor

sagudev commented Jan 1, 2025

i'm going to revise this now that i can run conformance tests after #6840

Unfortunately am not sure how relevant information from cts_runner actually is, as there is no concept of (bad) expectations (so only selected tests are run) and it uses old CTS version. The most useful results come from browsers running CTS, either Firefox or Servo as both run all test and have expectations properly set, so you know what results become different using your PR.

In servo you can simply override wgpu in Cargo.toml (ensuring that your PR bases from same revision of wgpu previous used in servo) then run ./mach try webgpu in servo folder to trigger CI run of CTS in GitHub Actions. I did initial CTS run for this PR here: https://github.com/sagudev/servo/actions/runs/12568503599/attempts/1#summary-35037584122 (note that there are some flaky crashes in webgpu:shader,execution,expression due to cyclic JS imports, so you can ignore them).

@turbocrime
Copy link
Contributor Author

turbocrime commented Jan 1, 2025

yes, realizing this since i patched things together. i was hoping to have canonical tests for edge cases and ambiguities, that could execute in a nice automated way, but it seems like the validation tests can't run in cts_runner without more api work.

maybe this repo should remove cts_runner and the documentation that suggests using it, if it's no longer relevant.

thanks for the instructions for executing in servo's ci! this is very useful

@jamienicol
Copy link
Contributor

jamienicol commented Jan 17, 2025

I've ran the CTS without and with this in firefox and it looks good. There are no new failures, and there are a few new passes as expected. There are also quite a few more places where previously we failed due to parsing error: unknown attribute: must_use, but with that fixed now we fail for another reason. (Seems to be type conversion mostly AFAICS)

As you noted above this does have the limitation that it doesn't ensure the result of @must_use builtin functions are actually used. But let's not let perfect be the enemy of good. We can save that for a follow-up. I think this is mostly ready to go.

@turbocrime do you still have changes planned for this, or would you like me to review as-is? Or if you're too busy I'm happy to take this over the line for you. LMK!

Comment on lines +1483 to +1511
#[test]
#[ignore = "validation can't be tested if parser fails"]
fn must_use_unused_validation() {
check_validation! {
"
@must_use
fn use_me(a: i32) -> i32 {
return 10;
}

fn useless() -> i32 {
use_me(1);
return 0;
}
":
Err(
naga::valid::ValidationError::Function {
handle: _caller,
name: caller_name,
source: naga::valid::FunctionError::InvalidCall {
function: _callee,
error: naga::valid::CallError::ResultNotUsed(_result),
},
},
)
if caller_name == "useless"
}
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure how to test validation if the parser will reject the shader. perhaps i could manually create the AST by parsing a shader without the attribute and then modifying it.

@turbocrime
Copy link
Contributor Author

turbocrime commented Jan 18, 2025

As you noted above this does have the limitation that it doesn't ensure the result of @must_use builtin functions are actually used. But let's not let perfect be the enemy of good. We can save that for a follow-up. I think this is mostly ready to go.

i assume the builtins aren't presently 'annotated'. if must_use builtins are expressed correctly in AST, perhaps validation phase can catch that.

validation code is present and works if i remove the parser error, but i'm not sure how to test it when the parser throws. i'm not sure if the validation code is actually useful - would the parser know about builtins' attributes at parsing time? will the parsing step ever be skipped? do we care about that validation if the parsing step is skipped?

@turbocrime do you still have changes planned for this, or would you like me to review as-is? Or if you're too busy I'm happy to take this over the line for you. LMK!

i had a local commit sitting around that reverted some random junk. pushed that up, ready for you to take a look.

i will have way less free time starting monday so feel free to take over.

@turbocrime turbocrime marked this pull request as ready for review January 18, 2025 00:50
@turbocrime
Copy link
Contributor Author

if you'd like to see the validation phase successfully detect an unused call, see f028d07 where i have disabled the parser failures

@turbocrime
Copy link
Contributor Author

turbocrime commented Jan 18, 2025

this is covered by the parser, but perhaps the validator should also error if it encounters a call to some @must_use that somehow returns nothing, whether it's in an expression or a statement. i experimented briefly but couldn't get the parser to emit an example.

@turbocrime turbocrime changed the title [naga] parse @must_use attribute [naga] parse and validate @must_use attribute Jan 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
Status: In Progress
Development

Successfully merging this pull request may close these issues.

4 participants