From 2d586de63cc1a55da387e2a2d8e88b7fe75ad591 Mon Sep 17 00:00:00 2001 From: Jon Ross-Perkins Date: Fri, 25 Aug 2023 15:31:26 -0700 Subject: [PATCH] Refactor index logic to share more code. (#3152) Trying to improve diagnostic names and code flow. I was thinking "operand" might be a better name than "name" in the context of what `a` is in `a[b]`, where we already call `b` the `index`. Flow-wise, note this replaces pushing BuiltinError with instead creating Index nodes that may contain an error. This is intended to aim towards producing a more consistent SemIR in the face of errors. There are pros and cons of both approaches, but I'm aiming for simpler control flow. --- toolchain/diagnostics/diagnostic_kind.def | 6 +- .../semantics/semantics_handle_index.cpp | 136 ++++++++++-------- .../index/fail_array_large_index.carbon | 12 +- .../index/fail_array_non_int_indexing.carbon | 12 +- .../fail_array_out_of_bound_access.carbon | 12 +- .../index/fail_empty_tuple_access.carbon | 3 + .../index/fail_non_deterministic_type.carbon | 5 +- .../index/fail_non_tuple_access.carbon | 2 +- .../index/fail_tuple_large_index.carbon | 5 +- .../index/fail_tuple_non_int_indexing.carbon | 7 +- .../fail_tuple_out_of_bound_access.carbon | 5 +- 11 files changed, 126 insertions(+), 79 deletions(-) diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 5bbc54e7ac9d..7a0837faf771 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -112,9 +112,9 @@ CARBON_DIAGNOSTIC_KIND(CallArgTypeMismatch) CARBON_DIAGNOSTIC_KIND(MissingReturnStatement) CARBON_DIAGNOSTIC_KIND(RepeatedConst) CARBON_DIAGNOSTIC_KIND(InvalidArrayExpression) -CARBON_DIAGNOSTIC_KIND(InvalidIndexExpression) -CARBON_DIAGNOSTIC_KIND(NondeterministicType) -CARBON_DIAGNOSTIC_KIND(OutOfBoundsAccess) +CARBON_DIAGNOSTIC_KIND(TypeNotIndexable) +CARBON_DIAGNOSTIC_KIND(IndexOutOfBounds) +CARBON_DIAGNOSTIC_KIND(TupleIndexIntegerLiteral) CARBON_DIAGNOSTIC_KIND(ReturnStatementDisallowExpression) CARBON_DIAGNOSTIC_KIND(ReturnStatementImplicitNote) CARBON_DIAGNOSTIC_KIND(ReturnStatementMissingExpression) diff --git a/toolchain/semantics/semantics_handle_index.cpp b/toolchain/semantics/semantics_handle_index.cpp index 2d5920474824..5d9531c481ee 100644 --- a/toolchain/semantics/semantics_handle_index.cpp +++ b/toolchain/semantics/semantics_handle_index.cpp @@ -15,79 +15,93 @@ auto HandleIndexExpressionStart(Context& /*context*/, return true; } +// Validates that the index (required to be an IntegerLiteral) is valid within +// the array or tuple size. Returns the index on success, or nullptr on failure. +static auto ValidateIntegerLiteralBound(Context& context, + ParseTree::Node parse_node, + SemIR::Node operand_node, + SemIR::Node index_node, int size) + -> const llvm::APInt* { + const auto& index_val = context.semantics_ir().GetIntegerLiteral( + index_node.GetAsIntegerLiteral()); + if (index_val.uge(size)) { + CARBON_DIAGNOSTIC(IndexOutOfBounds, Error, + "Index `{0}` is past the end of `{1}`.", llvm::APSInt, + std::string); + context.emitter().Emit( + parse_node, IndexOutOfBounds, + llvm::APSInt(index_val, /*isUnsigned=*/true), + context.semantics_ir().StringifyType(operand_node.type_id())); + return nullptr; + } + return &index_val; +} + auto HandleIndexExpression(Context& context, ParseTree::Node parse_node) -> bool { - CARBON_DIAGNOSTIC(OutOfBoundsAccess, Error, - "Index `{0}` is past the end of `{1}`.", llvm::APSInt, - std::string); - auto index_node_id = context.node_stack().PopExpression(); auto index_node = context.semantics_ir().GetNode(index_node_id); - auto name_node_id = context.node_stack().PopExpression(); - name_node_id = context.MaterializeIfInitializing(name_node_id); - auto name_node = context.semantics_ir().GetNode(name_node_id); - auto name_type_id = - context.semantics_ir().GetTypeAllowBuiltinTypes(name_node.type_id()); - auto name_type_node = context.semantics_ir().GetNode(name_type_id); + auto operand_node_id = context.node_stack().PopExpression(); + operand_node_id = context.MaterializeIfInitializing(operand_node_id); + auto operand_node = context.semantics_ir().GetNode(operand_node_id); + auto operand_type_id = operand_node.type_id(); + auto operand_type_node = context.semantics_ir().GetNode( + context.semantics_ir().GetTypeAllowBuiltinTypes(operand_type_id)); - if (name_type_node.kind() == SemIR::NodeKind::ArrayType) { - auto [bound_id, type_id] = name_type_node.GetAsArrayType(); - if (index_node.kind() == SemIR::NodeKind::IntegerLiteral) { - const auto& index_val = context.semantics_ir().GetIntegerLiteral( - index_node.GetAsIntegerLiteral()); - if (index_val.uge(context.semantics_ir().GetArrayBoundValue(bound_id))) { - context.emitter().Emit( - parse_node, OutOfBoundsAccess, - llvm::APSInt(index_val, /*isUnsigned=*/true), - context.semantics_ir().StringifyType(name_node.type_id())); - } else { - context.AddNodeAndPush( - parse_node, SemIR::Node::ArrayIndex::Make( - parse_node, type_id, name_node_id, index_node_id)); - return true; + switch (operand_type_node.kind()) { + case SemIR::NodeKind::ArrayType: { + auto [bound_id, element_type_id] = operand_type_node.GetAsArrayType(); + // We can check whether integers are in-bounds, although it doesn't affect + // the IR for an array. + if (index_node.kind() == SemIR::NodeKind::IntegerLiteral && + !ValidateIntegerLiteralBound( + context, parse_node, operand_node, index_node, + context.semantics_ir().GetArrayBoundValue(bound_id))) { + index_node_id = SemIR::NodeId::BuiltinError; } - } else if (context.ImplicitAsRequired( - index_node.parse_node(), index_node_id, - context.CanonicalizeType( - SemIR::NodeId::BuiltinIntegerType)) != - SemIR::NodeId::BuiltinError) { - context.AddNodeAndPush( - parse_node, SemIR::Node::ArrayIndex::Make( - parse_node, type_id, name_node_id, index_node_id)); + auto cast_index_id = context.ImplicitAsRequired( + index_node.parse_node(), index_node_id, + context.CanonicalizeType(SemIR::NodeId::BuiltinIntegerType)); + context.AddNodeAndPush(parse_node, SemIR::Node::ArrayIndex::Make( + parse_node, element_type_id, + operand_node_id, cast_index_id)); return true; } - } else if (name_type_node.kind() == SemIR::NodeKind::TupleType) { - if (index_node.kind() == SemIR::NodeKind::IntegerLiteral) { - const auto& index_val = context.semantics_ir().GetIntegerLiteral( - index_node.GetAsIntegerLiteral()); - auto type_block = - context.semantics_ir().GetTypeBlock(name_type_node.GetAsTupleType()); - - if (index_val.uge(static_cast(type_block.size()))) { - context.emitter().Emit( - parse_node, OutOfBoundsAccess, - llvm::APSInt(index_val, /*isUnsigned=*/true), - context.semantics_ir().StringifyType(name_node.type_id())); + case SemIR::NodeKind::TupleType: { + SemIR::TypeId element_type_id = SemIR::TypeId::Error; + if (index_node.kind() == SemIR::NodeKind::IntegerLiteral) { + auto type_block = context.semantics_ir().GetTypeBlock( + operand_type_node.GetAsTupleType()); + if (const auto* index_val = + ValidateIntegerLiteralBound(context, parse_node, operand_node, + index_node, type_block.size())) { + element_type_id = type_block[index_val->getZExtValue()]; + } else { + index_node_id = SemIR::NodeId::BuiltinError; + } } else { - context.AddNodeAndPush( - parse_node, SemIR::Node::TupleIndex::Make( - parse_node, type_block[index_val.getZExtValue()], - name_node_id, index_node_id)); - return true; + CARBON_DIAGNOSTIC(TupleIndexIntegerLiteral, Error, + "Tuples indices must be integer literals."); + context.emitter().Emit(parse_node, TupleIndexIntegerLiteral); + index_node_id = SemIR::NodeId::BuiltinError; } - } else { - CARBON_DIAGNOSTIC(NondeterministicType, Error, - "Type cannot be determined at compile time."); - context.emitter().Emit(parse_node, NondeterministicType); + context.AddNodeAndPush(parse_node, SemIR::Node::TupleIndex::Make( + parse_node, element_type_id, + operand_node_id, index_node_id)); + return true; + } + default: { + if (operand_type_id != SemIR::TypeId::Error) { + CARBON_DIAGNOSTIC(TypeNotIndexable, Error, + "`{0}` does not support indexing.", std::string); + context.emitter().Emit( + parse_node, TypeNotIndexable, + context.semantics_ir().StringifyType(operand_type_id)); + } + context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError); + return true; } - } else if (name_type_id != SemIR::NodeId::BuiltinError) { - CARBON_DIAGNOSTIC(InvalidIndexExpression, Error, - "Invalid index expression."); - context.emitter().Emit(parse_node, InvalidIndexExpression); } - - context.node_stack().Push(parse_node, SemIR::NodeId::BuiltinError); - return true; } } // namespace Carbon::Check diff --git a/toolchain/semantics/testdata/index/fail_array_large_index.carbon b/toolchain/semantics/testdata/index/fail_array_large_index.carbon index c8117dc089c9..88cd69581a96 100644 --- a/toolchain/semantics/testdata/index/fail_array_large_index.carbon +++ b/toolchain/semantics/testdata/index/fail_array_large_index.carbon @@ -46,7 +46,9 @@ var b: i32 = a[0xFFFFFFFFFFFFFFFFF]; // CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+7}, // CHECK:STDOUT: {kind: VarStorage, arg0: str1, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type0}, -// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: nodeError}, +// CHECK:STDOUT: {kind: ArrayIndex, arg0: node+2, arg1: nodeError, type: type0}, +// CHECK:STDOUT: {kind: BindValue, arg0: node+11, type: type0}, +// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: node+12}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -64,6 +66,8 @@ var b: i32 = a[0xFFFFFFFFFFFFFFFFF]; // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, // CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+4, @@ -81,6 +85,8 @@ var b: i32 = a[0xFFFFFFFFFFFFFFFFF]; // CHECK:STDOUT: %.loc7_23.3: [i32; 1] = array_value %.loc7_23.2 // CHECK:STDOUT: assign %a, %.loc7_23.3 // CHECK:STDOUT: %b: i32 = var "b" -// CHECK:STDOUT: %.loc11: i32 = int_literal -1 -// CHECK:STDOUT: assign %b, +// CHECK:STDOUT: %.loc11_16: i32 = int_literal -1 +// CHECK:STDOUT: %.loc11_35.1: i32 = array_index %a, +// CHECK:STDOUT: %.loc11_35.2: i32 = bind_value %.loc11_35.1 +// CHECK:STDOUT: assign %b, %.loc11_35.2 // CHECK:STDOUT: } diff --git a/toolchain/semantics/testdata/index/fail_array_non_int_indexing.carbon b/toolchain/semantics/testdata/index/fail_array_non_int_indexing.carbon index 9ac95f7df463..73de098406a4 100644 --- a/toolchain/semantics/testdata/index/fail_array_non_int_indexing.carbon +++ b/toolchain/semantics/testdata/index/fail_array_non_int_indexing.carbon @@ -47,7 +47,9 @@ var b: i32 = a[2.6]; // CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+7}, // CHECK:STDOUT: {kind: VarStorage, arg0: str1, type: type0}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: type3}, -// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: nodeError}, +// CHECK:STDOUT: {kind: ArrayIndex, arg0: node+2, arg1: nodeError, type: type0}, +// CHECK:STDOUT: {kind: BindValue, arg0: node+11, type: type0}, +// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: node+12}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -65,6 +67,8 @@ var b: i32 = a[2.6]; // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, // CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+4, @@ -82,6 +86,8 @@ var b: i32 = a[2.6]; // CHECK:STDOUT: %.loc7_23.3: [i32; 1] = array_value %.loc7_23.2 // CHECK:STDOUT: assign %a, %.loc7_23.3 // CHECK:STDOUT: %b: i32 = var "b" -// CHECK:STDOUT: %.loc11: f64 = real_literal 26e-1 -// CHECK:STDOUT: assign %b, +// CHECK:STDOUT: %.loc11_16: f64 = real_literal 26e-1 +// CHECK:STDOUT: %.loc11_19.1: i32 = array_index %a, +// CHECK:STDOUT: %.loc11_19.2: i32 = bind_value %.loc11_19.1 +// CHECK:STDOUT: assign %b, %.loc11_19.2 // CHECK:STDOUT: } diff --git a/toolchain/semantics/testdata/index/fail_array_out_of_bound_access.carbon b/toolchain/semantics/testdata/index/fail_array_out_of_bound_access.carbon index e76a03ac5933..3756cfbc1481 100644 --- a/toolchain/semantics/testdata/index/fail_array_out_of_bound_access.carbon +++ b/toolchain/semantics/testdata/index/fail_array_out_of_bound_access.carbon @@ -46,7 +46,9 @@ var b: i32 = a[2]; // CHECK:STDOUT: {kind: Assign, arg0: node+2, arg1: node+7}, // CHECK:STDOUT: {kind: VarStorage, arg0: str1, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type0}, -// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: nodeError}, +// CHECK:STDOUT: {kind: ArrayIndex, arg0: node+2, arg1: nodeError, type: type0}, +// CHECK:STDOUT: {kind: BindValue, arg0: node+11, type: type0}, +// CHECK:STDOUT: {kind: Assign, arg0: node+9, arg1: node+12}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ // CHECK:STDOUT: [ @@ -64,6 +66,8 @@ var b: i32 = a[2]; // CHECK:STDOUT: node+9, // CHECK:STDOUT: node+10, // CHECK:STDOUT: node+11, +// CHECK:STDOUT: node+12, +// CHECK:STDOUT: node+13, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+4, @@ -81,6 +85,8 @@ var b: i32 = a[2]; // CHECK:STDOUT: %.loc7_23.3: [i32; 1] = array_value %.loc7_23.2 // CHECK:STDOUT: assign %a, %.loc7_23.3 // CHECK:STDOUT: %b: i32 = var "b" -// CHECK:STDOUT: %.loc11: i32 = int_literal 2 -// CHECK:STDOUT: assign %b, +// CHECK:STDOUT: %.loc11_16: i32 = int_literal 2 +// CHECK:STDOUT: %.loc11_17.1: i32 = array_index %a, +// CHECK:STDOUT: %.loc11_17.2: i32 = bind_value %.loc11_17.1 +// CHECK:STDOUT: assign %b, %.loc11_17.2 // CHECK:STDOUT: } diff --git a/toolchain/semantics/testdata/index/fail_empty_tuple_access.carbon b/toolchain/semantics/testdata/index/fail_empty_tuple_access.carbon index 638a22a0fcfc..5932de553403 100644 --- a/toolchain/semantics/testdata/index/fail_empty_tuple_access.carbon +++ b/toolchain/semantics/testdata/index/fail_empty_tuple_access.carbon @@ -43,6 +43,7 @@ fn Run() { // CHECK:STDOUT: {kind: Call, arg0: block0, arg1: function0, type: type0}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int0, type: type1}, // CHECK:STDOUT: {kind: MaterializeTemporary, type: type0}, +// CHECK:STDOUT: {kind: TupleIndex, arg0: node+6, arg1: nodeError, type: typeError}, // CHECK:STDOUT: {kind: Return}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -61,6 +62,7 @@ fn Run() { // CHECK:STDOUT: node+5, // CHECK:STDOUT: node+6, // CHECK:STDOUT: node+7, +// CHECK:STDOUT: node+8, // CHECK:STDOUT: ], // CHECK:STDOUT: ] // CHECK:STDOUT: @@ -80,5 +82,6 @@ fn Run() { // CHECK:STDOUT: %.loc13_4.2: () = call @F() // CHECK:STDOUT: %.loc13_7: i32 = int_literal 0 // CHECK:STDOUT: %.loc13_4.3: () = materialize_temporary +// CHECK:STDOUT: %.loc13_8: = tuple_index %.loc13_4.3, // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/semantics/testdata/index/fail_non_deterministic_type.carbon b/toolchain/semantics/testdata/index/fail_non_deterministic_type.carbon index ee01c300c48c..f8bbca0d38dc 100644 --- a/toolchain/semantics/testdata/index/fail_non_deterministic_type.carbon +++ b/toolchain/semantics/testdata/index/fail_non_deterministic_type.carbon @@ -6,7 +6,7 @@ var a: (i32, i32) = (2, 3); var b: i32 = 0; -// CHECK:STDERR: fail_non_deterministic_type.carbon:[[@LINE+3]]:17: Type cannot be determined at compile time. +// CHECK:STDERR: fail_non_deterministic_type.carbon:[[@LINE+3]]:17: Tuples indices must be integer literals. // CHECK:STDERR: var c: i32 = a[b]; // CHECK:STDERR: ^ var c: i32 = a[b]; @@ -58,6 +58,7 @@ var c: i32 = a[b]; // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type1}, // CHECK:STDOUT: {kind: Assign, arg0: node+12, arg1: node+13}, // CHECK:STDOUT: {kind: VarStorage, arg0: str2, type: type1}, +// CHECK:STDOUT: {kind: TupleIndex, arg0: node+5, arg1: nodeError, type: typeError}, // CHECK:STDOUT: {kind: Assign, arg0: node+15, arg1: nodeError}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -81,6 +82,7 @@ var c: i32 = a[b]; // CHECK:STDOUT: node+14, // CHECK:STDOUT: node+15, // CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, @@ -109,5 +111,6 @@ var c: i32 = a[b]; // CHECK:STDOUT: %.loc8: i32 = int_literal 0 // CHECK:STDOUT: assign %b, %.loc8 // CHECK:STDOUT: %c: i32 = var "c" +// CHECK:STDOUT: %.loc12: = tuple_index %a, // CHECK:STDOUT: assign %c, // CHECK:STDOUT: } diff --git a/toolchain/semantics/testdata/index/fail_non_tuple_access.carbon b/toolchain/semantics/testdata/index/fail_non_tuple_access.carbon index 091fe535bbef..85a013cef86f 100644 --- a/toolchain/semantics/testdata/index/fail_non_tuple_access.carbon +++ b/toolchain/semantics/testdata/index/fail_non_tuple_access.carbon @@ -5,7 +5,7 @@ // AUTOUPDATE fn Main() { - // CHECK:STDERR: fail_non_tuple_access.carbon:[[@LINE+3]]:6: Invalid index expression. + // CHECK:STDERR: fail_non_tuple_access.carbon:[[@LINE+3]]:6: `i32` does not support indexing. // CHECK:STDERR: 0[1]; // CHECK:STDERR: ^ 0[1]; diff --git a/toolchain/semantics/testdata/index/fail_tuple_large_index.carbon b/toolchain/semantics/testdata/index/fail_tuple_large_index.carbon index 12ae96d9724f..1af540d047fd 100644 --- a/toolchain/semantics/testdata/index/fail_tuple_large_index.carbon +++ b/toolchain/semantics/testdata/index/fail_tuple_large_index.carbon @@ -55,6 +55,7 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF]; // CHECK:STDOUT: {kind: Assign, arg0: node+11, arg1: node+12}, // CHECK:STDOUT: {kind: VarStorage, arg0: str2, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int1, type: type1}, +// CHECK:STDOUT: {kind: TupleIndex, arg0: node+11, arg1: nodeError, type: typeError}, // CHECK:STDOUT: {kind: Assign, arg0: node+14, arg1: nodeError}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -78,6 +79,7 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF]; // CHECK:STDOUT: node+14, // CHECK:STDOUT: node+15, // CHECK:STDOUT: node+16, +// CHECK:STDOUT: node+17, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, @@ -106,6 +108,7 @@ var c: i32 = b[0xFFFFFFFFFFFFFFFFF]; // CHECK:STDOUT: %.loc7_5: (i32,) = bind_value %a // CHECK:STDOUT: assign %b, %.loc7_5 // CHECK:STDOUT: %c: i32 = var "c" -// CHECK:STDOUT: %.loc12: i32 = int_literal -1 +// CHECK:STDOUT: %.loc12_16: i32 = int_literal -1 +// CHECK:STDOUT: %.loc12_35: = tuple_index %b, // CHECK:STDOUT: assign %c, // CHECK:STDOUT: } diff --git a/toolchain/semantics/testdata/index/fail_tuple_non_int_indexing.carbon b/toolchain/semantics/testdata/index/fail_tuple_non_int_indexing.carbon index a91073f52555..97bf48df58f2 100644 --- a/toolchain/semantics/testdata/index/fail_tuple_non_int_indexing.carbon +++ b/toolchain/semantics/testdata/index/fail_tuple_non_int_indexing.carbon @@ -5,7 +5,7 @@ // AUTOUPDATE var a: (i32, i32) = (12, 6); -// CHECK:STDERR: fail_tuple_non_int_indexing.carbon:[[@LINE+3]]:19: Type cannot be determined at compile time. +// CHECK:STDERR: fail_tuple_non_int_indexing.carbon:[[@LINE+3]]:19: Tuples indices must be integer literals. // CHECK:STDERR: var b: i32 = a[2.6]; // CHECK:STDERR: ^ var b: i32 = a[2.6]; @@ -55,6 +55,7 @@ var b: i32 = a[2.6]; // CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: node+10}, // CHECK:STDOUT: {kind: VarStorage, arg0: str1, type: type1}, // CHECK:STDOUT: {kind: RealLiteral, arg0: real0, type: type3}, +// CHECK:STDOUT: {kind: TupleIndex, arg0: node+5, arg1: nodeError, type: typeError}, // CHECK:STDOUT: {kind: Assign, arg0: node+12, arg1: nodeError}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -76,6 +77,7 @@ var b: i32 = a[2.6]; // CHECK:STDOUT: node+12, // CHECK:STDOUT: node+13, // CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+15, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, @@ -101,6 +103,7 @@ var b: i32 = a[2.6]; // CHECK:STDOUT: %.loc7_27: (i32, i32) = tuple_value (%.loc7_22.2, %.loc7_26.2) // CHECK:STDOUT: assign %a, %.loc7_27 // CHECK:STDOUT: %b: i32 = var "b" -// CHECK:STDOUT: %.loc11: f64 = real_literal 26e-1 +// CHECK:STDOUT: %.loc11_16: f64 = real_literal 26e-1 +// CHECK:STDOUT: %.loc11_19: = tuple_index %a, // CHECK:STDOUT: assign %b, // CHECK:STDOUT: } diff --git a/toolchain/semantics/testdata/index/fail_tuple_out_of_bound_access.carbon b/toolchain/semantics/testdata/index/fail_tuple_out_of_bound_access.carbon index b49f9ed8b2b4..ddf73ce139ae 100644 --- a/toolchain/semantics/testdata/index/fail_tuple_out_of_bound_access.carbon +++ b/toolchain/semantics/testdata/index/fail_tuple_out_of_bound_access.carbon @@ -54,6 +54,7 @@ var b: i32 = a[2]; // CHECK:STDOUT: {kind: Assign, arg0: node+5, arg1: node+10}, // CHECK:STDOUT: {kind: VarStorage, arg0: str1, type: type1}, // CHECK:STDOUT: {kind: IntegerLiteral, arg0: int2, type: type1}, +// CHECK:STDOUT: {kind: TupleIndex, arg0: node+5, arg1: nodeError, type: typeError}, // CHECK:STDOUT: {kind: Assign, arg0: node+12, arg1: nodeError}, // CHECK:STDOUT: ] // CHECK:STDOUT: node_blocks: [ @@ -75,6 +76,7 @@ var b: i32 = a[2]; // CHECK:STDOUT: node+12, // CHECK:STDOUT: node+13, // CHECK:STDOUT: node+14, +// CHECK:STDOUT: node+15, // CHECK:STDOUT: ], // CHECK:STDOUT: [ // CHECK:STDOUT: node+0, @@ -100,6 +102,7 @@ var b: i32 = a[2]; // CHECK:STDOUT: %.loc7_27: (i32, i32) = tuple_value (%.loc7_22.2, %.loc7_26.2) // CHECK:STDOUT: assign %a, %.loc7_27 // CHECK:STDOUT: %b: i32 = var "b" -// CHECK:STDOUT: %.loc11: i32 = int_literal 2 +// CHECK:STDOUT: %.loc11_16: i32 = int_literal 2 +// CHECK:STDOUT: %.loc11_17: = tuple_index %a, // CHECK:STDOUT: assign %b, // CHECK:STDOUT: }