Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Tuple-like-returns proposal for function-out-params functionality #3501

@kdashg

Description

@kdashg

In #3276, we touched on how multiple return types via (something like) tuples with destructured assignment could satisfy some of the our needs for the abstract function-out-params functionality that have us exploring inout and evaluating the extent of our ptr function-argument restrictions.

Previously, we agreed that multiple-return and tuples would be good candidates for post-v1, but that we should focus on more pressing matters for MVP. However, if we can go (at least part-way) in this direction, we might be able to get v1 to a place that's both more future-proof than adding inout, and also avoids some of the trickier restrictions we'd need for ptr in v1.

So, let's see how much we can do with how little!


Here's an example (and REPL) of what I'm talking about in Rust: https://tourofrust.com/10_en.html

Here's my proposal for the classic swap example in WGSL:

fn swap(a: i32, b: i32) -> (i32, i32) {
  return (b, a);
}
// For v1:
var (a, b) = swap(1, 2); // => a=2, b=1
(a, b) = swap(a, b); // => a=1, b=2

// Post-v1:
var res = swap(3, 4); // res=(4,3)
res = swap(res.0, res.1); // res=(3,4)
(res.0, res.1) = swap(res.0, res.1); // res=(4,3)

(a, b) = (b, a);
(res.0, res.1) = (res.1, res.0);

(a, b) = ((b), a);
(a, b) = ((b,).0, a);

In WGSL, I propose:

  • 1: In v1: minimal Tuple-like-returns, skipping 1-tuple(-likes) for now

    • 1a: New return statement option: return paren_left expression (comma expression)+ paren_right (not returning a Tuple per-se)
    • 1b: Functions with multiple returns must be destructured into lval assignments, since they aren't Tuples per-se, so assignment gains option paren_left lhs_expression (comma lhs_expression)+ paren_right equals expression.
    • **1c: Not being real Tuples, multiple-returns don't type-match as expressions, except via destructuring assignment.
  • 2: post-v1: Real Tuples, tbd, something like:

    • 2a: (i32, i32) is an example of the written type of a Tuple.
    • 2b: Tuples can be destructured into assigning separate lvals.
    • 2c: Tuples can be constructed via:
      • paren_left paren_right (e.g. empty Tuple ())
      • or paren_left expression comma paren_right (e.g. 1-tuple (a,) disambiguated from identity-expression (a))
      • or paren_left expression (comma expression)+ comma? paren_right (e.g. n>1-tuples: (a, b) or (a, b,))
    • 2d: Tuples can be (re)assigned as wholes
    • 2e: Tuple elements can be (re)assigned

Maybe this kind of scoping here is too minimalist, as real Tuples don't seem like that much more work, but I'm really trying to keep things lean in terms of late additions to the spec. (And so I'm enumerating this as an option)


Conceptually, this is merely a sugaring source-level transform:

//fn swap(a: i32, b: i32) -> (i32, i32) {
struct __swap_ret {
  __0: i32,
  __1: i32,
};
fn swap(a: i32, b: i32) -> __swap_ret {
//  return (b, a);
  return __swap_ret(b, a);
}
// For v1:
//var (a, b) = swap(1, 2); // => a=2, b=1
var __tmp0 = swap(1, 2);
var a = __tmp0.__0;
var b = __tmp0.__1;

//(a, b) = swap(a, b); // => a=1, b=2
let __tmp1 = swap(a, b);
a = __tmp1.__0;
b = __tmp1.__1;

All existing analyses would continue to apply and operate as-if on the de-sugared source.


I couldn't find any examples of cross-function ptr use in e.g. https://austin-eng.com/webgpu-samples/samples/computeBoids#updateSprites.wgsl.

In drafting this, it kind of feels like jumping straight to having Tuples might be almost trivial, and could simplify some things, but I really want to explore how lean we can go, and not sign up for more work on the implementation side.
It feels straight-forward to have full Tuples as a source-level sugaring transform but I have only given this hours and not days of thought. (And I want to know what everyone else thinks!)

Metadata

Metadata

Assignees

No one assigned

    Labels

    wgslWebGPU Shading Language Issues

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions