Skip to content

fix: Throw on coercing/casting runtime values to bool, and suggest directly comparing to the desired value #2442

@iwoplaza

Description

@iwoplaza

Handling undefined in shader functions is a whole set of problems. Because undefined as a value doesn't exist on the GPU, yet undefined behavior does, users can wrongly depend on checks against an empty array item under the assumption that it will fail, yet the GPU will happily read from outside of the bounds of the array and give a truthy value.

Let's say we have a function like this:

function foo() {
  'use gpu';
  const arr = [1, 2, 3];
  while (true) {
    if (!arr[i]) {
      break;
    }
    // ...
  }
}

Currently, we will generate the following WGSL:

fn foo() {
  var arr = array<i32>(1, 2, 3);
  while (true) {
    if (!arr[i]) { // WILL read outside of the array, potentially infinite loop
      break;
    }
    // ...
  }
}

It's very hard to exhaustively track whether something can or can't be undefined by tracing through the program, and then again we'd have to verify that devs don't depend on the value being undefined or not.

Solution

My current solution to this problem, is to recognize that coercing non-bool primitives to bool in WGSL is equivalent to comparing them to 0.

let a = bool(1);
// same thing
let b = 1 != 0;

When coercing numbers to bool in JavaScript, there are many more cases where the result can be false:

  • !!(0) -> false
  • !!(NaN) -> false
  • !!(undefined) -> false
  • (a few more...)

We can use that fact to nudge users in the right direction, to state their intent. I think we should throw a descriptive error each time a runtime-known value is coerced/cast into a boolean, and require devs to change it to a more explicit form.

What about comptime

Comptime-known values are fine to coerce to bools 👍

Metadata

Metadata

Assignees

No one assigned

    Labels

    stabilityTasks that focus on improving stability, that includes tests, refining edge-cases, refactoring.

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions