From 7938d9a8d0556498754feb12695776702984c235 Mon Sep 17 00:00:00 2001 From: Geoff Romer Date: Fri, 6 Feb 2026 18:41:22 -0800 Subject: [PATCH] Lex/parse support for ->?, :?, and form literals (#6695) See #5389 (pending) for the language design. --- toolchain/check/BUILD | 1 + toolchain/check/handle_binding_pattern.cpp | 5 + toolchain/check/handle_form_literal.cpp | 40 ++++ toolchain/check/handle_function.cpp | 4 + toolchain/check/node_stack.h | 3 + toolchain/check/testdata/array/import.carbon | 16 +- .../testdata/class/import_indirect.carbon | 112 ++++++------ .../check/testdata/impl/error_recovery.carbon | 2 +- .../function/arithmetic_types_direct.carbon | 2 +- .../primitives/import_symbolic.carbon | 144 +++++++-------- toolchain/check/testdata/struct/import.carbon | 22 +-- toolchain/check/testdata/tuple/import.carbon | 22 +-- toolchain/diagnostics/kind.def | 1 + toolchain/lex/token_kind.def | 4 + toolchain/parse/context.h | 4 + toolchain/parse/handle_binding_pattern.cpp | 57 ++++-- toolchain/parse/handle_expr.cpp | 5 + toolchain/parse/handle_form_literal.cpp | 78 ++++++++ toolchain/parse/handle_function.cpp | 10 + toolchain/parse/node_ids.h | 2 + toolchain/parse/node_kind.def | 9 + toolchain/parse/precedence.cpp | 1 - toolchain/parse/state.def | 82 ++++++++- .../testdata/basics/form_literals.carbon | 173 ++++++++++++++++++ .../testdata/function/declaration.carbon | 62 ++++++- .../testdata/generics/impl/fail_impl.carbon | 2 +- .../interface/fail_self_param_syntax.carbon | 2 +- .../testdata/let/fail_missing_type.carbon | 2 +- toolchain/parse/tree.h | 7 +- toolchain/parse/tree_and_subtrees.cpp | 16 +- toolchain/parse/typed_nodes.h | 63 ++++++- 31 files changed, 758 insertions(+), 195 deletions(-) create mode 100644 toolchain/check/handle_form_literal.cpp create mode 100644 toolchain/parse/handle_form_literal.cpp create mode 100644 toolchain/parse/testdata/basics/form_literals.carbon diff --git a/toolchain/check/BUILD b/toolchain/check/BUILD index ee11619b9989..218bf6a02c21 100644 --- a/toolchain/check/BUILD +++ b/toolchain/check/BUILD @@ -244,6 +244,7 @@ cc_library( "//toolchain/lex:token_index", "//toolchain/lex:token_kind", "//toolchain/lex:tokenized_buffer", + "//toolchain/parse:node_category", "//toolchain/parse:node_kind", "//toolchain/parse:tree", "//toolchain/sem_ir:absolute_node_id", diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index 19c5a29dcfc7..f8201a595e92 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -301,6 +301,11 @@ auto HandleParseNode(Context& context, Parse::VarBindingPatternId node_id) Parse::NodeKind::VarBindingPattern); } +auto HandleParseNode(Context& context, Parse::FormBindingPatternId node_id) + -> bool { + return context.TODO(node_id, "Implement :? support"); +} + auto HandleParseNode(Context& context, Parse::CompileTimeBindingPatternStartId /*node_id*/) -> bool { diff --git a/toolchain/check/handle_form_literal.cpp b/toolchain/check/handle_form_literal.cpp new file mode 100644 index 000000000000..2811db2e41b0 --- /dev/null +++ b/toolchain/check/handle_form_literal.cpp @@ -0,0 +1,40 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/check/context.h" +#include "toolchain/check/handle.h" +#include "toolchain/parse/node_category.h" + +namespace Carbon::Check { + +auto HandleParseNode(Context& context, Parse::RefPrimitiveFormId node_id) + -> bool { + return context.TODO(node_id, "Implement form literals"); +} + +auto HandleParseNode(Context& context, Parse::ValPrimitiveFormId node_id) + -> bool { + return context.TODO(node_id, "Implement form literals"); +} + +auto HandleParseNode(Context& context, Parse::VarPrimitiveFormId node_id) + -> bool { + return context.TODO(node_id, "Implement form literals"); +} + +auto HandleParseNode(Context& context, Parse::FormLiteralKeywordId node_id) + -> bool { + return context.TODO(node_id, "Implement form literals"); +} + +auto HandleParseNode(Context& context, Parse::FormLiteralOpenParenId node_id) + -> bool { + return context.TODO(node_id, "Implement form literals"); +} + +auto HandleParseNode(Context& context, Parse::FormLiteralId node_id) -> bool { + return context.TODO(node_id, "Implement form literals"); +} + +} // namespace Carbon::Check diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 1c5b67337e91..8c8c3d1671bf 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -76,6 +76,10 @@ auto HandleParseNode(Context& context, Parse::ReturnTypeId node_id) -> bool { return true; } +auto HandleParseNode(Context& context, Parse::ReturnFormId node_id) -> bool { + return context.TODO(node_id, "Support ->?"); +} + // Diagnoses issues with the modifiers, removing modifiers that shouldn't be // present. static auto DiagnoseModifiers(Context& context, diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 901562558b27..1abba5c678de 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -427,6 +427,7 @@ class NodeStack { case Parse::NodeKind::ImplicitParamList: case Parse::NodeKind::WhileConditionStart: case Parse::NodeKind::ReturnType: + case Parse::NodeKind::ReturnForm: return Id::KindFor(); case Parse::NodeKind::FunctionDefinitionStart: case Parse::NodeKind::BuiltinFunctionDefinitionStart: @@ -497,6 +498,8 @@ class NodeStack { case Parse::NodeKind::FileStart: case Parse::NodeKind::ForHeader: case Parse::NodeKind::Forall: + case Parse::NodeKind::FormLiteralKeyword: + case Parse::NodeKind::FormLiteralOpenParen: case Parse::NodeKind::IdentifierNameQualifierWithParams: case Parse::NodeKind::IdentifierNameQualifierWithoutParams: case Parse::NodeKind::IdentifierPackageName: diff --git a/toolchain/check/testdata/array/import.carbon b/toolchain/check/testdata/array/import.carbon index 65556d5bfadc..f91810f99b92 100644 --- a/toolchain/check/testdata/array/import.carbon +++ b/toolchain/check/testdata/array/import.carbon @@ -31,16 +31,16 @@ fn G(n: i32) -> i32 { library "[[@TEST_NAME]]"; interface I { - let val:! array(i32, 1); + let value:! array(i32, 1); } class C {} -// CHECK:STDERR: fail_todo_symbolic_decl.carbon:[[@LINE+4]]:26: error: expression is runtime; expected constant [EvalRequiresConstantValue] -// CHECK:STDERR: impl C as I where .val = (1,) {} -// CHECK:STDERR: ^~~~ +// CHECK:STDERR: fail_todo_symbolic_decl.carbon:[[@LINE+4]]:28: error: expression is runtime; expected constant [EvalRequiresConstantValue] +// CHECK:STDERR: impl C as I where .value = (1,) {} +// CHECK:STDERR: ^~~~ // CHECK:STDERR: -impl C as I where .val = (1,) {} +impl C as I where .value = (1,) {} // --- fail_todo_import_symbolic_decl.carbon @@ -50,10 +50,10 @@ import library "symbolic_decl"; fn F() -> array(i32, 1) { //@dump-sem-ir-begin // CHECK:STDERR: fail_todo_import_symbolic_decl.carbon:[[@LINE+4]]:11: error: cannot convert type `C` into type implementing `I` [ConversionFailureTypeToFacet] - // CHECK:STDERR: return (C as I).val; + // CHECK:STDERR: return (C as I).value; // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -131,7 +131,7 @@ fn F() -> array(i32, 1) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C] // CHECK:STDOUT: %I.ref: type = name_ref I, imports.%Main.I [concrete = constants.%I.type] -// CHECK:STDOUT: %val.ref: = name_ref val, [concrete = ] +// CHECK:STDOUT: %value.ref: = name_ref value, [concrete = ] // CHECK:STDOUT: return to %return.param // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/import_indirect.carbon b/toolchain/check/testdata/class/import_indirect.carbon index 2a9935c3d9e5..02f8a5b1d21d 100644 --- a/toolchain/check/testdata/class/import_indirect.carbon +++ b/toolchain/check/testdata/class/import_indirect.carbon @@ -71,8 +71,8 @@ library "[[@TEST_NAME]]"; import library "a"; import library "b"; -var val: C = {}; -var ptr: D* = &val; +var value: C = {}; +var ptr: D* = &value; // --- triangle_reverse.carbon @@ -81,8 +81,8 @@ library "[[@TEST_NAME]]"; import library "b"; import library "a"; -var val: C = {}; -var ptr: D* = &val; +var value: C = {}; +var ptr: D* = &value; // --- diamond.carbon @@ -91,8 +91,8 @@ library "[[@TEST_NAME]]"; import library "b"; import library "c"; -var val: D = {}; -var ptr: E* = &val; +var value: D = {}; +var ptr: E* = &value; // --- diamond_reverse.carbon @@ -101,8 +101,8 @@ library "[[@TEST_NAME]]"; import library "c"; import library "b"; -var val: D = {}; -var ptr: E* = &val; +var value: D = {}; +var ptr: E* = &value; // CHECK:STDOUT: --- a.carbon // CHECK:STDOUT: @@ -339,7 +339,7 @@ var ptr: E* = &val; // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %ptr.31e: type = ptr_type %C [concrete] // CHECK:STDOUT: %pattern_type.506: type = pattern_type %ptr.31e [concrete] -// CHECK:STDOUT: %addr: %ptr.31e = addr_of file.%val.var [concrete] +// CHECK:STDOUT: %addr: %ptr.31e = addr_of file.%value.var [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %T.67d: type = symbolic_binding T, 0 [symbolic] @@ -379,18 +379,18 @@ var ptr: E* = &val; // CHECK:STDOUT: .b_val = imports.%Main.b_val // CHECK:STDOUT: .b_ptr = imports.%Main.b_ptr // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .val = %val +// CHECK:STDOUT: .value = %value // CHECK:STDOUT: .ptr = %ptr.loc8_5 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %val.patt: %pattern_type.7c7 = ref_binding_pattern val [concrete] -// CHECK:STDOUT: %val.var_patt: %pattern_type.7c7 = var_pattern %val.patt [concrete] +// CHECK:STDOUT: %value.patt: %pattern_type.7c7 = ref_binding_pattern value [concrete] +// CHECK:STDOUT: %value.var_patt: %pattern_type.7c7 = var_pattern %value.patt [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %val.var: ref %C = var %val.var_patt [concrete] +// CHECK:STDOUT: %value.var: ref %C = var %value.var_patt [concrete] // CHECK:STDOUT: %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C] -// CHECK:STDOUT: %val: ref %C = ref_binding val, %val.var [concrete = %val.var] +// CHECK:STDOUT: %value: ref %C = ref_binding value, %value.var [concrete = %value.var] // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %ptr.patt: %pattern_type.506 = ref_binding_pattern ptr [concrete] // CHECK:STDOUT: %ptr.var_patt: %pattern_type.506 = var_pattern %ptr.patt [concrete] @@ -412,12 +412,12 @@ var ptr: E* = &val; // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc7_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] -// CHECK:STDOUT: %.loc7_15.2: init %C to file.%val.var = class_init () [concrete = constants.%C.val] -// CHECK:STDOUT: %.loc7_1: init %C = converted %.loc7_15.1, %.loc7_15.2 [concrete = constants.%C.val] -// CHECK:STDOUT: assign file.%val.var, %.loc7_1 -// CHECK:STDOUT: %val.ref: ref %C = name_ref val, file.%val [concrete = file.%val.var] -// CHECK:STDOUT: %addr: %ptr.31e = addr_of %val.ref [concrete = constants.%addr] +// CHECK:STDOUT: %.loc7_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc7_17.2: init %C to file.%value.var = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc7_1: init %C = converted %.loc7_17.1, %.loc7_17.2 [concrete = constants.%C.val] +// CHECK:STDOUT: assign file.%value.var, %.loc7_1 +// CHECK:STDOUT: %value.ref: ref %C = name_ref value, file.%value [concrete = file.%value.var] +// CHECK:STDOUT: %addr: %ptr.31e = addr_of %value.ref [concrete = constants.%addr] // CHECK:STDOUT: %impl.elem0: %.cda = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9] // CHECK:STDOUT: %bound_method.loc8_15.1: = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound] // CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn] @@ -438,7 +438,7 @@ var ptr: E* = &val; // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %ptr.31e: type = ptr_type %C [concrete] // CHECK:STDOUT: %pattern_type.506: type = pattern_type %ptr.31e [concrete] -// CHECK:STDOUT: %addr: %ptr.31e = addr_of file.%val.var [concrete] +// CHECK:STDOUT: %addr: %ptr.31e = addr_of file.%value.var [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %T.67d: type = symbolic_binding T, 0 [symbolic] @@ -478,18 +478,18 @@ var ptr: E* = &val; // CHECK:STDOUT: .b_ptr = imports.%Main.b_ptr // CHECK:STDOUT: .C = imports.%Main.C // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .val = %val +// CHECK:STDOUT: .value = %value // CHECK:STDOUT: .ptr = %ptr.loc8_5 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %val.patt: %pattern_type.7c7 = ref_binding_pattern val [concrete] -// CHECK:STDOUT: %val.var_patt: %pattern_type.7c7 = var_pattern %val.patt [concrete] +// CHECK:STDOUT: %value.patt: %pattern_type.7c7 = ref_binding_pattern value [concrete] +// CHECK:STDOUT: %value.var_patt: %pattern_type.7c7 = var_pattern %value.patt [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %val.var: ref %C = var %val.var_patt [concrete] +// CHECK:STDOUT: %value.var: ref %C = var %value.var_patt [concrete] // CHECK:STDOUT: %C.ref: type = name_ref C, imports.%Main.C [concrete = constants.%C] -// CHECK:STDOUT: %val: ref %C = ref_binding val, %val.var [concrete = %val.var] +// CHECK:STDOUT: %value: ref %C = ref_binding value, %value.var [concrete = %value.var] // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %ptr.patt: %pattern_type.506 = ref_binding_pattern ptr [concrete] // CHECK:STDOUT: %ptr.var_patt: %pattern_type.506 = var_pattern %ptr.patt [concrete] @@ -511,12 +511,12 @@ var ptr: E* = &val; // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc7_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] -// CHECK:STDOUT: %.loc7_15.2: init %C to file.%val.var = class_init () [concrete = constants.%C.val] -// CHECK:STDOUT: %.loc7_1: init %C = converted %.loc7_15.1, %.loc7_15.2 [concrete = constants.%C.val] -// CHECK:STDOUT: assign file.%val.var, %.loc7_1 -// CHECK:STDOUT: %val.ref: ref %C = name_ref val, file.%val [concrete = file.%val.var] -// CHECK:STDOUT: %addr: %ptr.31e = addr_of %val.ref [concrete = constants.%addr] +// CHECK:STDOUT: %.loc7_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc7_17.2: init %C to file.%value.var = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc7_1: init %C = converted %.loc7_17.1, %.loc7_17.2 [concrete = constants.%C.val] +// CHECK:STDOUT: assign file.%value.var, %.loc7_1 +// CHECK:STDOUT: %value.ref: ref %C = name_ref value, file.%value [concrete = file.%value.var] +// CHECK:STDOUT: %addr: %ptr.31e = addr_of %value.ref [concrete = constants.%addr] // CHECK:STDOUT: %impl.elem0: %.cda = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9] // CHECK:STDOUT: %bound_method.loc8_15.1: = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound] // CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn] @@ -537,7 +537,7 @@ var ptr: E* = &val; // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %ptr.31e: type = ptr_type %C [concrete] // CHECK:STDOUT: %pattern_type.506: type = pattern_type %ptr.31e [concrete] -// CHECK:STDOUT: %addr: %ptr.31e = addr_of file.%val.var [concrete] +// CHECK:STDOUT: %addr: %ptr.31e = addr_of file.%value.var [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %T.67d: type = symbolic_binding T, 0 [symbolic] @@ -581,18 +581,18 @@ var ptr: E* = &val; // CHECK:STDOUT: .c_val = imports.%Main.c_val // CHECK:STDOUT: .c_ptr = imports.%Main.c_ptr // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .val = %val +// CHECK:STDOUT: .value = %value // CHECK:STDOUT: .ptr = %ptr.loc8_5 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %val.patt: %pattern_type.7c7 = ref_binding_pattern val [concrete] -// CHECK:STDOUT: %val.var_patt: %pattern_type.7c7 = var_pattern %val.patt [concrete] +// CHECK:STDOUT: %value.patt: %pattern_type.7c7 = ref_binding_pattern value [concrete] +// CHECK:STDOUT: %value.var_patt: %pattern_type.7c7 = var_pattern %value.patt [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %val.var: ref %C = var %val.var_patt [concrete] +// CHECK:STDOUT: %value.var: ref %C = var %value.var_patt [concrete] // CHECK:STDOUT: %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C] -// CHECK:STDOUT: %val: ref %C = ref_binding val, %val.var [concrete = %val.var] +// CHECK:STDOUT: %value: ref %C = ref_binding value, %value.var [concrete = %value.var] // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %ptr.patt: %pattern_type.506 = ref_binding_pattern ptr [concrete] // CHECK:STDOUT: %ptr.var_patt: %pattern_type.506 = var_pattern %ptr.patt [concrete] @@ -614,12 +614,12 @@ var ptr: E* = &val; // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc7_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] -// CHECK:STDOUT: %.loc7_15.2: init %C to file.%val.var = class_init () [concrete = constants.%C.val] -// CHECK:STDOUT: %.loc7_1: init %C = converted %.loc7_15.1, %.loc7_15.2 [concrete = constants.%C.val] -// CHECK:STDOUT: assign file.%val.var, %.loc7_1 -// CHECK:STDOUT: %val.ref: ref %C = name_ref val, file.%val [concrete = file.%val.var] -// CHECK:STDOUT: %addr: %ptr.31e = addr_of %val.ref [concrete = constants.%addr] +// CHECK:STDOUT: %.loc7_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc7_17.2: init %C to file.%value.var = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc7_1: init %C = converted %.loc7_17.1, %.loc7_17.2 [concrete = constants.%C.val] +// CHECK:STDOUT: assign file.%value.var, %.loc7_1 +// CHECK:STDOUT: %value.ref: ref %C = name_ref value, file.%value [concrete = file.%value.var] +// CHECK:STDOUT: %addr: %ptr.31e = addr_of %value.ref [concrete = constants.%addr] // CHECK:STDOUT: %impl.elem0: %.cda = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9] // CHECK:STDOUT: %bound_method.loc8_15.1: = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound] // CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn] @@ -640,7 +640,7 @@ var ptr: E* = &val; // CHECK:STDOUT: %C.val: %C = struct_value () [concrete] // CHECK:STDOUT: %ptr.31e: type = ptr_type %C [concrete] // CHECK:STDOUT: %pattern_type.506: type = pattern_type %ptr.31e [concrete] -// CHECK:STDOUT: %addr: %ptr.31e = addr_of file.%val.var [concrete] +// CHECK:STDOUT: %addr: %ptr.31e = addr_of file.%value.var [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %T.67d: type = symbolic_binding T, 0 [symbolic] @@ -684,18 +684,18 @@ var ptr: E* = &val; // CHECK:STDOUT: .b_val = imports.%Main.b_val // CHECK:STDOUT: .b_ptr = imports.%Main.b_ptr // CHECK:STDOUT: .Core = imports.%Core -// CHECK:STDOUT: .val = %val +// CHECK:STDOUT: .value = %value // CHECK:STDOUT: .ptr = %ptr.loc8_5 // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %default.import = import // CHECK:STDOUT: name_binding_decl { -// CHECK:STDOUT: %val.patt: %pattern_type.7c7 = ref_binding_pattern val [concrete] -// CHECK:STDOUT: %val.var_patt: %pattern_type.7c7 = var_pattern %val.patt [concrete] +// CHECK:STDOUT: %value.patt: %pattern_type.7c7 = ref_binding_pattern value [concrete] +// CHECK:STDOUT: %value.var_patt: %pattern_type.7c7 = var_pattern %value.patt [concrete] // CHECK:STDOUT: } -// CHECK:STDOUT: %val.var: ref %C = var %val.var_patt [concrete] +// CHECK:STDOUT: %value.var: ref %C = var %value.var_patt [concrete] // CHECK:STDOUT: %D.ref: type = name_ref D, imports.%Main.D [concrete = constants.%C] -// CHECK:STDOUT: %val: ref %C = ref_binding val, %val.var [concrete = %val.var] +// CHECK:STDOUT: %value: ref %C = ref_binding value, %value.var [concrete = %value.var] // CHECK:STDOUT: name_binding_decl { // CHECK:STDOUT: %ptr.patt: %pattern_type.506 = ref_binding_pattern ptr [concrete] // CHECK:STDOUT: %ptr.var_patt: %pattern_type.506 = var_pattern %ptr.patt [concrete] @@ -717,12 +717,12 @@ var ptr: E* = &val; // CHECK:STDOUT: // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %.loc7_15.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] -// CHECK:STDOUT: %.loc7_15.2: init %C to file.%val.var = class_init () [concrete = constants.%C.val] -// CHECK:STDOUT: %.loc7_1: init %C = converted %.loc7_15.1, %.loc7_15.2 [concrete = constants.%C.val] -// CHECK:STDOUT: assign file.%val.var, %.loc7_1 -// CHECK:STDOUT: %val.ref: ref %C = name_ref val, file.%val [concrete = file.%val.var] -// CHECK:STDOUT: %addr: %ptr.31e = addr_of %val.ref [concrete = constants.%addr] +// CHECK:STDOUT: %.loc7_17.1: %empty_struct_type = struct_literal () [concrete = constants.%empty_struct] +// CHECK:STDOUT: %.loc7_17.2: init %C to file.%value.var = class_init () [concrete = constants.%C.val] +// CHECK:STDOUT: %.loc7_1: init %C = converted %.loc7_17.1, %.loc7_17.2 [concrete = constants.%C.val] +// CHECK:STDOUT: assign file.%value.var, %.loc7_1 +// CHECK:STDOUT: %value.ref: ref %C = name_ref value, file.%value [concrete = file.%value.var] +// CHECK:STDOUT: %addr: %ptr.31e = addr_of %value.ref [concrete = constants.%addr] // CHECK:STDOUT: %impl.elem0: %.cda = impl_witness_access constants.%Copy.impl_witness.2c7, element0 [concrete = constants.%ptr.as.Copy.impl.Op.ed9] // CHECK:STDOUT: %bound_method.loc8_15.1: = bound_method %addr, %impl.elem0 [concrete = constants.%ptr.as.Copy.impl.Op.bound] // CHECK:STDOUT: %specific_fn: = specific_function %impl.elem0, @ptr.as.Copy.impl.Op(constants.%C) [concrete = constants.%ptr.as.Copy.impl.Op.specific_fn] diff --git a/toolchain/check/testdata/impl/error_recovery.carbon b/toolchain/check/testdata/impl/error_recovery.carbon index d74fde90c59f..6cad18e53ea7 100644 --- a/toolchain/check/testdata/impl/error_recovery.carbon +++ b/toolchain/check/testdata/impl/error_recovery.carbon @@ -118,7 +118,7 @@ class C {}; //@dump-sem-ir-begin impl C as I { // This leaves the impl with a placeholder instruction in the witness table. - // CHECK:STDERR: fail_invalid_fn_syntax_in_impl.carbon:[[@LINE+8]]:11: error: expected `:` or `:!` in binding pattern [ExpectedBindingPattern] + // CHECK:STDERR: fail_invalid_fn_syntax_in_impl.carbon:[[@LINE+8]]:11: error: expected `:`, `:!`, or `:?` in binding pattern [ExpectedBindingPattern] // CHECK:STDERR: fn Op[x self: C]() {} // CHECK:STDERR: ^~~~ // CHECK:STDERR: diff --git a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_direct.carbon b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_direct.carbon index ac8ff05a000c..a047ca1c9b92 100644 --- a/toolchain/check/testdata/interop/cpp/function/arithmetic_types_direct.carbon +++ b/toolchain/check/testdata/interop/cpp/function/arithmetic_types_direct.carbon @@ -288,7 +288,7 @@ library "[[@TEST_NAME]]"; import Cpp library "int_return.h"; -fn Carbon_foo(val: i32); +fn Carbon_foo(value: i32); fn F() { //@dump-sem-ir-begin diff --git a/toolchain/check/testdata/primitives/import_symbolic.carbon b/toolchain/check/testdata/primitives/import_symbolic.carbon index 3303ea81f8cf..ca6de4b7ccce 100644 --- a/toolchain/check/testdata/primitives/import_symbolic.carbon +++ b/toolchain/check/testdata/primitives/import_symbolic.carbon @@ -15,11 +15,11 @@ library "[[@TEST_NAME]]"; interface I { - let val:! bool; + let value:! bool; } class C { - impl as I where .val = false {} + impl as I where .value = false {} } // --- import_bool.carbon @@ -29,7 +29,7 @@ import library "bool"; fn F() -> bool { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -38,12 +38,12 @@ fn F() -> bool { library "[[@TEST_NAME]]"; interface I { - let val:! Core.Char; + let value:! Core.Char; } class C {} -impl C as I where .val = 'a' {} +impl C as I where .value = 'a' {} // --- import_char.carbon @@ -52,7 +52,7 @@ import library "char"; fn F() -> Core.Char { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -61,12 +61,12 @@ fn F() -> Core.Char { library "[[@TEST_NAME]]"; interface I { - let val:! Core.CharLiteral(); + let value:! Core.CharLiteral(); } class C {} -impl C as I where .val = 'a' {} +impl C as I where .value = 'a' {} // --- import_char_literal.carbon @@ -75,7 +75,7 @@ import library "char_literal"; fn F() -> Core.CharLiteral() { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -84,12 +84,12 @@ fn F() -> Core.CharLiteral() { library "[[@TEST_NAME]]"; interface I { - let val:! f64; + let value:! f64; } class C {} -impl C as I where .val = 0.1 {} +impl C as I where .value = 0.1 {} // --- import_float.carbon @@ -98,7 +98,7 @@ import library "float"; fn F() -> f64 { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -107,12 +107,12 @@ fn F() -> f64 { library "[[@TEST_NAME]]"; interface I { - let val:! Core.FloatLiteral(); + let value:! Core.FloatLiteral(); } class C {} -impl C as I where .val = 0.1 {} +impl C as I where .value = 0.1 {} // --- import_float_literal.carbon @@ -121,7 +121,7 @@ import library "float_literal"; fn F() -> Core.FloatLiteral() { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -130,12 +130,12 @@ fn F() -> Core.FloatLiteral() { library "[[@TEST_NAME]]"; interface I { - let val:! i32; + let value:! i32; } class C {} -impl C as I where .val = 8 {} +impl C as I where .value = 8 {} // --- import_int.carbon @@ -144,7 +144,7 @@ import library "int"; fn F() -> i32 { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -153,12 +153,12 @@ fn F() -> i32 { library "[[@TEST_NAME]]"; interface I { - let val:! Core.IntLiteral(); + let value:! Core.IntLiteral(); } class C {} -impl C as I where .val = 7 {} +impl C as I where .value = 7 {} // --- import_int_literal.carbon @@ -167,7 +167,7 @@ import library "int_literal"; fn F() -> Core.IntLiteral() { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -176,12 +176,12 @@ fn F() -> Core.IntLiteral() { library "[[@TEST_NAME]]"; interface I { - let val:! u32; + let value:! u32; } class C {} -impl C as I where .val = 8 {} +impl C as I where .value = 8 {} // --- unsigned_uint.carbon @@ -190,7 +190,7 @@ import library "uint"; fn F() -> u32 { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -203,7 +203,7 @@ fn F() -> u32 { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.aa0: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.dd8 [concrete] +// CHECK:STDOUT: %assoc0.af3: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.4da [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Copy.impl_witness.348: = impl_witness imports.%Copy.impl_witness_table.3cc [concrete] @@ -217,11 +217,11 @@ fn F() -> u32 { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//bool, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//bool, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.be4: %I.assoc_type = import_ref Main//bool, loc5_10, loaded [concrete = constants.%assoc0.aa0] -// CHECK:STDOUT: %Main.import_ref.d18: bool = import_ref Main//bool, loc9_32, loaded [concrete = constants.%false] +// CHECK:STDOUT: %Main.import_ref.1c8: %I.assoc_type = import_ref Main//bool, loc5_12, loaded [concrete = constants.%assoc0.af3] +// CHECK:STDOUT: %Main.import_ref.d18: bool = import_ref Main//bool, loc9_34, loaded [concrete = constants.%false] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.d18), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.dd8: bool = import_ref Main//bool, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: bool = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.4da: bool = import_ref Main//bool, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: bool = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.595: %bool.as.Copy.impl.Op.type = import_ref Core//prelude/copy, loc{{\d+_\d+}}, loaded [concrete = constants.%bool.as.Copy.impl.Op] // CHECK:STDOUT: %Copy.impl_witness_table.3cc = impl_witness_table (%Core.import_ref.595), @bool.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -234,7 +234,7 @@ fn F() -> u32 { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.be4 [concrete = constants.%assoc0.aa0] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.1c8 [concrete = constants.%assoc0.af3] // CHECK:STDOUT: %impl.elem0.loc7_18.1: bool = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%false] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.56b = impl_witness_access constants.%Copy.impl_witness.348, element0 [concrete = constants.%bool.as.Copy.impl.Op] // CHECK:STDOUT: %bound_method: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%bool.as.Copy.impl.Op.bound] @@ -252,7 +252,7 @@ fn F() -> u32 { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.2ac: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.55e [concrete] +// CHECK:STDOUT: %assoc0.840: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.90f [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Copy.impl_witness.bd9: = impl_witness imports.%Copy.impl_witness_table.5ef [concrete] @@ -266,11 +266,11 @@ fn F() -> u32 { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//char, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//char, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.7e5: %I.assoc_type = import_ref Main//char, loc5_10, loaded [concrete = constants.%assoc0.2ac] -// CHECK:STDOUT: %Main.import_ref.d0c: %char = import_ref Main//char, loc10_30, loaded [concrete = constants.%int_97] +// CHECK:STDOUT: %Main.import_ref.d69: %I.assoc_type = import_ref Main//char, loc5_12, loaded [concrete = constants.%assoc0.840] +// CHECK:STDOUT: %Main.import_ref.d0c: %char = import_ref Main//char, loc10_32, loaded [concrete = constants.%int_97] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.d0c), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.55e: %char = import_ref Main//char, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: %char = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.90f: %char = import_ref Main//char, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: %char = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.35d: %char.as.Copy.impl.Op.type = import_ref Core//prelude/types/char, loc{{\d+_\d+}}, loaded [concrete = constants.%char.as.Copy.impl.Op] // CHECK:STDOUT: %Copy.impl_witness_table.5ef = impl_witness_table (%Core.import_ref.35d), @char.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -283,7 +283,7 @@ fn F() -> u32 { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.7e5 [concrete = constants.%assoc0.2ac] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.d69 [concrete = constants.%assoc0.840] // CHECK:STDOUT: %impl.elem0.loc7_18.1: %char = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%int_97] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.11f = impl_witness_access constants.%Copy.impl_witness.bd9, element0 [concrete = constants.%char.as.Copy.impl.Op] // CHECK:STDOUT: %bound_method: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%char.as.Copy.impl.Op.bound] @@ -300,7 +300,7 @@ fn F() -> u32 { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.35b: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.2ad [concrete] +// CHECK:STDOUT: %assoc0.c6f: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.8d8 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Copy.impl_witness.100: = impl_witness imports.%Copy.impl_witness_table.853 [concrete] @@ -314,11 +314,11 @@ fn F() -> u32 { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//char_literal, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//char_literal, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.297: %I.assoc_type = import_ref Main//char_literal, loc5_10, loaded [concrete = constants.%assoc0.35b] -// CHECK:STDOUT: %Main.import_ref.43e: Core.CharLiteral = import_ref Main//char_literal, loc10_30, loaded [concrete = constants.%.54f] +// CHECK:STDOUT: %Main.import_ref.6f9: %I.assoc_type = import_ref Main//char_literal, loc5_12, loaded [concrete = constants.%assoc0.c6f] +// CHECK:STDOUT: %Main.import_ref.43e: Core.CharLiteral = import_ref Main//char_literal, loc10_32, loaded [concrete = constants.%.54f] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.43e), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.2ad: Core.CharLiteral = import_ref Main//char_literal, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: Core.CharLiteral = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.8d8: Core.CharLiteral = import_ref Main//char_literal, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: Core.CharLiteral = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.d09: %Core.CharLiteral.as.Copy.impl.Op.type = import_ref Core//prelude/copy, loc{{\d+_\d+}}, loaded [concrete = constants.%Core.CharLiteral.as.Copy.impl.Op] // CHECK:STDOUT: %Copy.impl_witness_table.853 = impl_witness_table (%Core.import_ref.d09), @Core.CharLiteral.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -331,7 +331,7 @@ fn F() -> u32 { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.297 [concrete = constants.%assoc0.35b] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.6f9 [concrete = constants.%assoc0.c6f] // CHECK:STDOUT: %impl.elem0.loc7_18.1: Core.CharLiteral = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%.54f] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.0d7 = impl_witness_access constants.%Copy.impl_witness.100, element0 [concrete = constants.%Core.CharLiteral.as.Copy.impl.Op] // CHECK:STDOUT: %bound_method: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%Core.CharLiteral.as.Copy.impl.Op.bound] @@ -351,7 +351,7 @@ fn F() -> u32 { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.2c4: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.26f [concrete] +// CHECK:STDOUT: %assoc0.f67: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.893 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Float.as.Copy.impl.Op.type.2fe: type = fn_type @Float.as.Copy.impl.Op, @Float.as.Copy.impl(%N) [symbolic] @@ -369,11 +369,11 @@ fn F() -> u32 { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//float, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//float, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.0eb: %I.assoc_type = import_ref Main//float, loc5_10, loaded [concrete = constants.%assoc0.2c4] -// CHECK:STDOUT: %Main.import_ref.0d9: %f64.d77 = import_ref Main//float, loc10_30, loaded [concrete = constants.%float] +// CHECK:STDOUT: %Main.import_ref.e98: %I.assoc_type = import_ref Main//float, loc5_12, loaded [concrete = constants.%assoc0.f67] +// CHECK:STDOUT: %Main.import_ref.0d9: %f64.d77 = import_ref Main//float, loc10_32, loaded [concrete = constants.%float] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.0d9), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.26f: %f64.d77 = import_ref Main//float, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: %f64.d77 = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.893: %f64.d77 = import_ref Main//float, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: %f64.d77 = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.47c: @Float.as.Copy.impl.%Float.as.Copy.impl.Op.type (%Float.as.Copy.impl.Op.type.2fe) = import_ref Core//prelude/types/float, loc{{\d+_\d+}}, loaded [symbolic = @Float.as.Copy.impl.%Float.as.Copy.impl.Op (constants.%Float.as.Copy.impl.Op.240)] // CHECK:STDOUT: %Copy.impl_witness_table.119 = impl_witness_table (%Core.import_ref.47c), @Float.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -386,7 +386,7 @@ fn F() -> u32 { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.0eb [concrete = constants.%assoc0.2c4] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.e98 [concrete = constants.%assoc0.f67] // CHECK:STDOUT: %impl.elem0.loc7_18.1: %f64.d77 = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%float] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.c41 = impl_witness_access constants.%Copy.impl_witness.1e3, element0 [concrete = constants.%Float.as.Copy.impl.Op.f05] // CHECK:STDOUT: %bound_method.loc7_18.1: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%Float.as.Copy.impl.Op.bound] @@ -404,7 +404,7 @@ fn F() -> u32 { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.7ab: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.a44 [concrete] +// CHECK:STDOUT: %assoc0.8a0: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.2e3 [concrete] // CHECK:STDOUT: %float.3fedf4.2: Core.FloatLiteral = float_literal_value 1e-1 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] @@ -419,11 +419,11 @@ fn F() -> u32 { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//float_literal, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//float_literal, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.cf4: %I.assoc_type = import_ref Main//float_literal, loc5_10, loaded [concrete = constants.%assoc0.7ab] -// CHECK:STDOUT: %Main.import_ref.dec: Core.FloatLiteral = import_ref Main//float_literal, loc10_30, loaded [concrete = constants.%float.3fedf4.2] +// CHECK:STDOUT: %Main.import_ref.10a: %I.assoc_type = import_ref Main//float_literal, loc5_12, loaded [concrete = constants.%assoc0.8a0] +// CHECK:STDOUT: %Main.import_ref.dec: Core.FloatLiteral = import_ref Main//float_literal, loc10_32, loaded [concrete = constants.%float.3fedf4.2] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.dec), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.a44: Core.FloatLiteral = import_ref Main//float_literal, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: Core.FloatLiteral = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.2e3: Core.FloatLiteral = import_ref Main//float_literal, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: Core.FloatLiteral = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.3f0: %Core.FloatLiteral.as.Copy.impl.Op.type = import_ref Core//prelude/copy, loc{{\d+_\d+}}, loaded [concrete = constants.%Core.FloatLiteral.as.Copy.impl.Op] // CHECK:STDOUT: %Copy.impl_witness_table.65a = impl_witness_table (%Core.import_ref.3f0), @Core.FloatLiteral.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -436,7 +436,7 @@ fn F() -> u32 { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.cf4 [concrete = constants.%assoc0.7ab] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.10a [concrete = constants.%assoc0.8a0] // CHECK:STDOUT: %impl.elem0.loc7_18.1: Core.FloatLiteral = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%float.3fedf4.2] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.f37 = impl_witness_access constants.%Copy.impl_witness.ba9, element0 [concrete = constants.%Core.FloatLiteral.as.Copy.impl.Op] // CHECK:STDOUT: %bound_method: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%Core.FloatLiteral.as.Copy.impl.Op.bound] @@ -456,7 +456,7 @@ fn F() -> u32 { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.096: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.52f [concrete] +// CHECK:STDOUT: %assoc0.2ce: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.e84 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic] @@ -474,11 +474,11 @@ fn F() -> u32 { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//int, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//int, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.641: %I.assoc_type = import_ref Main//int, loc5_10, loaded [concrete = constants.%assoc0.096] -// CHECK:STDOUT: %Main.import_ref.330: %i32 = import_ref Main//int, loc10_28, loaded [concrete = constants.%int_8] +// CHECK:STDOUT: %Main.import_ref.76f: %I.assoc_type = import_ref Main//int, loc5_12, loaded [concrete = constants.%assoc0.2ce] +// CHECK:STDOUT: %Main.import_ref.330: %i32 = import_ref Main//int, loc10_30, loaded [concrete = constants.%int_8] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.330), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.52f: %i32 = import_ref Main//int, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: %i32 = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.e84: %i32 = import_ref Main//int, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: %i32 = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/types/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)] // CHECK:STDOUT: %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -491,7 +491,7 @@ fn F() -> u32 { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.641 [concrete = constants.%assoc0.096] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.76f [concrete = constants.%assoc0.2ce] // CHECK:STDOUT: %impl.elem0.loc7_18.1: %i32 = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%int_8] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.f79 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664] // CHECK:STDOUT: %bound_method.loc7_18.1: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%Int.as.Copy.impl.Op.bound] @@ -510,7 +510,7 @@ fn F() -> u32 { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.b62: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.763 [concrete] +// CHECK:STDOUT: %assoc0.415: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.334 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Copy.impl_witness.98e: = impl_witness imports.%Copy.impl_witness_table.d8f [concrete] @@ -524,11 +524,11 @@ fn F() -> u32 { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//int_literal, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//int_literal, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.f39: %I.assoc_type = import_ref Main//int_literal, loc5_10, loaded [concrete = constants.%assoc0.b62] -// CHECK:STDOUT: %Main.import_ref.bc3: Core.IntLiteral = import_ref Main//int_literal, loc10_28, loaded [concrete = constants.%int_7] +// CHECK:STDOUT: %Main.import_ref.398: %I.assoc_type = import_ref Main//int_literal, loc5_12, loaded [concrete = constants.%assoc0.415] +// CHECK:STDOUT: %Main.import_ref.bc3: Core.IntLiteral = import_ref Main//int_literal, loc10_30, loaded [concrete = constants.%int_7] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.bc3), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.763: Core.IntLiteral = import_ref Main//int_literal, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: Core.IntLiteral = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.334: Core.IntLiteral = import_ref Main//int_literal, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: Core.IntLiteral = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.66a: %Core.IntLiteral.as.Copy.impl.Op.type = import_ref Core//prelude/copy, loc{{\d+_\d+}}, loaded [concrete = constants.%Core.IntLiteral.as.Copy.impl.Op] // CHECK:STDOUT: %Copy.impl_witness_table.d8f = impl_witness_table (%Core.import_ref.66a), @Core.IntLiteral.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -541,7 +541,7 @@ fn F() -> u32 { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.f39 [concrete = constants.%assoc0.b62] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.398 [concrete = constants.%assoc0.415] // CHECK:STDOUT: %impl.elem0.loc7_18.1: Core.IntLiteral = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%int_7] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.6b5 = impl_witness_access constants.%Copy.impl_witness.98e, element0 [concrete = constants.%Core.IntLiteral.as.Copy.impl.Op] // CHECK:STDOUT: %bound_method: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%Core.IntLiteral.as.Copy.impl.Op.bound] @@ -561,7 +561,7 @@ fn F() -> u32 { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.ea3: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.f37 [concrete] +// CHECK:STDOUT: %assoc0.aa0: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.ee9 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %UInt.as.Copy.impl.Op.type.68f: type = fn_type @UInt.as.Copy.impl.Op, @UInt.as.Copy.impl(%N) [symbolic] @@ -579,11 +579,11 @@ fn F() -> u32 { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//uint, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//uint, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.fa7: %I.assoc_type = import_ref Main//uint, loc5_10, loaded [concrete = constants.%assoc0.ea3] -// CHECK:STDOUT: %Main.import_ref.647: %u32 = import_ref Main//uint, loc10_28, loaded [concrete = constants.%int_8] +// CHECK:STDOUT: %Main.import_ref.4d2: %I.assoc_type = import_ref Main//uint, loc5_12, loaded [concrete = constants.%assoc0.aa0] +// CHECK:STDOUT: %Main.import_ref.647: %u32 = import_ref Main//uint, loc10_30, loaded [concrete = constants.%int_8] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.647), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.f37: %u32 = import_ref Main//uint, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: %u32 = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.ee9: %u32 = import_ref Main//uint, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: %u32 = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.c3c: @UInt.as.Copy.impl.%UInt.as.Copy.impl.Op.type (%UInt.as.Copy.impl.Op.type.68f) = import_ref Core//prelude/types/uint, loc{{\d+_\d+}}, loaded [symbolic = @UInt.as.Copy.impl.%UInt.as.Copy.impl.Op (constants.%UInt.as.Copy.impl.Op.576)] // CHECK:STDOUT: %Copy.impl_witness_table.bd0 = impl_witness_table (%Core.import_ref.c3c), @UInt.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -596,7 +596,7 @@ fn F() -> u32 { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.fa7 [concrete = constants.%assoc0.ea3] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.4d2 [concrete = constants.%assoc0.aa0] // CHECK:STDOUT: %impl.elem0.loc7_18.1: %u32 = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%int_8] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.fcc = impl_witness_access constants.%Copy.impl_witness.514, element0 [concrete = constants.%UInt.as.Copy.impl.Op.c10] // CHECK:STDOUT: %bound_method.loc7_18.1: = bound_method %impl.elem0.loc7_18.1, %impl.elem0.loc7_18.2 [concrete = constants.%UInt.as.Copy.impl.Op.bound] diff --git a/toolchain/check/testdata/struct/import.carbon b/toolchain/check/testdata/struct/import.carbon index da0952c98f5e..073cbe56ff22 100644 --- a/toolchain/check/testdata/struct/import.carbon +++ b/toolchain/check/testdata/struct/import.carbon @@ -61,12 +61,12 @@ var c_bad: C({.a = 3, .b = 4}) = F(); library "[[@TEST_NAME]]"; interface I { - let val:! {.x: i32}; + let value:! {.x: i32}; } class C {} -impl C as I where .val = {.x = 1} {} +impl C as I where .value = {.x = 1} {} // --- import_symbolic_decl.carbon @@ -75,7 +75,7 @@ import library "symbolic_decl"; fn F() -> {.x: i32} { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -294,7 +294,7 @@ fn F() -> {.x: i32} { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.696: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.b51 [concrete] +// CHECK:STDOUT: %assoc0.7f5: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.8d8 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic] @@ -312,11 +312,11 @@ fn F() -> {.x: i32} { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//symbolic_decl, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//symbolic_decl, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.0f2: %I.assoc_type = import_ref Main//symbolic_decl, loc5_10, loaded [concrete = constants.%assoc0.696] -// CHECK:STDOUT: %Main.import_ref.1ec: %struct_type.x = import_ref Main//symbolic_decl, loc10_35, loaded [concrete = constants.%struct] +// CHECK:STDOUT: %Main.import_ref.dfb: %I.assoc_type = import_ref Main//symbolic_decl, loc5_12, loaded [concrete = constants.%assoc0.7f5] +// CHECK:STDOUT: %Main.import_ref.1ec: %struct_type.x = import_ref Main//symbolic_decl, loc10_37, loaded [concrete = constants.%struct] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.1ec), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.b51: %struct_type.x = import_ref Main//symbolic_decl, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: %struct_type.x = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.8d8: %struct_type.x = import_ref Main//symbolic_decl, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: %struct_type.x = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)] // CHECK:STDOUT: %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -329,7 +329,7 @@ fn F() -> {.x: i32} { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18.1: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.0f2 [concrete = constants.%assoc0.696] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.dfb [concrete = constants.%assoc0.7f5] // CHECK:STDOUT: %impl.elem0.loc7_18.1: %struct_type.x = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%struct] // CHECK:STDOUT: %.loc7_18.2: %i32 = struct_access %impl.elem0.loc7_18.1, element0 [concrete = constants.%int_1] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.f79 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664] @@ -338,7 +338,7 @@ fn F() -> {.x: i32} { // CHECK:STDOUT: %bound_method.loc7_18.2: = bound_method %.loc7_18.2, %specific_fn [concrete = constants.%bound_method] // CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc7_18.2(%.loc7_18.2) [concrete = constants.%int_1] // CHECK:STDOUT: %.loc7_18.3: init %struct_type.x = struct_init (%Int.as.Copy.impl.Op.call) [concrete = constants.%struct] -// CHECK:STDOUT: %.loc7_22: init %struct_type.x = converted %impl.elem0.loc7_18.1, %.loc7_18.3 [concrete = constants.%struct] -// CHECK:STDOUT: return %.loc7_22 +// CHECK:STDOUT: %.loc7_24: init %struct_type.x = converted %impl.elem0.loc7_18.1, %.loc7_18.3 [concrete = constants.%struct] +// CHECK:STDOUT: return %.loc7_24 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/tuple/import.carbon b/toolchain/check/testdata/tuple/import.carbon index 3a99cf750924..40008c6c300d 100644 --- a/toolchain/check/testdata/tuple/import.carbon +++ b/toolchain/check/testdata/tuple/import.carbon @@ -63,12 +63,12 @@ var c_bad: C((3, 4)) = F(); library "[[@TEST_NAME]]"; interface I { - let val:! (i32,); + let value:! (i32,); } class C {} -impl C as I where .val = (1,) {} +impl C as I where .value = (1,) {} // --- import_symbolic_decl.carbon @@ -77,7 +77,7 @@ import library "symbolic_decl"; fn F() -> (i32,) { //@dump-sem-ir-begin - return (C as I).val; + return (C as I).value; //@dump-sem-ir-end } @@ -325,7 +325,7 @@ fn F() -> (i32,) { // CHECK:STDOUT: %I.impl_witness: = impl_witness imports.%I.impl_witness_table [concrete] // CHECK:STDOUT: %I.facet: %I.type = facet_value %C, (%I.impl_witness) [concrete] // CHECK:STDOUT: %I.assoc_type: type = assoc_entity_type @I [concrete] -// CHECK:STDOUT: %assoc0.8b4: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.ce8 [concrete] +// CHECK:STDOUT: %assoc0.5ae: %I.assoc_type = assoc_entity element0, imports.%Main.import_ref.ca6 [concrete] // CHECK:STDOUT: %Copy.type: type = facet_type <@Copy> [concrete] // CHECK:STDOUT: %Copy.Op.type: type = fn_type @Copy.Op [concrete] // CHECK:STDOUT: %Int.as.Copy.impl.Op.type.824: type = fn_type @Int.as.Copy.impl.Op, @Int.as.Copy.impl(%N) [symbolic] @@ -343,11 +343,11 @@ fn F() -> (i32,) { // CHECK:STDOUT: imports { // CHECK:STDOUT: %Main.I: type = import_ref Main//symbolic_decl, I, loaded [concrete = constants.%I.type] // CHECK:STDOUT: %Main.C: type = import_ref Main//symbolic_decl, C, loaded [concrete = constants.%C] -// CHECK:STDOUT: %Main.import_ref.bf0: %I.assoc_type = import_ref Main//symbolic_decl, loc5_10, loaded [concrete = constants.%assoc0.8b4] -// CHECK:STDOUT: %Main.import_ref.fd7: %tuple.type.a1c = import_ref Main//symbolic_decl, loc10_31, loaded [concrete = constants.%tuple.246] +// CHECK:STDOUT: %Main.import_ref.a8c: %I.assoc_type = import_ref Main//symbolic_decl, loc5_12, loaded [concrete = constants.%assoc0.5ae] +// CHECK:STDOUT: %Main.import_ref.fd7: %tuple.type.a1c = import_ref Main//symbolic_decl, loc10_33, loaded [concrete = constants.%tuple.246] // CHECK:STDOUT: %I.impl_witness_table = impl_witness_table (%Main.import_ref.fd7), @C.as.I.impl [concrete] -// CHECK:STDOUT: %Main.import_ref.ce8: %tuple.type.a1c = import_ref Main//symbolic_decl, loc5_10, loaded [concrete = %val] -// CHECK:STDOUT: %val: %tuple.type.a1c = assoc_const_decl @val [concrete] {} +// CHECK:STDOUT: %Main.import_ref.ca6: %tuple.type.a1c = import_ref Main//symbolic_decl, loc5_12, loaded [concrete = %value] +// CHECK:STDOUT: %value: %tuple.type.a1c = assoc_const_decl @value [concrete] {} // CHECK:STDOUT: %Core.import_ref.18d: @Int.as.Copy.impl.%Int.as.Copy.impl.Op.type (%Int.as.Copy.impl.Op.type.824) = import_ref Core//prelude/parts/int, loc{{\d+_\d+}}, loaded [symbolic = @Int.as.Copy.impl.%Int.as.Copy.impl.Op (constants.%Int.as.Copy.impl.Op.9b9)] // CHECK:STDOUT: %Copy.impl_witness_table.e76 = impl_witness_table (%Core.import_ref.18d), @Int.as.Copy.impl [concrete] // CHECK:STDOUT: } @@ -360,7 +360,7 @@ fn F() -> (i32,) { // CHECK:STDOUT: %.loc7_13: %I.type = converted %C.ref, %I.facet [concrete = constants.%I.facet] // CHECK:STDOUT: %as_type: type = facet_access_type %.loc7_13 [concrete = constants.%C] // CHECK:STDOUT: %.loc7_18.1: type = converted %.loc7_13, %as_type [concrete = constants.%C] -// CHECK:STDOUT: %val.ref: %I.assoc_type = name_ref val, imports.%Main.import_ref.bf0 [concrete = constants.%assoc0.8b4] +// CHECK:STDOUT: %value.ref: %I.assoc_type = name_ref value, imports.%Main.import_ref.a8c [concrete = constants.%assoc0.5ae] // CHECK:STDOUT: %impl.elem0.loc7_18.1: %tuple.type.a1c = impl_witness_access constants.%I.impl_witness, element0 [concrete = constants.%tuple.246] // CHECK:STDOUT: %tuple.elem0: %i32 = tuple_access %impl.elem0.loc7_18.1, element0 [concrete = constants.%int_1] // CHECK:STDOUT: %impl.elem0.loc7_18.2: %.f79 = impl_witness_access constants.%Copy.impl_witness.f17, element0 [concrete = constants.%Int.as.Copy.impl.Op.664] @@ -369,7 +369,7 @@ fn F() -> (i32,) { // CHECK:STDOUT: %bound_method.loc7_18.2: = bound_method %tuple.elem0, %specific_fn [concrete = constants.%bound_method] // CHECK:STDOUT: %Int.as.Copy.impl.Op.call: init %i32 = call %bound_method.loc7_18.2(%tuple.elem0) [concrete = constants.%int_1] // CHECK:STDOUT: %.loc7_18.2: init %tuple.type.a1c = tuple_init (%Int.as.Copy.impl.Op.call) [concrete = constants.%tuple.246] -// CHECK:STDOUT: %.loc7_22: init %tuple.type.a1c = converted %impl.elem0.loc7_18.1, %.loc7_18.2 [concrete = constants.%tuple.246] -// CHECK:STDOUT: return %.loc7_22 +// CHECK:STDOUT: %.loc7_24: init %tuple.type.a1c = converted %impl.elem0.loc7_18.1, %.loc7_18.2 [concrete = constants.%tuple.246] +// CHECK:STDOUT: return %.loc7_24 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/diagnostics/kind.def b/toolchain/diagnostics/kind.def index 67a2f20b4714..2d22f5032140 100644 --- a/toolchain/diagnostics/kind.def +++ b/toolchain/diagnostics/kind.def @@ -95,6 +95,7 @@ CARBON_DIAGNOSTIC_KIND(CharLiteralUnderflow) CARBON_DIAGNOSTIC_KIND(BinaryOperatorRequiresWhitespace) CARBON_DIAGNOSTIC_KIND(ExpectedArrayComma) +CARBON_DIAGNOSTIC_KIND(ExpectedCategoryModifier) CARBON_DIAGNOSTIC_KIND(ExpectedCloseSymbol) CARBON_DIAGNOSTIC_KIND(ExpectedCodeBlock) CARBON_DIAGNOSTIC_KIND(ExpectedLambdaBody) diff --git a/toolchain/lex/token_kind.def b/toolchain/lex/token_kind.def index 856ab70a75c0..934134557ccf 100644 --- a/toolchain/lex/token_kind.def +++ b/toolchain/lex/token_kind.def @@ -59,12 +59,14 @@ CARBON_TOKEN(Error) CARBON_SYMBOL_TOKEN(GreaterGreaterEqual, ">>=") CARBON_SYMBOL_TOKEN(LessEqualGreater, "<=>") CARBON_SYMBOL_TOKEN(LessLessEqual, "<<=") +CARBON_SYMBOL_TOKEN(MinusGreaterQuestion,"->?") CARBON_SYMBOL_TOKEN(AmpEqual, "&=") CARBON_SYMBOL_TOKEN(CaretEqual, "^=") CARBON_SYMBOL_TOKEN(ColonEqual, ":=") CARBON_TOKEN_WITH_VIRTUAL_NODE( CARBON_SYMBOL_TOKEN(ColonExclaim, ":!")) +CARBON_SYMBOL_TOKEN(ColonQuestion, ":?") CARBON_SYMBOL_TOKEN(EqualEqual, "==") CARBON_SYMBOL_TOKEN(EqualGreater, "=>") CARBON_SYMBOL_TOKEN(ExclaimEqual, "!=") @@ -189,6 +191,7 @@ CARBON_KEYWORD_TOKEN(Extern, "extern") CARBON_KEYWORD_TOKEN(False, "false") CARBON_KEYWORD_TOKEN(Final, "final") CARBON_KEYWORD_TOKEN(For, "for") +CARBON_KEYWORD_TOKEN(Form, "form") CARBON_KEYWORD_TOKEN(Forall, "forall") CARBON_KEYWORD_TOKEN(Friend, "friend") CARBON_KEYWORD_TOKEN(If, "if") @@ -221,6 +224,7 @@ CARBON_KEYWORD_TOKEN(Underscore, "_") CARBON_KEYWORD_TOKEN(Unsafe, "unsafe") CARBON_KEYWORD_TOKEN(Unused, "unused") CARBON_KEYWORD_TOKEN(Virtual, "virtual") +CARBON_KEYWORD_TOKEN(Val, "val") CARBON_TOKEN_WITH_VIRTUAL_NODE( CARBON_KEYWORD_TOKEN(Where, "where")) CARBON_KEYWORD_TOKEN(While, "while") diff --git a/toolchain/parse/context.h b/toolchain/parse/context.h index c2bfa62ba26f..f9ec61b00d56 100644 --- a/toolchain/parse/context.h +++ b/toolchain/parse/context.h @@ -145,6 +145,10 @@ class Context { kind != NodeKind::InvalidParseSubtree), "{0} nodes must always have an error", kind); tree_->node_impls_.push_back(Tree::NodeImpl(kind, has_error, token)); + CARBON_VLOG("Add #node{0}: {1}", + llvm::format_hex_no_prefix(tree_->node_impls_.size() - 1, 0, + /*Upper=*/true), + tree_->node_impls_.back()); } // Adds a node and returns its typed NodeId. diff --git a/toolchain/parse/handle_binding_pattern.cpp b/toolchain/parse/handle_binding_pattern.cpp index daccaff97169..d01812b8f2e2 100644 --- a/toolchain/parse/handle_binding_pattern.cpp +++ b/toolchain/parse/handle_binding_pattern.cpp @@ -14,9 +14,10 @@ auto HandleBindingPattern(Context& context) -> void { // Handle an invalid pattern introducer for parameters and variables. auto on_error = [&](bool expected_name) { if (!state.has_error) { - CARBON_DIAGNOSTIC(ExpectedBindingPattern, Error, - "expected {0:name|`:` or `:!`} in binding pattern", - Diagnostics::BoolAsSelect); + CARBON_DIAGNOSTIC( + ExpectedBindingPattern, Error, + "expected {0:name|`:`, `:!`, or `:?`} in binding pattern", + Diagnostics::BoolAsSelect); context.emitter().Emit(*context.position(), ExpectedBindingPattern, expected_name); state.has_error = true; @@ -51,7 +52,8 @@ auto HandleBindingPattern(Context& context) -> void { if (auto token_kind = context.PositionKind(); token_kind == Lex::TokenKind::Colon || - token_kind == Lex::TokenKind::ColonExclaim) { + token_kind == Lex::TokenKind::ColonExclaim || + token_kind == Lex::TokenKind::ColonQuestion) { // Add the wrapper node for the `template` keyword if present. if (template_token) { if (token_kind != Lex::TokenKind::ColonExclaim && !state.has_error) { @@ -75,10 +77,21 @@ auto HandleBindingPattern(Context& context) -> void { context.AddNode(NodeKind::RefBindingName, *ref_token, state.has_error); } - state.kind = token_kind == Lex::TokenKind::Colon - ? StateKind::BindingPatternFinishAsRegular - : StateKind::BindingPatternFinishAsGeneric; - // Use the `:` or `:!` for the root node. + switch (token_kind) { + case Lex::TokenKind::Colon: + state.kind = StateKind::BindingPatternFinishAsRegular; + break; + case Lex::TokenKind::ColonExclaim: + state.kind = StateKind::BindingPatternFinishAsGeneric; + break; + case Lex::TokenKind::ColonQuestion: + state.kind = StateKind::BindingPatternFinishAsForm; + break; + default: + CARBON_FATAL("Unexpected token kind"); + } + + // Use the `:`, `:!`, or `:?` for the root node. state.token = context.Consume(); if (token_kind == Lex::TokenKind::ColonExclaim) { @@ -99,24 +112,32 @@ auto HandleBindingPattern(Context& context) -> void { } // Handles BindingPatternFinishAs(Generic|Regular). -static auto HandleBindingPatternFinish(Context& context, bool is_compile_time) +static auto HandleBindingPatternFinish(Context& context, StateKind finish_kind) -> void { auto state = context.PopState(); auto node_kind = NodeKind::InvalidParse; if (state.in_var_pattern) { node_kind = NodeKind::VarBindingPattern; - if (is_compile_time) { + if (finish_kind == StateKind::BindingPatternFinishAsGeneric) { CARBON_DIAGNOSTIC(CompileTimeBindingInVarDecl, Error, "`var` pattern cannot declare a compile-time binding"); context.emitter().Emit(*context.position(), CompileTimeBindingInVarDecl); state.has_error = true; } } else { - if (is_compile_time) { - node_kind = NodeKind::CompileTimeBindingPattern; - } else { - node_kind = NodeKind::LetBindingPattern; + switch (finish_kind) { + case StateKind::BindingPatternFinishAsGeneric: + node_kind = NodeKind::CompileTimeBindingPattern; + break; + case StateKind::BindingPatternFinishAsRegular: + node_kind = NodeKind::LetBindingPattern; + break; + case StateKind::BindingPatternFinishAsForm: + node_kind = NodeKind::FormBindingPattern; + break; + default: + CARBON_FATAL("Unexpected StateKind {0}", finish_kind); } } context.AddNode(node_kind, state.token, state.has_error); @@ -129,11 +150,15 @@ static auto HandleBindingPatternFinish(Context& context, bool is_compile_time) } auto HandleBindingPatternFinishAsGeneric(Context& context) -> void { - HandleBindingPatternFinish(context, /*is_compile_time=*/true); + HandleBindingPatternFinish(context, StateKind::BindingPatternFinishAsGeneric); } auto HandleBindingPatternFinishAsRegular(Context& context) -> void { - HandleBindingPatternFinish(context, /*is_compile_time=*/false); + HandleBindingPatternFinish(context, StateKind::BindingPatternFinishAsRegular); +} + +auto HandleBindingPatternFinishAsForm(Context& context) -> void { + HandleBindingPatternFinish(context, StateKind::BindingPatternFinishAsForm); } } // namespace Carbon::Parse diff --git a/toolchain/parse/handle_expr.cpp b/toolchain/parse/handle_expr.cpp index 2113ddfaa891..6d53b9e6bfa8 100644 --- a/toolchain/parse/handle_expr.cpp +++ b/toolchain/parse/handle_expr.cpp @@ -169,6 +169,11 @@ auto HandleExprInPostfix(Context& context) -> void { context.PushState(StateKind::ArrayExpr); break; } + case Lex::TokenKind::Form: { + context.PushState(state); + context.PushState(StateKind::FormLiteral); + break; + } case Lex::TokenKind::Package: { context.AddLeafNode(NodeKind::PackageExpr, context.Consume()); if (context.PositionKind() != Lex::TokenKind::Period) { diff --git a/toolchain/parse/handle_form_literal.cpp b/toolchain/parse/handle_form_literal.cpp new file mode 100644 index 000000000000..e69639720dad --- /dev/null +++ b/toolchain/parse/handle_form_literal.cpp @@ -0,0 +1,78 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "toolchain/lex/token_kind.h" +#include "toolchain/lex/tokenized_buffer.h" +#include "toolchain/parse/context.h" +#include "toolchain/parse/handle.h" +#include "toolchain/parse/node_kind.h" +#include "toolchain/parse/state.h" + +namespace Carbon::Parse { + +auto HandleFormLiteral(Context& context) -> void { + auto state = context.PopState(); + + auto keyword = context.ConsumeChecked(Lex::TokenKind::Form); + context.AddLeafNode(NodeKind::FormLiteralKeyword, keyword); + if (auto paren = context.ConsumeAndAddOpenParen( + keyword, NodeKind::FormLiteralOpenParen)) { + // Stash the open paren token for use by ConsumeAndAddCloseSymbol. + state.token = *paren; + } else { + state.has_error = true; + } + context.PushState(state, StateKind::FormLiteralFinish); + if (state.has_error) { + context.AddInvalidParse(keyword); + } else { + context.PushState(StateKind::PrimitiveForm, keyword); + } +} + +auto HandlePrimitiveForm(Context& context) -> void { + auto state = context.PopState(); + if (context.PositionIs(Lex::TokenKind::Ref) || + context.PositionIs(Lex::TokenKind::Var) || + context.PositionIs(Lex::TokenKind::Val)) { + state.token = context.Consume(); + } else { + CARBON_DIAGNOSTIC(ExpectedCategoryModifier, Error, + "expected `ref`, `var`, or `val` after `form(`"); + context.emitter().Emit(*context.position(), ExpectedCategoryModifier); + state.has_error = true; + } + context.PushState(state, StateKind::PrimitiveFormFinish); + context.PushState(StateKind::Expr); +} + +auto HandlePrimitiveFormFinish(Context& context) -> void { + auto state = context.PopState(); + + // Arbitrary default, only used in error recovery. + auto node_kind = NodeKind::ValPrimitiveForm; + switch (context.tokens().GetKind(state.token)) { + case Lex::TokenKind::Ref: + node_kind = NodeKind::RefPrimitiveForm; + break; + case Lex::TokenKind::Var: + node_kind = NodeKind::VarPrimitiveForm; + break; + case Lex::TokenKind::Val: + node_kind = NodeKind::ValPrimitiveForm; + break; + default: + CARBON_CHECK(state.has_error); + // Use the default node_kind set earlier for error recovery. + break; + } + context.AddNode(node_kind, state.token, state.has_error); +} + +auto HandleFormLiteralFinish(Context& context) -> void { + auto state = context.PopState(); + context.ConsumeAndAddCloseSymbol(state.token, state, NodeKind::FormLiteral); +} + +} // namespace Carbon::Parse diff --git a/toolchain/parse/handle_function.cpp b/toolchain/parse/handle_function.cpp index 2e32a924003c..28e06d9ff866 100644 --- a/toolchain/parse/handle_function.cpp +++ b/toolchain/parse/handle_function.cpp @@ -25,6 +25,10 @@ auto HandleFunctionAfterParams(Context& context) -> void { context.PushState(StateKind::FunctionReturnTypeFinish); context.ConsumeAndDiscard(); context.PushStateForExpr(PrecedenceGroup::ForType()); + } else if (context.PositionIs(Lex::TokenKind::MinusGreaterQuestion)) { + context.PushState(StateKind::FunctionReturnFormFinish); + context.ConsumeAndDiscard(); + context.PushStateForExpr(PrecedenceGroup::ForType()); } } @@ -34,6 +38,12 @@ auto HandleFunctionReturnTypeFinish(Context& context) -> void { context.AddNode(NodeKind::ReturnType, state.token, state.has_error); } +auto HandleFunctionReturnFormFinish(Context& context) -> void { + auto state = context.PopState(); + + context.AddNode(NodeKind::ReturnForm, state.token, state.has_error); +} + auto HandleFunctionSignatureFinish(Context& context) -> void { auto state = context.PopState(); diff --git a/toolchain/parse/node_ids.h b/toolchain/parse/node_ids.h index e7cda777afd8..1347a20ea86f 100644 --- a/toolchain/parse/node_ids.h +++ b/toolchain/parse/node_ids.h @@ -177,6 +177,8 @@ using AnyPointerDeferenceExprId = using AnyRuntimeBindingPatternName = NodeIdOneOf; +using AnyPrimitiveFormIdId = + NodeIdOneOf; // NodeId with kind that is anything but T::Kind. template diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index 6cf4bbbdbaa6..46bf010f48be 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -145,6 +145,7 @@ CARBON_PARSE_NODE_KIND(CodeBlock) CARBON_PARSE_NODE_KIND(FunctionIntroducer) CARBON_PARSE_NODE_KIND(LambdaIntroducer) CARBON_PARSE_NODE_KIND(ReturnType) +CARBON_PARSE_NODE_KIND(ReturnForm) CARBON_PARSE_NODE_KIND(FunctionDefinitionStart) CARBON_PARSE_NODE_KIND(FunctionDefinition) CARBON_PARSE_NODE_KIND(FunctionTerseDefinition) @@ -178,6 +179,7 @@ CARBON_PARSE_NODE_KIND(UnusedPattern) CARBON_PARSE_NODE_KIND(LetBindingPattern) CARBON_PARSE_NODE_KIND(AssociatedConstantNameAndType) CARBON_PARSE_NODE_KIND(VarBindingPattern) +CARBON_PARSE_NODE_KIND(FormBindingPattern) CARBON_PARSE_NODE_KIND(TemplateBindingName) CARBON_PARSE_NODE_KIND(CompileTimeBindingPatternStart) CARBON_PARSE_NODE_KIND(CompileTimeBindingPattern) @@ -230,6 +232,13 @@ CARBON_PARSE_NODE_KIND(WhileStatement) CARBON_PARSE_NODE_KIND(IndexExprStart) CARBON_PARSE_NODE_KIND(IndexExpr) +CARBON_PARSE_NODE_KIND(RefPrimitiveForm) +CARBON_PARSE_NODE_KIND(VarPrimitiveForm) +CARBON_PARSE_NODE_KIND(ValPrimitiveForm) +CARBON_PARSE_NODE_KIND(FormLiteralKeyword) +CARBON_PARSE_NODE_KIND(FormLiteralOpenParen) +CARBON_PARSE_NODE_KIND(FormLiteral) + CARBON_PARSE_NODE_KIND(ParenExprStart) CARBON_PARSE_NODE_KIND(ParenExpr) diff --git a/toolchain/parse/precedence.cpp b/toolchain/parse/precedence.cpp index da877e7dabef..f056217fc0cf 100644 --- a/toolchain/parse/precedence.cpp +++ b/toolchain/parse/precedence.cpp @@ -262,7 +262,6 @@ auto PrecedenceGroup::ForTrailing(Lex::TokenKind kind, bool infix) case Lex::TokenKind::TildeEqual: case Lex::TokenKind::Exclaim: case Lex::TokenKind::LessGreater: - case Lex::TokenKind::Question: case Lex::TokenKind::Colon: break; diff --git a/toolchain/parse/state.def b/toolchain/parse/state.def index 7ec22d9c4f21..96496dccb182 100644 --- a/toolchain/parse/state.def +++ b/toolchain/parse/state.def @@ -96,6 +96,51 @@ CARBON_PARSE_STATE(ArrayExprComma) // (state done) CARBON_PARSE_STATE(ArrayExprFinish) +// Handles the start of a form literal. +// +// form ( ... +// ^~~~~~ +// 1. PrimitiveForm +// 2. FormLiteralFinish +// +// form ??? +// ^~~~ +// 1. FormLiteralFinish +CARBON_PARSE_STATE(FormLiteral) + +// Handles the category modifier and type of a form literal. +// +// form ( val ... +// ^~~ +// form ( var ... +// ^~~ +// form ( ref ... +// ^~~ +// form ( ??? +// ^ +// 1. Expr +// 2. PrimitiveFormFinish +CARBON_PARSE_STATE(PrimitiveForm) + +// Finishes handling of PrimitiveForm. +// +// form ( ... ) +// ^ +// form ??? +// ^ +CARBON_PARSE_STATE(PrimitiveFormFinish) + +// Handles the end of a form literal. +// +// form ( ... ) +// ^ +// form ( ??? ) +// ^~~~~ +// form ??? +// ^ +// (state done) +CARBON_PARSE_STATE(FormLiteralFinish) + // Handles the `{` of a brace expression. // // {} @@ -485,11 +530,16 @@ CARBON_PARSE_STATE(Expr) // 1. ParenExpr // 2. ExprInPostfixLoop // -// [ +// array // ^ // 1. ArrayExpr // 2. ExprInPostfixLoop // +// form +// ^ +// 1. FormExpr +// 2. ExprInPostfixLoop +// // ??? // ^ // (state done) @@ -765,6 +815,12 @@ CARBON_PARSE_STATE(LambdaBodyFinish) // 2. FunctionReturnTypeFinish // 3. FunctionSignatureFinish // +// fn F(...) ->? ... +// ^~~ +// 1. Expr +// 2. FunctionReturnFormFinish +// 3. FunctionSignatureFinish +// // fn F(...) ... // ^ // 1. FunctionSignatureFinish @@ -777,6 +833,13 @@ CARBON_PARSE_STATE(FunctionAfterParams) // (state done) CARBON_PARSE_STATE(FunctionReturnTypeFinish) +// Finishes a function return form. +// +// fn F(...) ->? expr ... +// ^ +// (state done) +CARBON_PARSE_STATE(FunctionReturnFormFinish) + // Finishes a function signature. If it's a declaration, the function is done; // otherwise, this also starts definition processing. // @@ -1086,11 +1149,11 @@ CARBON_PARSE_STATE(Pattern) // with `ref` in expression patterns. See issue #6342. // // [ref] name: ... -// ^~~~~ +// ^~~~~~~~~~~ // [ref] self: ... -// ^~~~~ +// ^~~~~~~~~~~ // [ref] _: ... -// ^~ +// ^~~~~~~~ // 1. Expr // 2. BindingPatternFinishAsRegular // @@ -1103,6 +1166,15 @@ CARBON_PARSE_STATE(Pattern) // 1. Expr // 2. BindingPatternFinishAsGeneric // +// name:? ... +// ^~~~~~ +// self:? ... +// ^~~~~~ +// _:? ... +// ^~~ +// 1. Expr +// 2. BindingPatternFinishAsForm +// // ??? // ^ // 1. BindingPatternFinishAsRegular @@ -1113,7 +1185,7 @@ CARBON_PARSE_STATE(BindingPattern) // name: type // ^ // (state done) -CARBON_PARSE_STATE_VARIANTS2(BindingPatternFinish, Generic, Regular) +CARBON_PARSE_STATE_VARIANTS3(BindingPatternFinish, Generic, Regular, Form) // Handles `var` in a pattern context. // diff --git a/toolchain/parse/testdata/basics/form_literals.carbon b/toolchain/parse/testdata/basics/form_literals.carbon new file mode 100644 index 000000000000..ae101c566ff2 --- /dev/null +++ b/toolchain/parse/testdata/basics/form_literals.carbon @@ -0,0 +1,173 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/parse/testdata/basics/form_literals.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/basics/form_literals.carbon + +// --- basics.carbon + +fn F() { + form(ref i32); + form(var T(X, Y)); + form(val X.Y); +} + +fn VarReturn() ->? form(ref i32); + +// --- fail_invalid_form_literal.carbon + +fn F() { + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+4]]:7: error: expected `(` after `form` [ExpectedParenAfter] + // CHECK:STDERR: form; + // CHECK:STDERR: ^ + // CHECK:STDERR: + form; + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+8]]:8: error: expected `ref`, `var`, or `val` after `form(` [ExpectedCategoryModifier] + // CHECK:STDERR: form(); + // CHECK:STDERR: ^ + // CHECK:STDERR: + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+4]]:8: error: expected expression [ExpectedExpr] + // CHECK:STDERR: form(); + // CHECK:STDERR: ^ + // CHECK:STDERR: + form(); + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+4]]:8: error: expected `ref`, `var`, or `val` after `form(` [ExpectedCategoryModifier] + // CHECK:STDERR: form(i32); + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + form(i32); + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+8]]:8: error: expected `ref`, `var`, or `val` after `form(` [ExpectedCategoryModifier] + // CHECK:STDERR: form(whole lot of nonsense); + // CHECK:STDERR: ^~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+4]]:14: error: unexpected tokens before `)` [ExpectedCloseSymbol] + // CHECK:STDERR: form(whole lot of nonsense); + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + form(whole lot of nonsense); + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+4]]:18: error: unexpected tokens before `)` [ExpectedCloseSymbol] + // CHECK:STDERR: form(var whole lot of nonsense); + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + form(var whole lot of nonsense); + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+8]]:8: error: expected `(` after `form` [ExpectedParenAfter] + // CHECK:STDERR: form whole lot of nonsense; + // CHECK:STDERR: ^~~~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+4]]:8: error: expected `;` after expression statement [ExpectedExprSemi] + // CHECK:STDERR: form whole lot of nonsense; + // CHECK:STDERR: ^~~~~ + // CHECK:STDERR: + form whole lot of nonsense; + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+8]]:8: error: expected `(` after `form` [ExpectedParenAfter] + // CHECK:STDERR: form var whole lot of nonsense; + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + // CHECK:STDERR: fail_invalid_form_literal.carbon:[[@LINE+4]]:8: error: expected `;` after expression statement [ExpectedExprSemi] + // CHECK:STDERR: form var whole lot of nonsense; + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + form var whole lot of nonsense; +} + +// CHECK:STDOUT: - filename: basics.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'F'}, +// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, +// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: '('}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'RefPrimitiveForm', text: 'ref', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: '('}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'T'}, +// CHECK:STDOUT: {kind: 'CallExprStart', text: '(', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'X'}, +// CHECK:STDOUT: {kind: 'TupleLiteralComma', text: ','}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Y'}, +// CHECK:STDOUT: {kind: 'CallExpr', text: ')', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'VarPrimitiveForm', text: 'var', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: ')', subtree_size: 10}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 11}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: '('}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'X'}, +// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'}, +// CHECK:STDOUT: {kind: 'MemberAccessExpr', text: '.', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ValPrimitiveForm', text: 'val', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: ')', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 8}, +// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 31}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'VarReturn'}, +// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, +// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: '('}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'RefPrimitiveForm', text: 'ref', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ReturnForm', text: '->?', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 11}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: - filename: fail_invalid_form_literal.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'F'}, +// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, +// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: 'form', has_error: yes}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: 'form', has_error: yes}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: 'form', has_error: yes, subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: '('}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: ')', has_error: yes}, +// CHECK:STDOUT: {kind: 'ValPrimitiveForm', text: 'form', has_error: yes, subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: '('}, +// CHECK:STDOUT: {kind: 'IntTypeLiteral', text: 'i32'}, +// CHECK:STDOUT: {kind: 'ValPrimitiveForm', text: 'form', has_error: yes, subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: '('}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'whole'}, +// CHECK:STDOUT: {kind: 'ValPrimitiveForm', text: 'form', has_error: yes, subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: ')', has_error: yes, subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: '('}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'whole'}, +// CHECK:STDOUT: {kind: 'VarPrimitiveForm', text: 'var', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: ')', has_error: yes, subtree_size: 5}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: 'form', has_error: yes}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: 'form', has_error: yes}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: 'form', has_error: yes, subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', has_error: yes, subtree_size: 5}, +// CHECK:STDOUT: {kind: 'FormLiteralKeyword', text: 'form'}, +// CHECK:STDOUT: {kind: 'FormLiteralOpenParen', text: 'form', has_error: yes}, +// CHECK:STDOUT: {kind: 'InvalidParse', text: 'form', has_error: yes}, +// CHECK:STDOUT: {kind: 'FormLiteral', text: 'form', has_error: yes, subtree_size: 4}, +// CHECK:STDOUT: {kind: 'ExprStatement', text: ';', has_error: yes, subtree_size: 5}, +// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 45}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/function/declaration.carbon b/toolchain/parse/testdata/function/declaration.carbon index 39e6ff94bc0a..cebbda087ca8 100644 --- a/toolchain/parse/testdata/function/declaration.carbon +++ b/toolchain/parse/testdata/function/declaration.carbon @@ -148,7 +148,7 @@ fn F(); // --- fail_with_identifier_as_param.carbon -// CHECK:STDERR: fail_with_identifier_as_param.carbon:[[@LINE+4]]:11: error: expected `:` or `:!` in binding pattern [ExpectedBindingPattern] +// CHECK:STDERR: fail_with_identifier_as_param.carbon:[[@LINE+4]]:11: error: expected `:`, `:!`, or `:?` in binding pattern [ExpectedBindingPattern] // CHECK:STDERR: fn foo(bar); // CHECK:STDERR: ^ // CHECK:STDERR: @@ -162,6 +162,16 @@ fn foo(bar); // CHECK:STDERR: fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z); +// --- form_parameter.carbon + +fn FormParam(x:? Form); +fn ComplexFormParam(x:? X.Y(Z)); + +// --- return_form.carbon + +fn SimpleReturnForm() ->? Form; +fn ComplexReturnForm() ->? X.Y(Z); + // CHECK:STDOUT: - filename: basic.carbon // CHECK:STDOUT: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, @@ -421,3 +431,53 @@ fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z); // CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', has_error: yes, subtree_size: 3}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] +// CHECK:STDOUT: - filename: form_parameter.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'FormParam'}, +// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, +// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'x'}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Form'}, +// CHECK:STDOUT: {kind: 'FormBindingPattern', text: ':?', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 5}, +// CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 8}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'ComplexFormParam'}, +// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, +// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'x'}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'X'}, +// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'}, +// CHECK:STDOUT: {kind: 'MemberAccessExpr', text: '.', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'CallExprStart', text: '(', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Z'}, +// CHECK:STDOUT: {kind: 'CallExpr', text: ')', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FormBindingPattern', text: ':?', subtree_size: 8}, +// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 10}, +// CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 13}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] +// CHECK:STDOUT: - filename: return_form.carbon +// CHECK:STDOUT: parse_tree: [ +// CHECK:STDOUT: {kind: 'FileStart', text: ''}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'SimpleReturnForm'}, +// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, +// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Form'}, +// CHECK:STDOUT: {kind: 'ReturnForm', text: '->?', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'ComplexReturnForm'}, +// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, +// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'X'}, +// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'Y'}, +// CHECK:STDOUT: {kind: 'MemberAccessExpr', text: '.', subtree_size: 3}, +// CHECK:STDOUT: {kind: 'CallExprStart', text: '(', subtree_size: 4}, +// CHECK:STDOUT: {kind: 'IdentifierNameExpr', text: 'Z'}, +// CHECK:STDOUT: {kind: 'CallExpr', text: ')', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'ReturnForm', text: '->?', subtree_size: 7}, +// CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 12}, +// CHECK:STDOUT: {kind: 'FileEnd', text: ''}, +// CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/generics/impl/fail_impl.carbon b/toolchain/parse/testdata/generics/impl/fail_impl.carbon index 27e1483295c5..78bd596d55e0 100644 --- a/toolchain/parse/testdata/generics/impl/fail_impl.carbon +++ b/toolchain/parse/testdata/generics/impl/fail_impl.carbon @@ -54,7 +54,7 @@ impl forall f32; // CHECK:STDERR: impl forall [] u32; -// CHECK:STDERR: fail_impl.carbon:[[@LINE+8]]:21: error: expected `:` or `:!` in binding pattern [ExpectedBindingPattern] +// CHECK:STDERR: fail_impl.carbon:[[@LINE+8]]:21: error: expected `:`, `:!`, or `:?` in binding pattern [ExpectedBindingPattern] // CHECK:STDERR: impl forall [invalid] i8; // CHECK:STDERR: ^ // CHECK:STDERR: diff --git a/toolchain/parse/testdata/generics/interface/fail_self_param_syntax.carbon b/toolchain/parse/testdata/generics/interface/fail_self_param_syntax.carbon index 45990cc0d633..0f51570174d3 100644 --- a/toolchain/parse/testdata/generics/interface/fail_self_param_syntax.carbon +++ b/toolchain/parse/testdata/generics/interface/fail_self_param_syntax.carbon @@ -9,7 +9,7 @@ // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/generics/interface/fail_self_param_syntax.carbon interface Foo { - // CHECK:STDERR: fail_self_param_syntax.carbon:[[@LINE+4]]:13: error: expected `:` or `:!` in binding pattern [ExpectedBindingPattern] + // CHECK:STDERR: fail_self_param_syntax.carbon:[[@LINE+4]]:13: error: expected `:`, `:!`, or `:?` in binding pattern [ExpectedBindingPattern] // CHECK:STDERR: fn Sub[me Self](b: Self) -> Self; // CHECK:STDERR: ^~~~ // CHECK:STDERR: diff --git a/toolchain/parse/testdata/let/fail_missing_type.carbon b/toolchain/parse/testdata/let/fail_missing_type.carbon index 7e0077d4f043..9bd1beeaa8a6 100644 --- a/toolchain/parse/testdata/let/fail_missing_type.carbon +++ b/toolchain/parse/testdata/let/fail_missing_type.carbon @@ -8,7 +8,7 @@ // TIP: To dump output, run: // TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/parse/testdata/let/fail_missing_type.carbon -// CHECK:STDERR: fail_missing_type.carbon:[[@LINE+4]]:7: error: expected `:` or `:!` in binding pattern [ExpectedBindingPattern] +// CHECK:STDERR: fail_missing_type.carbon:[[@LINE+4]]:7: error: expected `:`, `:!`, or `:?` in binding pattern [ExpectedBindingPattern] // CHECK:STDERR: let a = 4; // CHECK:STDERR: ^ // CHECK:STDERR: diff --git a/toolchain/parse/tree.h b/toolchain/parse/tree.h index f47921da93dc..4c9510cf2d5d 100644 --- a/toolchain/parse/tree.h +++ b/toolchain/parse/tree.h @@ -196,7 +196,7 @@ class Tree : public Printable { // The in-memory representation of data used for a particular node in the // tree. - class NodeImpl { + class NodeImpl : public Printable { public: explicit NodeImpl(NodeKind kind, bool has_error, Lex::TokenIndex token) : kind_(kind), has_error_(has_error), token_index_(token.index) { @@ -210,6 +210,11 @@ class Tree : public Printable { return Lex::TokenIndex(token_index_); } + auto Print(llvm::raw_ostream& output) const -> void { + output << "{kind: " << kind_ << ", has_error: " << has_error_ + << ", token_index: " << token_index_ << "}\n"; + } + private: // The kind of this node. NodeKind kind_; diff --git a/toolchain/parse/tree_and_subtrees.cpp b/toolchain/parse/tree_and_subtrees.cpp index 9993be4702d6..081dbf4aae37 100644 --- a/toolchain/parse/tree_and_subtrees.cpp +++ b/toolchain/parse/tree_and_subtrees.cpp @@ -35,17 +35,19 @@ TreeAndSubtrees::TreeAndSubtrees(const Lex::TokenizedBuffer& tokens, CARBON_CHECK(static_cast(child.index) < subtree_sizes_.size()); size += subtree_sizes_.Get(child); if (kind.has_bracket() && i == kind.child_count() - 1) { - CARBON_CHECK(kind.bracket() == tree.node_kind(child), - "Node {0} with child count {1} needs bracket {2}, found " - "wrong bracket {3}", - kind, kind.child_count(), kind.bracket(), - tree.node_kind(child)); + CARBON_CHECK( + kind.bracket() == tree.node_kind(child), + "NodeId {0} ({1}) with child count {2} needs bracket {3}, found " + "wrong bracket {4}", + n, kind, kind.child_count(), kind.bracket(), + tree.node_kind(child)); } } } else { while (true) { - CARBON_CHECK(!size_stack.empty(), "Node {0} is missing bracket {1}", - kind, kind.bracket()); + CARBON_CHECK(!size_stack.empty(), + "NodeId {0} ({1}) is missing bracket {2}", kind, n, + kind.bracket()); auto child = size_stack.pop_back_val(); size += subtree_sizes_.Get(child); if (kind.bracket() == tree.node_kind(child)) { diff --git a/toolchain/parse/typed_nodes.h b/toolchain/parse/typed_nodes.h index 833dab355bf6..b37eabaa7d49 100644 --- a/toolchain/parse/typed_nodes.h +++ b/toolchain/parse/typed_nodes.h @@ -365,6 +365,16 @@ struct VarBindingPattern { AnyExprId type; }; +// A form binding pattern, such as `name:? Form`. +struct FormBindingPattern { + static constexpr auto Kind = NodeKind::FormBindingPattern.Define( + {.category = NodeCategory::Pattern, .child_count = 2}); + + AnyRuntimeBindingPatternName name; + Lex::ColonQuestionTokenIndex token; + AnyExprId type; +}; + // A template binding name: `template T`. struct TemplateBindingName { static constexpr auto Kind = @@ -452,6 +462,14 @@ struct ReturnType { AnyExprId type; }; +// A return form: `->? form(var i32)` +struct ReturnForm { + static constexpr auto Kind = NodeKind::ReturnForm.Define({.child_count = 1}); + + Lex::MinusGreaterQuestionTokenIndex token; + AnyExprId type; +}; + // A function signature: `fn F() -> i32`. template @@ -462,7 +480,7 @@ struct FunctionSignature { FunctionIntroducerId introducer; llvm::SmallVector modifiers; DeclName name; - std::optional return_type; + std::optional> return_type; TokenKind token; }; @@ -964,6 +982,49 @@ struct ArrayExpr { Lex::CloseParenTokenIndex token; }; +struct RefPrimitiveForm { + static constexpr auto Kind = NodeKind::RefPrimitiveForm.Define( + {.category = NodeCategory::Expr, .child_count = 1}); + + Lex::RefTokenIndex token; + AnyExprId type; +}; + +struct VarPrimitiveForm { + static constexpr auto Kind = NodeKind::VarPrimitiveForm.Define( + {.category = NodeCategory::Expr, .child_count = 1}); + + Lex::VarTokenIndex token; + AnyExprId type; +}; + +struct ValPrimitiveForm { + static constexpr auto Kind = NodeKind::ValPrimitiveForm.Define( + {.category = NodeCategory::Expr, .child_count = 1}); + + Lex::ValTokenIndex token; + AnyExprId type; +}; + +using FormLiteralKeyword = + LeafNode; + +using FormLiteralOpenParen = + LeafNode; + +// A `form` literal: `form(ref i32)` +struct FormLiteral { + static constexpr auto Kind = NodeKind::FormLiteral.Define( + {.category = NodeCategory::Expr, + .bracketed_by = NodeKind::FormLiteralKeyword, + .child_count = 3}); + + FormLiteralKeywordId keyword; + FormLiteralOpenParenId start; + AnyPrimitiveFormIdId category; + Lex::CloseParenTokenIndex token; +}; + // The opening portion of an indexing expression: `a[`. // // TODO: Consider flattening this into `IndexExpr`.