Sema: rewrite comptime arithmetic #23177
Open
+11,278
−2,435
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Hey @kristoff-it, this is what that "simple little one-line fix" evolved into! Isn't that fun?
This commit reworks how Sema handles arithmetic on comptime-known values, fixing many bugs in the process.
The general pattern is that arithmetic on comptime-known values is now handled by the new namespace
Sema.arith
. Functions handling comptime arithmetic no longer live onValue
; this is because some of them can emit compile errors, so some can't go onValue
. Only semantic analysis should really be doing arithmetic onValue
s anyway, so it makes sense for it to integrate more tightly withSema
.This commit also implements more coherent rules surrounding how
undefined
interacts with comptime and mixed-comptime-runtime arithmetic. The rules are as follows.If an operation cannot trigger Illegal Behavior, and any operand is
undefined
, the result isundefined
. This includes operations like0 *| undef
, where the LHS logically could be used to determine a defined result. This is partly to simplify the language, but mostly to permit codegen backends to representundefined
values as completely invalid states.If an operation can trigger Illegal Behvaior, and any operand is
undefined
, then Illegal Behavior results. This occurs even if the operand in question isn't the one that "decides" illegal behavior; for instance,undef / 1
triggers IB. This is for the same reasons as described above.An operation which would trigger Illegal Behavior, when evaluated at comptime, instead triggers a compile error. Additionally, if one operand is comptime-known undef, such that the other (runtime-known) operand isn't needed to determine that Illegal Behavior would occur, the compile error is triggered.
The only situation in which an operation with one comptime-known operand has a comptime-known result is if that operand is undefined, in which case the result is either undefined or a compile error per the above rules. This could potentially be loosened in future (for instance,
0 * rt
could be comptime-known 0 with a runtime assertion thatrt
is not undefined), but at least for now, defining it more conservatively simplifies the language and allows us to easily change this in future if desired.This commit fixes many bugs regarding the handling of
undefined
, particularly in vectors. Along with a collection of smaller tests, two very large test cases are added to check arithmetic onundefined
.The operations which have been rewritten in this PR are:
+
,+%
,+|
,@addWithOverflow
-
,-%
,-|
,@subWithOverflow
*
,*%
,*|
,@mulWithOverflow
/
,@divFloor
,@divTrunc
,@divExact
%
,@rem
,@mod
Other arithmetic operations are currently unchanged.
Resolves: #22743
Resolves: #22745
Resolves: #22748
Resolves: #22749
Resolves: #22914