From dc36f1266023633d1795f13deea7ed7e66bfc602 Mon Sep 17 00:00:00 2001 From: Joanna Brozek Date: Mon, 30 Mar 2026 14:34:51 +0200 Subject: [PATCH 1/6] Remove builtin enumerate --- xls/dslx/bytecode/builtins.cc | 18 ------------- xls/dslx/bytecode/builtins.h | 2 -- xls/dslx/bytecode/bytecode_interpreter.cc | 2 -- .../bytecode/bytecode_interpreter_test.cc | 23 ----------------- xls/dslx/dslx_builtins.h | 1 - xls/dslx/frontend/builtin_stubs.x | 2 -- xls/dslx/frontend/builtins_metadata.cc | 1 - xls/dslx/tests/BUILD | 6 ----- xls/dslx/tests/enumerate.x | 25 ------------------- .../typecheck_module_v2_builtin_test.cc | 15 ----------- 10 files changed, 95 deletions(-) delete mode 100644 xls/dslx/tests/enumerate.x diff --git a/xls/dslx/bytecode/builtins.cc b/xls/dslx/bytecode/builtins.cc index e3956d1d2d..8702b56b1e 100644 --- a/xls/dslx/bytecode/builtins.cc +++ b/xls/dslx/bytecode/builtins.cc @@ -518,24 +518,6 @@ absl::Status RunBuiltinCtz(const Bytecode& bytecode, InterpreterStack& stack) { return absl::OkStatus(); } -absl::Status RunBuiltinEnumerate(const Bytecode& bytecode, - InterpreterStack& stack) { - XLS_RET_CHECK(!stack.empty()); - XLS_ASSIGN_OR_RETURN(InterpValue input, stack.Pop()); - XLS_ASSIGN_OR_RETURN(const std::vector* values, - input.GetValues()); - - std::vector elements; - elements.reserve(values->size()); - for (int32_t i = 0; i < values->size(); i++) { - elements.push_back( - InterpValue::MakeTuple({InterpValue::MakeU32(i), values->at(i)})); - } - XLS_ASSIGN_OR_RETURN(InterpValue result, InterpValue::MakeArray(elements)); - stack.Push(result); - return absl::OkStatus(); -} - absl::Status RunBuiltinOrReduce(const Bytecode& bytecode, InterpreterStack& stack) { VLOG(3) << "Executing builtin OrReduce."; diff --git a/xls/dslx/bytecode/builtins.h b/xls/dslx/bytecode/builtins.h index a532475fa8..d3477fd042 100644 --- a/xls/dslx/bytecode/builtins.h +++ b/xls/dslx/bytecode/builtins.h @@ -72,8 +72,6 @@ absl::Status RunBuiltinCeilLog2(const Bytecode& bytecode, absl::Status RunBuiltinClz(const Bytecode& bytecode, InterpreterStack& stack); absl::Status RunBuiltinCover(const Bytecode& bytecode, InterpreterStack& stack); absl::Status RunBuiltinCtz(const Bytecode& bytecode, InterpreterStack& stack); -absl::Status RunBuiltinEnumerate(const Bytecode& bytecode, - InterpreterStack& stack); absl::Status RunBuiltinOrReduce(const Bytecode& bytecode, InterpreterStack& stack); absl::Status RunBuiltinRange(const Bytecode& bytecode, InterpreterStack& stack); diff --git a/xls/dslx/bytecode/bytecode_interpreter.cc b/xls/dslx/bytecode/bytecode_interpreter.cc index c680081d0a..1e556e856d 100644 --- a/xls/dslx/bytecode/bytecode_interpreter.cc +++ b/xls/dslx/bytecode/bytecode_interpreter.cc @@ -1673,8 +1673,6 @@ absl::Status BytecodeInterpreter::RunBuiltinFn(const Bytecode& bytecode, return RunBuiltinCover(bytecode, stack_); case Builtin::kCtz: return RunBuiltinCtz(bytecode, stack_); - case Builtin::kEnumerate: - return RunBuiltinEnumerate(bytecode, stack_); case Builtin::kFail: { XLS_ASSIGN_OR_RETURN(InterpValue value, Pop()); std::string message{value.ToString()}; diff --git a/xls/dslx/bytecode/bytecode_interpreter_test.cc b/xls/dslx/bytecode/bytecode_interpreter_test.cc index 3997afc73c..af0370bf21 100644 --- a/xls/dslx/bytecode/bytecode_interpreter_test.cc +++ b/xls/dslx/bytecode/bytecode_interpreter_test.cc @@ -1940,29 +1940,6 @@ fn main(x: s10, y: s10) -> s10 { EXPECT_THAT(bits.ToInt64(), IsOkAndHolds(-507)); } -TEST_F(BytecodeInterpreterTest, BuiltinEnumerate) { - constexpr std::string_view kProgram = R"( -fn main() -> (u32, u8)[4] { - let x = u8[4]:[5, 6, 7, 8]; - enumerate(x) -})"; - - XLS_ASSERT_OK_AND_ASSIGN(InterpValue actual, Interpret(kProgram, "main")); - XLS_ASSERT_OK_AND_ASSIGN( - InterpValue expected, - InterpValue::MakeArray({ - InterpValue::MakeTuple( - {InterpValue::MakeUBits(32, 0), InterpValue::MakeUBits(8, 5)}), - InterpValue::MakeTuple( - {InterpValue::MakeUBits(32, 1), InterpValue::MakeUBits(8, 6)}), - InterpValue::MakeTuple( - {InterpValue::MakeUBits(32, 2), InterpValue::MakeUBits(8, 7)}), - InterpValue::MakeTuple( - {InterpValue::MakeUBits(32, 3), InterpValue::MakeUBits(8, 8)}), - })); - EXPECT_TRUE(expected.Eq(actual)); -} - TEST_F(BytecodeInterpreterTest, BuiltinUMulp) { constexpr std::string_view kProgram = R"( fn main(x: u10, y: u10) -> u10 { diff --git a/xls/dslx/dslx_builtins.h b/xls/dslx/dslx_builtins.h index 52c9b09d21..921e42595f 100644 --- a/xls/dslx/dslx_builtins.h +++ b/xls/dslx/dslx_builtins.h @@ -46,7 +46,6 @@ namespace xls::dslx { X("decode", kDecode) \ X("element_count", kElementCount) \ X("encode", kEncode) \ - X("enumerate", kEnumerate) \ X("fail!", kFail) \ X("gate!", kGate) \ X("map", kMap) \ diff --git a/xls/dslx/frontend/builtin_stubs.x b/xls/dslx/frontend/builtin_stubs.x index 60167cd88a..0ca5748c18 100644 --- a/xls/dslx/frontend/builtin_stubs.x +++ b/xls/dslx/frontend/builtin_stubs.x @@ -56,8 +56,6 @@ fn decode(x: uN[N]) -> T; fn element_count() -> u32; -fn enumerate(x: T[N]) -> (u32, T)[N]; - fn fail! (label: u8[N], fallback_value: T) -> T; fn gate!(x: u1, y: T) -> T; diff --git a/xls/dslx/frontend/builtins_metadata.cc b/xls/dslx/frontend/builtins_metadata.cc index 87d153ba60..5a77a52bac 100644 --- a/xls/dslx/frontend/builtins_metadata.cc +++ b/xls/dslx/frontend/builtins_metadata.cc @@ -98,7 +98,6 @@ const absl::flat_hash_map& GetParametricBuiltins() { {"signex", {}}, {"array_slice", {}}, {"update", {}}, - {"enumerate", {}}, {"widening_cast", {}}, {"checked_cast", {}}, diff --git a/xls/dslx/tests/BUILD b/xls/dslx/tests/BUILD index ab6f67bc9b..00d306cc81 100644 --- a/xls/dslx/tests/BUILD +++ b/xls/dslx/tests/BUILD @@ -338,12 +338,6 @@ dslx_lang_test( dslx_lang_test(name = "for_over_range") -dslx_lang_test( - name = "enumerate", - compare = "interpreter", - convert_to_ir = True, -) - dslx_lang_test( name = "character_conversion", # TODO: https://github.com/google/xls/issues/1526 - fails opportunistic_postcondition in autofmt diff --git a/xls/dslx/tests/enumerate.x b/xls/dslx/tests/enumerate.x deleted file mode 100644 index 9d4424262d..0000000000 --- a/xls/dslx/tests/enumerate.x +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright 2022 The XLS Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -fn main(array: u8[4]) -> (u32, u8)[4] { enumerate(array) } - -#[test] -fn enumerate_test() { - let my_array = u8[4]:[1, 2, 4, 8]; - let enumerated = main(my_array); - assert_eq(enumerated[u32:0], (u32:0, u8:1)); - assert_eq(enumerated[u32:1], (u32:1, u8:2)); - assert_eq(enumerated[u32:2], (u32:2, u8:4)); - assert_eq(enumerated[u32:3], (u32:3, u8:8)); -} diff --git a/xls/dslx/type_system_v2/typecheck_module_v2_builtin_test.cc b/xls/dslx/type_system_v2/typecheck_module_v2_builtin_test.cc index 56114bd848..a0053bf1f3 100644 --- a/xls/dslx/type_system_v2/typecheck_module_v2_builtin_test.cc +++ b/xls/dslx/type_system_v2/typecheck_module_v2_builtin_test.cc @@ -659,21 +659,6 @@ const_assert!(element_count() == 10); XLS_EXPECT_OK(TypecheckV2(kProgram, "main", &import_data)); } -TEST(TypecheckV2BuiltinTest, Enumerate) { - EXPECT_THAT(R"(const Y = enumerate([u16:1, u16:2, u16:3]);)", - TypecheckSucceeds(HasNodeWithType("Y", "(uN[32], uN[16])[3]"))); -} - -TEST(TypecheckV2BuiltinTest, EnumerateImplicitSize) { - EXPECT_THAT(R"(const Y = enumerate([u16:1, u16:2, u16:3]);)", - TypecheckSucceeds(HasNodeWithType("Y", "(uN[32], uN[16])[3]"))); -} - -TEST(TypecheckV2BuiltinTest, EnumerateImplicitType) { - EXPECT_THAT(R"(const Y = enumerate([u16:1, u16:2, u16:3]);)", - TypecheckSucceeds(HasNodeWithType("Y", "(uN[32], uN[16])[3]"))); -} - TEST(TypecheckV2BuiltinTest, Fail) { EXPECT_THAT( R"( From a2aec1f72a376d3c8e7651170229f9db6cc6ce4b Mon Sep 17 00:00:00 2001 From: Joanna Brozek Date: Wed, 29 Apr 2026 10:34:31 +0200 Subject: [PATCH 2/6] type_system_v2: Use std::enumerate() --- xls/dslx/type_system_v2/typecheck_module_v2_lambda_test.cc | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/xls/dslx/type_system_v2/typecheck_module_v2_lambda_test.cc b/xls/dslx/type_system_v2/typecheck_module_v2_lambda_test.cc index e63b9878c1..193bb8e3ec 100644 --- a/xls/dslx/type_system_v2/typecheck_module_v2_lambda_test.cc +++ b/xls/dslx/type_system_v2/typecheck_module_v2_lambda_test.cc @@ -189,12 +189,13 @@ const_assert!(ARR[1] == u16:2); TEST(TypecheckV2Test, NestedLambdas) { EXPECT_THAT( R"( +import std; fn main() -> u32[4][5] { let z = zero!(); - map(enumerate(z), | tup | { + map(std::enumerate(z), | tup | { let i = tup.0; let arr = tup.1; - map(enumerate(arr), | tup2 | { + map(std::enumerate(arr), | tup2 | { let j = tup2.0; i + j }) From 5f0fa0f668c02bd75ce31e6fb159740508ad4c8d Mon Sep 17 00:00:00 2001 From: Joanna Brozek Date: Wed, 29 Apr 2026 09:35:01 +0200 Subject: [PATCH 3/6] type_system_v2: Allow empty range --- xls/dslx/tests/errors/error_modules_test.py | 9 -------- xls/dslx/tests/errors/match_empty_range.x | 21 ------------------- .../typecheck_module_v2_array_tuple_test.cc | 10 --------- .../type_system_v2/validate_concrete_type.cc | 6 ++---- 4 files changed, 2 insertions(+), 44 deletions(-) delete mode 100644 xls/dslx/tests/errors/match_empty_range.x diff --git a/xls/dslx/tests/errors/error_modules_test.py b/xls/dslx/tests/errors/error_modules_test.py index c3c1250d70..ff183622d3 100644 --- a/xls/dslx/tests/errors/error_modules_test.py +++ b/xls/dslx/tests/errors/error_modules_test.py @@ -1097,15 +1097,6 @@ def test_user_defined_parametric_type(self): stderr, ) - def test_match_empty_range(self): - stderr = self._run( - 'xls/dslx/tests/errors/match_empty_range.x', - ) - self.assertIn( - '`u32:0..u32:0` from `u32:0` to `u32:0` is an empty range', - stderr, - ) - def test_parametric_test_fn(self): stderr = self._run( 'xls/dslx/tests/errors/parametric_test_fn.x', diff --git a/xls/dslx/tests/errors/match_empty_range.x b/xls/dslx/tests/errors/match_empty_range.x deleted file mode 100644 index 36b505b5a9..0000000000 --- a/xls/dslx/tests/errors/match_empty_range.x +++ /dev/null @@ -1,21 +0,0 @@ -// Copyright 2023 The XLS Authors -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -fn f(x: u32) -> u32 { - match x { - // Since the range is exclusive this is an empty range. - u32:0..u32:0 => u32::MAX, - _ => x, - } -} diff --git a/xls/dslx/type_system_v2/typecheck_module_v2_array_tuple_test.cc b/xls/dslx/type_system_v2/typecheck_module_v2_array_tuple_test.cc index 50e724f571..1bf66780c9 100644 --- a/xls/dslx/type_system_v2/typecheck_module_v2_array_tuple_test.cc +++ b/xls/dslx/type_system_v2/typecheck_module_v2_array_tuple_test.cc @@ -1726,16 +1726,6 @@ const X = foo()..(A * 2); TypecheckSucceeds(HasNodeWithType("X", "sN[16][8]"))); } -TEST(TypecheckV2Test, RangeExprEmptyRange) { - XLS_ASSERT_OK_AND_ASSIGN(TypecheckResult result, TypecheckV2(R"( -const A = s8:4; -const X = A..s8:4; -)")); - ASSERT_THAT(result.tm.warnings.warnings().size(), 1); - EXPECT_EQ(result.tm.warnings.warnings()[0].message, - "`A..s8:4` from `s8:4` to `s8:4` is an empty range"); -} - TEST(TypecheckV2Test, RangeExprSignednessMismatch) { EXPECT_THAT(R"(const X = u32:1..s32:2;)", TypecheckFails(HasSignednessMismatch("s32", "u32"))); diff --git a/xls/dslx/type_system_v2/validate_concrete_type.cc b/xls/dslx/type_system_v2/validate_concrete_type.cc index 82a59ef362..4c119f2762 100644 --- a/xls/dslx/type_system_v2/validate_concrete_type.cc +++ b/xls/dslx/type_system_v2/validate_concrete_type.cc @@ -406,11 +406,9 @@ class TypeValidator : public AstNodeVisitorWithDefault { const_cast(&import_data_), const_cast(&ti_), &warning_collector_, env, range->end())); + // Allow empty range if (!range->inclusive_end() && start.Eq(end)) { - warning_collector_.Add( - range->span(), WarningKind::kEmptyRangeLiteral, - absl::StrFormat("`%s` from `%s` to `%s` is an empty range", - range->ToString(), start.ToString(), end.ToString())); + return absl::OkStatus(); } // In TIv1 we only warn for ranges in match arm that is empty. if (range->has_pattern_semantics()) { From 351b14a3f44f5f0458d8729db1f852ad86e5bb34 Mon Sep 17 00:00:00 2001 From: Joanna Brozek Date: Wed, 29 Apr 2026 15:19:46 +0200 Subject: [PATCH 4/6] std: Add test for struct enumeration --- xls/dslx/stdlib/std.x | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) diff --git a/xls/dslx/stdlib/std.x b/xls/dslx/stdlib/std.x index 30115ceeca..78f5a843fb 100644 --- a/xls/dslx/stdlib/std.x +++ b/xls/dslx/stdlib/std.x @@ -51,6 +51,41 @@ fn enumerate_tuple_test() { assert_eq(enumerated[1], (1, (false, 2))); } +type TestIdx = uN[2]; +type TestValue = uN[32]; + +struct TestData { idx: TestIdx, value: TestValue } + +const TEST_DATA = TestData[20]:[ + TestData { idx: TestIdx:0, value: TestValue:0xca32_9f4a }, + TestData { idx: TestIdx:1, value: TestValue:0x0fb3_fa42 }, + TestData { idx: TestIdx:2, value: TestValue:0xe7ee_da41 }, + TestData { idx: TestIdx:3, value: TestValue:0xef51_f98c }, + TestData { idx: TestIdx:0, value: TestValue:0x97a3_a2d2 }, + TestData { idx: TestIdx:0, value: TestValue:0xea06_e94b }, + TestData { idx: TestIdx:1, value: TestValue:0x5fac_17ce }, + TestData { idx: TestIdx:3, value: TestValue:0xf9d8_9938 }, + TestData { idx: TestIdx:2, value: TestValue:0xc262_2d2e }, + TestData { idx: TestIdx:2, value: TestValue:0xb4dd_424e }, + TestData { idx: TestIdx:1, value: TestValue:0x01f9_b9e4 }, + TestData { idx: TestIdx:1, value: TestValue:0x3020_6eec }, + TestData { idx: TestIdx:3, value: TestValue:0x3124_87b5 }, + TestData { idx: TestIdx:0, value: TestValue:0x0a49_f5e3 }, + TestData { idx: TestIdx:2, value: TestValue:0xde3b_5d0f }, + TestData { idx: TestIdx:3, value: TestValue:0x5948_c1b3 }, + TestData { idx: TestIdx:0, value: TestValue:0xa26d_851f }, + TestData { idx: TestIdx:3, value: TestValue:0x3fa9_59c0 }, + TestData { idx: TestIdx:1, value: TestValue:0x4efd_dd09 }, + TestData { idx: TestIdx:1, value: TestValue:0x6d75_058a }, +]; + +#[test] +fn enumerate_struct_test() { + let enumerated = enumerate(TEST_DATA); + assert_eq(enumerated[0], (0, TEST_DATA[0])); + assert_eq(enumerated[19], (19, TEST_DATA[19])); +} + pub fn sizeof(x: xN[S][N]) -> u32 { N } #[test] From a76cb2144cf41970f8229ba1e340d09f8089a293 Mon Sep 17 00:00:00 2001 From: Joanna Brozek Date: Wed, 29 Apr 2026 15:20:16 +0200 Subject: [PATCH 5/6] std: Add support for empty array enumeration --- .../ir_converter_test_ArrayEnumerate.ir | 23 ++++++++----------- xls/dslx/stdlib/std.x | 9 +++++++- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/xls/dslx/ir_convert/testdata/ir_converter_test_ArrayEnumerate.ir b/xls/dslx/ir_convert/testdata/ir_converter_test_ArrayEnumerate.ir index 435624076b..8c40acde5c 100644 --- a/xls/dslx/ir_convert/testdata/ir_converter_test_ArrayEnumerate.ir +++ b/xls/dslx/ir_convert/testdata/ir_converter_test_ArrayEnumerate.ir @@ -3,23 +3,20 @@ package test_module file_number 0 "xls/dslx/stdlib/std.x" file_number 1 "test_module.x" -fn ____std__enumerate__4_u8_counted_for_0_body(i: bits[32] id=7, result: (bits[32], bits[8])[4] id=10, x: bits[8][4] id=11) -> (bits[32], bits[8])[4] { - literal.8: bits[32] = literal(value=0, id=8) - add.9: bits[32] = add(i, literal.8, id=9) - array_index.12: bits[8] = array_index(x, indices=[add.9], id=12) - tuple.13: (bits[32], bits[8]) = tuple(add.9, array_index.12, id=13) - ret array_update.14: (bits[32], bits[8])[4] = array_update(result, tuple.13, indices=[add.9], id=14) +fn ____std__enumerate__4_u8_counted_for_0_body(i: bits[32] id=4, result: (bits[32], bits[8])[4] id=7, x: bits[8][4] id=8) -> (bits[32], bits[8])[4] { + literal.5: bits[32] = literal(value=0, id=5) + add.6: bits[32] = add(i, literal.5, id=6) + array_index.9: bits[8] = array_index(x, indices=[add.6], id=9) + tuple.10: (bits[32], bits[8]) = tuple(add.6, array_index.9, id=10) + ret array_update.11: (bits[32], bits[8])[4] = array_update(result, tuple.10, indices=[add.6], id=11) } fn __std__enumerate__4_u8(x: bits[8][4] id=1) -> (bits[32], bits[8])[4] { - literal.3: bits[32] = literal(value=0, id=3) - literal.4: bits[8] = literal(value=0, id=4) - tuple.5: (bits[32], bits[8]) = tuple(literal.3, literal.4, id=5) - array.6: (bits[32], bits[8])[4] = array(tuple.5, tuple.5, tuple.5, tuple.5, id=6) + literal.3: (bits[32], bits[8])[4] = literal(value=[(0, 0), (0, 0), (0, 0), (0, 0)], id=3) N: bits[32] = literal(value=4, id=2) - ret counted_for.15: (bits[32], bits[8])[4] = counted_for(array.6, trip_count=4, stride=1, body=____std__enumerate__4_u8_counted_for_0_body, invariant_args=[x], id=15) + ret counted_for.12: (bits[32], bits[8])[4] = counted_for(literal.3, trip_count=4, stride=1, body=____std__enumerate__4_u8_counted_for_0_body, invariant_args=[x], id=12) } -top fn __test_module__main(array: bits[8][4] id=16) -> (bits[32], bits[8])[4] { - ret invoke.17: (bits[32], bits[8])[4] = invoke(array, to_apply=__std__enumerate__4_u8, id=17) +top fn __test_module__main(array: bits[8][4] id=13) -> (bits[32], bits[8])[4] { + ret invoke.14: (bits[32], bits[8])[4] = invoke(array, to_apply=__std__enumerate__4_u8, id=14) } diff --git a/xls/dslx/stdlib/std.x b/xls/dslx/stdlib/std.x index 78f5a843fb..dbfd08b5fd 100644 --- a/xls/dslx/stdlib/std.x +++ b/xls/dslx/stdlib/std.x @@ -19,7 +19,7 @@ pub fn enumerate(x: T[N]) -> (u32, T)[N] { for (i, result) in 0..N { update(result, i, (i, x[i])) - }([(u32:0, zero!()), ...]) + }(zero!<(u32, T)[N]>()) } #[test] @@ -32,6 +32,13 @@ fn emumerate_test() { assert_eq(enumerated[3], (3, 8)); } +#[test] +fn emumerate_empty_array_test() { + let empty_array: u32[0] = []; + let enumerated_empty = enumerate(empty_array); + assert_eq(enumerated_empty, []); +} + #[test] fn enumerate_type_test() { type RamData = uN[8]; From 6c17e74746b6c694781d41dd4cd634edf183e26b Mon Sep 17 00:00:00 2001 From: Joanna Brozek Date: Thu, 30 Apr 2026 09:43:32 +0200 Subject: [PATCH 6/6] deduce_utils: Allow indexing into zero-sized arrays for constexpr --- xls/dslx/type_system/deduce_utils.cc | 22 +++++++++---------- xls/dslx/type_system/typecheck_module_test.cc | 7 ------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/xls/dslx/type_system/deduce_utils.cc b/xls/dslx/type_system/deduce_utils.cc index 598f005490..d7489cd405 100644 --- a/xls/dslx/type_system/deduce_utils.cc +++ b/xls/dslx/type_system/deduce_utils.cc @@ -239,18 +239,6 @@ absl::Status ValidateArrayIndex(const Index& node, const Type& array_type, // producing a `Type`. const auto& casted_array_type = dynamic_cast(array_type); - // Reject indexing into zero-sized arrays regardless of whether the index is - // constexpr, since out-of-bounds semantics (return last element) are - // undefined for empty arrays. - - XLS_ASSIGN_OR_RETURN(int64_t concrete_size, - casted_array_type.size().GetAsInt64()); - if (concrete_size == 0) { - return TypeInferenceErrorStatus(node.span(), &array_type, - "Zero-sized arrays cannot be indexed", - file_table); - } - if (!ti.IsKnownConstExpr(rhs)) { return absl::OkStatus(); } @@ -270,6 +258,16 @@ absl::Status ValidateArrayIndex(const Index& node, const Type& array_type, constexpr_index), file_table); } + + // Reject indexing into zero-sized arrays, since out-of-bounds semantics + // (return last element) are undefined for empty arrays. + XLS_ASSIGN_OR_RETURN(int64_t concrete_size, + casted_array_type.size().GetAsInt64()); + if (concrete_size == 0) { + return TypeInferenceErrorStatus(node.span(), &array_type, + "Zero-sized arrays cannot be indexed", + file_table); + } return absl::OkStatus(); } diff --git a/xls/dslx/type_system/typecheck_module_test.cc b/xls/dslx/type_system/typecheck_module_test.cc index b2e9b7984e..07a3f51fc9 100644 --- a/xls/dslx/type_system/typecheck_module_test.cc +++ b/xls/dslx/type_system/typecheck_module_test.cc @@ -116,13 +116,6 @@ fn main() -> u2 { p(u2:0) } XLS_EXPECT_OK(Typecheck(text)); } -TEST_F(TypecheckV2Test, IndexZeroSizedArray) { - std::string_view text = R"(fn f(a: u8[0], b: u3) -> u8 { a[b] })"; - EXPECT_THAT(Typecheck(text), - StatusIs(absl::StatusCode::kInvalidArgument, - HasSubstr("Zero-sized arrays cannot be indexed"))); -} - TEST_F(TypecheckV2Test, ZeroMacroFunctionRefIsNotValue) { // Bare parametric macro reference should have function type `() -> E` and // not be directly usable as a value of type `E`.