Skip to content

Add support for (either ...) in wast#8421

Open
stevenfontanella wants to merge 1 commit intomainfrom
either2
Open

Add support for (either ...) in wast#8421
stevenfontanella wants to merge 1 commit intomainfrom
either2

Conversation

@stevenfontanella
Copy link
Member

@stevenfontanella stevenfontanella commented Mar 5, 2026

  • Adds support for (either ...) in assert_return in WAST
  • Also allows customizing the error type in Result, which we use to keep track of the failing lane in assertions.

Example failure:

(module
  (func (export "f") (result i32)
    (i32.const 1)
  )
)

(assert_return (invoke "f") (either (i32.const 2) (i32.const 3)))
Expected one of (2 | 3) but got 1

Example failure with SIMD from relaxed_min_max.wast:

Expected one of (canonical f32 | canonical f32 | 0 | 0x00000000) at lane 0 but got i32x4 0x7fc00000 0x7fc00000 0x7fc00000 0x7fc00000

Part of #8261 and #8315. Fixes i16x8_relaxed_q15mulr_s.wast, i8x16_relaxed_swizzle.wast, relaxed_madd_nmadd.wast spec tests, and partially fixes relaxed_dot_product.wast, relaxed_laneselect.wast, relaxed_min_max.wast, and threads/thread.wast.

@stevenfontanella stevenfontanella force-pushed the either2 branch 3 times, most recently from 5b361b4 to c7fcea9 Compare March 5, 2026 19:51
@stevenfontanella stevenfontanella changed the title [WIP] Add support for either in wast Add support for (either ...) in wast Mar 5, 2026
@stevenfontanella stevenfontanella marked this pull request as ready for review March 5, 2026 20:55
auto r = eitherResult(in);
CHECK_ERR(r);
res.emplace_back(std::move(*r));
res.emplace_back(*std::move(r));
Copy link
Member

Choose a reason for hiding this comment

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

Why is this better or more correct?

Copy link
Member Author

Choose a reason for hiding this comment

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

I based this off of Google's style guide for absl::StatusOr which recommends moving from the whole thing instead of just the value inside to indicate that the whole result type is moved-from. Basically it would likely be a mistake to do something with r after this and moving r instead of *r hints that to the reader. I got it from here (ctrl+f "Moving from the value"): https://abseil.io/tips/181

Copy link
Member

Choose a reason for hiding this comment

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

Interesting! Makes sense, though I find it slightly less intuitive. Seems fine to introduce here.

Comment on lines +382 to +383
if (!val.type.isRef() ||
!HeapType::isSubType(val.type.getHeapType(), ref->type)) {
Copy link
Member

Choose a reason for hiding this comment

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

We should probably check that the value is not null here, too.

Comment on lines +368 to +369
auto valLanes = val.getLanesI32x4();
auto expLanes = v->getLanesI32x4();
Copy link
Member

Choose a reason for hiding this comment

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

Can we avoid hard-coding a lane interpretation here? Maybe we should always use LaneResults for vectors if we want to be more precise about lanes in error messages?


if (auto* v = std::get_if<Literal>(&expected)) {
if (val != *v) {
if (val.type.isVector() && v->type.isVector() && isAlternative) {
Copy link
Member

Choose a reason for hiding this comment

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

It's not clear to me why we check isAlternative here.

<< resultToString(result);
return Err{err.str()};
}
for (Index i = 0; i < values->size(); ++i) {
Copy link
Member

Choose a reason for hiding this comment

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

Do you know whether either cases are supposed to handle multiple values in the case of multivalue or whether each value gets its own either clause? I would have expected the former, in which case this loop would have to be inside the either handling. (But if there are no tests that exercise this yet, it's ok to leave a TODO rather than fixing it.)

Copy link
Member Author

Choose a reason for hiding this comment

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

According to the spec it's the latter:
image

So we can say

(assert_return (invoke "foo") (either a b) (either c d))

But not

(assert_return (invoke "foo") (either (a c) (b d))

Copy link
Member

Choose a reason for hiding this comment

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

Interesting, thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants