r/wg21
P3932R0 - Fix LWG4470: Fix integer-from in [simd] WG21
Posted by u/lwg_defect_accumulator · 5 hr. ago

Document: P3932R0 — Fix LWG4470: Fix integer-from in [simd]
Author: Matthias Kretz
Date: 2026-02-13
Audience: LWG (C++26)

Three LWG issues in one pass. The headline is LWG4470: integer-from<Bytes> was used throughout [simd] to derive a signed integer type from an element byte count — works great until Bytes is 16, which is exactly what you get when complex<double> became a vectorizable type. There's no standard 128-bit integer, so the whole machinery quietly breaks for a type the standard just welcomed in. The fix introduces mask-element-size<T> as a new exposition-only helper that side-steps the problem without requiring the implementation to conjure nonexistent integer types.

Along the way: LWG4518 fixes simd::cat's return type. Currently it uses deduce-abi-t which can silently produce a different ABI tag than the inputs — meaning simd::cat(simd::chunk<2>(x)...) is not necessarily the same type as x. That's surprising. The fix switches to resize_t anchored on the first argument, which is a simple heuristic but at least doesn't violate the principle of least astonishment for the common case.

LWG4414 rounds it out: deduce-abi-t<T,N> was underspecified for arguments it doesn't support (e.g., simd::vec<std::string> or simd::vec<int, INT_MAX>). The old wording was ambiguous about whether that made the specialization ill-formed. The new wording says it names an unspecified type, which is what the intent always was.

No behavior changes for user code. No feature test macro bump. This is spec maintenance — the kind that matters a lot if you are writing an implementation.

▲ 38 points (91% upvoted) · 11 comments
sorted by: best
u/complex_double_was_a_mistake 47 points 5 hr. ago

TIL complex<double> is now a vectorizable type in C++26 std::simd, and adding it apparently broke the entire mask integer selection mechanism. Not a criticism of the fix — just impressed that one small addition had that many downstream spec consequences.

u/mask_element_size_enthusiast 31 points 4 hr. ago

It's because basic_mask<Bytes, Abi> is parameterized by element byte count, not by type. And the spec used integer-from<Bytes> to find a signed integer of that width for ABI tag deduction — 1→int8, 2→int16, 4→int32, 8→int64. complex<double> has sizeof 16, so the spec was implicitly demanding int128_t. Which isn't a thing in standard C++. The new mask-element-size<T> decouples the mask's ABI selection from the raw byte count so the spec doesn't accidentally promise something implementations can't deliver.

u/complex_double_was_a_mistake 18 points 3 hr. ago

So the whole thing was silently broken for any implementation that actually tried to support complex<double> SIMD. Nobody would have caught this until someone went to write the wording tests. Classic.

u/former_simd_implementer_irl 29 points 4 hr. ago

The simd::cat issue (LWG4518) is the one that would actually bite users. The example in the paper:

basic_vec<T, Abi> x = ...;
auto [...vs] = simd::chunk<2>(x);
auto y = simd::cat(vs...);
static_assert(is_same_v<decltype(x), decltype(y)>); // can FAIL

Round-trip identity failing silently is exactly the kind of thing that shows up as a bizarre hard-to-reproduce type mismatch three levels deep in a template instantiation. Using resize_t anchored on the first argument is a pragmatic fix. Not perfect for mixed-ABI inputs but correct for the 95% case.

u/abi_tag_archaeology 14 points 3 hr. ago

Using resize_t anchored on the first argument is a pragmatic fix.

The paper acknowledges this is a "simple heuristic" for mixed-ABI inputs. I'd push back a little — if you pass chunks with different ABI tags to cat (which the function explicitly allows for different widths), there's genuinely no correct answer. "Use the first one" at least doesn't pretend otherwise.

u/not_a_real_vc_user 22 points 3 hr. ago

std::simd lands in C++26 and we're already finding spec bugs before the ink is dry. How many more integer-from uses are hiding in [simd] that are going to quietly explode when someone adds another exotic vectorizable type?

u/mask_element_size_enthusiast 19 points 2 hr. ago

That's literally what this paper does — it reviews every use of integer-from in [simd] and replaces the ones that are broken. Section 2.1 starts with "All uses of integer-from need to be reviewed". So Matthias went through them. The fix is comprehensive, not a patch on one callsite.

u/simd_skeptic_in_prod 11 points 2 hr. ago

Genuine question: does any shipping compiler actually implement complex<double> as a vectorizable type for std::simd yet? Or is this a spec fix for something that's only theoretical breakage at this point?

u/former_simd_implementer_irl 17 points 1 hr. ago

GCC's experimental <experimental/simd> doesn't support complex yet. But the wording is normative regardless — if the spec says complex<double> is vectorizable and integer-from<16> is broken, any conforming implementation that tries to support it would be in trouble. Better to fix the spec now than after three implementations ship.