Fix ===/any coercion bugs, in-operator crash, and add regression coverage#241
Merged
Conversation
… tests - mlirGenInLogic assumed any `in` expression whose right side has `.length` was a numeric-index check, so a string-literal left side (e.g. "length" in arr) got cast to an index type and crashed LLVM translation. Now falls through to the general field-lookup path for string literals. - getFieldTypeByFieldName didn't strip LiteralType wrappers, so `in` checks against const strings/string literals (e.g. "length" in "hi") incorrectly resolved to false instead of using the underlying type's field lookup. - Add 00in_method_names.ts and 00class_structural_extends.ts covering the #238 area (in-operator and structural extends against classes), wired into both test-compile and test-jit CMake targets. Verified against the full 696-test suite, no regressions. - Document a separate, deferred bug in docs/bugs/: generators lose their state across manual .next() calls (only for...of works). Root-caused to const bindings lacking backing storage; a first fix attempt broke unrelated interface/symbol tests and was reverted, so the fix itself is left for a dedicated follow-up.
…tests for coercion behavior
=== / !== previously shared codegen with ==/!=, so mismatched primitive kinds (1 === true) were coerced to a common type and wrongly compared equal. adjustTypesForBinaryOp now short-circuits to a constant when both operand types are unambiguous, differing primitives. AnyCompareOp's ==/!= lowering did a raw memcmp of the boxed payload bytes, never applying JS loose-equality coercion across differing any payload kinds (number<->string, boolean<->number, boolean<->string). It now compares the boxed type tags first and coerces via the existing cast helpers when they differ, accounting for the fact that boxed integer literals carry concrete-width tags (s32/s64) rather than "number". Adds 00mixed_type_ops.ts covering cross-type binary op coercion. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
… assertion conditionalExpressionLowering (CodeLogicHelper.h) branched into its result block from the then/else block handles captured before invoking the builder callbacks, assuming the insertion point never moved. That broke as soon as a callback itself called the helper again (needed for AnyCompareOp's new multi-way coercion dispatch), producing an "operation with block successors must terminate its parent block" verifier error. It now re-reads the actual insertion block after each builder runs, so it composes safely when nested. AnyCompareOpLowering's local workaround (nestableConditional) is removed in favor of the shared, now-fixed helper. 01tuple.ts's `assert(obj8.field1 === 10)` relied on the old, buggy === semantics that coerced like == (fixed in the previous commit) -- field1 is string-typed and holds the coerced "10", so strict equality against the number 10 is correctly false. Updated to match the coercion pattern already used elsewhere in the same file. Full suite: 700/700 passing. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
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.
Summary
===/!==) no longer coerces mismatched primitive kinds (1 === truewas wronglytrue); short-circuits to a constant when both operand types are unambiguous, differing primitives.any == any/any != anynow applies JS loose-equality coercion across differing boxed payload kinds (number↔string, boolean↔number, boolean↔string), instead of a raw byte-for-bytememcmp. Handles the fact that boxed integer literals carry concrete-width type tags (s32/s64) rather than"number".CodeLogicHelper::conditionalExpressionLoweringis now safe to call from within its own then/else builder callbacks (previously branched from stale block handles, corrupting control flow when nested — needed for the any-coercion fix's multi-way tag dispatch).01tuple.tsthat relied on the old, buggy coercing===semantics.in-operator crash when the left-hand side is a string literal (e.g."length" in arr) and a related literal-type field lookup bug.00bool_arith_ops.ts,00mixed_type_ops.ts,00in_method_names.ts,00class_structural_extends.ts..next()calls don't advance state on aconst-bound generator (docs/bugs/00generator_manual_next.ts).Test plan
ctest -C Debug)===/!==no longer coerce across primitive kindsany==any/any!=anycoercion in both directions for all three kind pairs, plus!=and same-kind cases unaffected01tuple.tsassertion matches actual coerced runtime value🤖 Generated with Claude Code