From 145f878ce82214f5a4c387f371f80c7ea2d069a3 Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Mon, 18 Nov 2024 08:01:44 -0800 Subject: [PATCH] Allow `extend adapt` of non-class types. (#4544) Stop rejecting `extend adapt` of non-class types such as struct and tuple. These don't actually work just yet because name lookup into struct and tuple types is a special case that doesn't handle adapters, but this gets us a bit closer. This also slightly improves error recovery for name lookup into an invalid scope. --- toolchain/check/context.cpp | 6 + toolchain/check/handle_class.cpp | 20 +- .../check/testdata/class/extend_adapt.carbon | 257 +++++++++++++++++- .../check/testdata/class/fail_abstract.carbon | 1 + .../testdata/class/fail_adapt_bad_decl.carbon | 2 +- .../packages/no_prelude/export_name.carbon | 1 + .../testdata/pointer/fail_deref_error.carbon | 1 + .../pointer/fail_deref_function.carbon | 1 + .../pointer/fail_deref_namespace.carbon | 1 + .../pointer/fail_deref_not_pointer.carbon | 3 + .../testdata/pointer/fail_deref_type.carbon | 1 + .../struct/fail_access_into_invalid.carbon | 1 + .../struct/fail_duplicate_name.carbon | 1 + .../struct/fail_member_of_function.carbon | 1 + .../no_prelude/fail_nested_incomplete.carbon | 3 +- .../testdata/where_expr/designator.carbon | 2 + .../testdata/where_expr/fail_not_facet.carbon | 3 +- 17 files changed, 269 insertions(+), 36 deletions(-) diff --git a/toolchain/check/context.cpp b/toolchain/check/context.cpp index 42f186997a0e..9a7af983969b 100644 --- a/toolchain/check/context.cpp +++ b/toolchain/check/context.cpp @@ -481,6 +481,12 @@ auto Context::AppendLookupScopesForConstant( } return true; } + if (base_const_id == SemIR::ConstantId::Error) { + // Lookup into this scope should fail without producing an error. + scopes->push_back(LookupScope{.name_scope_id = SemIR::NameScopeId::Invalid, + .specific_id = SemIR::SpecificId::Invalid}); + return true; + } // TODO: Per the design, if `base_id` is any kind of type, then lookup should // treat it as a name scope, even if it doesn't have members. For example, // `(i32*).X` should fail because there's no name `X` in `i32*`, not because diff --git a/toolchain/check/handle_class.cpp b/toolchain/check/handle_class.cpp index 56db92aba11d..b9092cd5e89a 100644 --- a/toolchain/check/handle_class.cpp +++ b/toolchain/check/handle_class.cpp @@ -405,26 +405,8 @@ auto HandleParseNode(Context& context, Parse::AdaptDeclId node_id) -> bool { // Extend the class scope with the adapted type's scope if requested. if (introducer.modifier_set.HasAnyOf(KeywordModifierSet::Extend)) { - auto extended_scope_inst_id = SemIR::InstId::Invalid; - if (adapted_type_id == SemIR::TypeId::Error) { - // Recover by not extending any scope. We instead set has_error to true - // below. - } else if (auto* adapted_class_info = - TryGetAsClass(context, adapted_type_id)) { - extended_scope_inst_id = adapted_inst_id; - CARBON_CHECK(adapted_class_info->scope_id.is_valid(), - "Complete class should have a scope"); - } else { - // TODO: Accept any type that has a scope. - context.TODO(node_id, "extending non-class type"); - } - auto& class_scope = context.name_scopes().Get(class_info.scope_id); - if (extended_scope_inst_id.is_valid()) { - class_scope.extended_scopes.push_back(extended_scope_inst_id); - } else { - class_scope.has_error = true; - } + class_scope.extended_scopes.push_back(adapted_inst_id); } return true; } diff --git a/toolchain/check/testdata/class/extend_adapt.carbon b/toolchain/check/testdata/class/extend_adapt.carbon index 4d82e6e45858..63e867dce508 100644 --- a/toolchain/check/testdata/class/extend_adapt.carbon +++ b/toolchain/check/testdata/class/extend_adapt.carbon @@ -85,17 +85,58 @@ fn F(a: SomeClassAdapter) -> i32 { return a.b; } -// --- fail_todo_adapt_non_class.carbon +// --- fail_todo_adapt_struct.carbon library "[[@TEST_NAME]]"; class StructAdapter { - // CHECK:STDERR: fail_todo_adapt_non_class.carbon:[[@LINE+3]]:3: error: semantics TODO: `extending non-class type` [SemanticsTodo] - // CHECK:STDERR: extend adapt {.a: i32, .b: i32}; - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ extend adapt {.a: i32, .b: i32}; } +fn F(a: StructAdapter) -> i32 { + // TODO: This should be allowed. + // CHECK:STDERR: fail_todo_adapt_struct.carbon:[[@LINE+4]]:10: error: name `b` not found [NameNotFound] + // CHECK:STDERR: return a.b; + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + return a.b; +} + +// --- fail_todo_adapt_tuple.carbon + +library "[[@TEST_NAME]]"; + +class TupleAdapter { + extend adapt (i32, i32); +} + +fn F(a: TupleAdapter) -> i32 { + // TODO: This should be allowed. + // CHECK:STDERR: fail_todo_adapt_tuple.carbon:[[@LINE+4]]:10: error: type `TupleAdapter` does not support tuple indexing; only tuples can be indexed that way [TupleIndexOnANonTupleType] + // CHECK:STDERR: return a.1; + // CHECK:STDERR: ^~~ + // CHECK:STDERR: + return a.1; +} + +// --- fail_adapt_builtin.carbon + +library "[[@TEST_NAME]]"; + +fn MakeInt(N: Core.IntLiteral()) -> type = "int.make_type_signed"; + +class IntAdapter { + extend adapt MakeInt(32); +} + +fn F(a: IntAdapter) -> i32 { + // Builtin types have no member names. + // CHECK:STDERR: fail_adapt_builtin.carbon:[[@LINE+3]]:10: error: name `foo` not found [NameNotFound] + // CHECK:STDERR: return a.foo; + // CHECK:STDERR: ^~~~~ + return a.foo; +} + // CHECK:STDOUT: --- basic.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { @@ -383,7 +424,7 @@ class StructAdapter { // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: --- fail_todo_adapt_non_class.carbon +// CHECK:STDOUT: --- fail_todo_adapt_struct.carbon // CHECK:STDOUT: // CHECK:STDOUT: constants { // CHECK:STDOUT: %StructAdapter: type = class_type @StructAdapter [template] @@ -391,6 +432,8 @@ class StructAdapter { // CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] // CHECK:STDOUT: %.1: type = struct_type {.a: i32, .b: i32} [template] // CHECK:STDOUT: %.3: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: imports { @@ -405,24 +448,210 @@ class StructAdapter { // CHECK:STDOUT: package: = namespace [template] { // CHECK:STDOUT: .Core = imports.%Core // CHECK:STDOUT: .StructAdapter = %StructAdapter.decl +// CHECK:STDOUT: .F = %F.decl // CHECK:STDOUT: } // CHECK:STDOUT: %Core.import = import Core // CHECK:STDOUT: %StructAdapter.decl: type = class_decl @StructAdapter [template = constants.%StructAdapter] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %a.patt: %StructAdapter = binding_pattern a +// CHECK:STDOUT: %a.param_patt: %StructAdapter = value_param_pattern %a.patt, runtime_param0 +// CHECK:STDOUT: %return.patt: i32 = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %StructAdapter.ref: type = name_ref StructAdapter, file.%StructAdapter.decl [template = constants.%StructAdapter] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_27.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc8_27.2: type = converted %int.make_type_32, %.loc8_27.1 [template = i32] +// CHECK:STDOUT: %a.param: %StructAdapter = value_param runtime_param0 +// CHECK:STDOUT: %a: %StructAdapter = bind_name a, %a.param +// CHECK:STDOUT: %return.param: ref i32 = out_param runtime_param1 +// CHECK:STDOUT: %return: ref i32 = return_slot %return.param +// CHECK:STDOUT: } // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: class @StructAdapter { -// CHECK:STDOUT: %int.make_type_32.loc8_21: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc8_21.1: type = value_of_initializer %int.make_type_32.loc8_21 [template = i32] -// CHECK:STDOUT: %.loc8_21.2: type = converted %int.make_type_32.loc8_21, %.loc8_21.1 [template = i32] -// CHECK:STDOUT: %int.make_type_32.loc8_30: init type = call constants.%Int32() [template = i32] -// CHECK:STDOUT: %.loc8_30.1: type = value_of_initializer %int.make_type_32.loc8_30 [template = i32] -// CHECK:STDOUT: %.loc8_30.2: type = converted %int.make_type_32.loc8_30, %.loc8_30.1 [template = i32] -// CHECK:STDOUT: %.loc8_33: type = struct_type {.a: i32, .b: i32} [template = constants.%.1] +// CHECK:STDOUT: %int.make_type_32.loc5_21: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc5_21.1: type = value_of_initializer %int.make_type_32.loc5_21 [template = i32] +// CHECK:STDOUT: %.loc5_21.2: type = converted %int.make_type_32.loc5_21, %.loc5_21.1 [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc5_30: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc5_30.1: type = value_of_initializer %int.make_type_32.loc5_30 [template = i32] +// CHECK:STDOUT: %.loc5_30.2: type = converted %int.make_type_32.loc5_30, %.loc5_30.1 [template = i32] +// CHECK:STDOUT: %.loc5_33: type = struct_type {.a: i32, .b: i32} [template = constants.%.1] // CHECK:STDOUT: adapt_decl %.1 -// CHECK:STDOUT: %.loc9: = complete_type_witness %.1 [template = constants.%.3] +// CHECK:STDOUT: %.loc6: = complete_type_witness %.1 [template = constants.%.3] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%StructAdapter -// CHECK:STDOUT: has_error +// CHECK:STDOUT: extend %.loc5_33 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%a.param_patt: %StructAdapter) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: %StructAdapter = name_ref a, %a +// CHECK:STDOUT: %b.ref: = name_ref b, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_adapt_tuple.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %TupleAdapter: type = class_type @TupleAdapter [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %tuple.type.1: type = tuple_type (type, type) [template] +// CHECK:STDOUT: %tuple.type.2: type = tuple_type (i32, i32) [template] +// CHECK:STDOUT: %.2: = complete_type_witness %tuple.type.2 [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.3: Core.IntLiteral = int_value 1 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Int32 = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .TupleAdapter = %TupleAdapter.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %TupleAdapter.decl: type = class_decl @TupleAdapter [template = constants.%TupleAdapter] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %a.patt: %TupleAdapter = binding_pattern a +// CHECK:STDOUT: %a.param_patt: %TupleAdapter = value_param_pattern %a.patt, runtime_param0 +// CHECK:STDOUT: %return.patt: i32 = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %TupleAdapter.ref: type = name_ref TupleAdapter, file.%TupleAdapter.decl [template = constants.%TupleAdapter] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc8_26.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc8_26.2: type = converted %int.make_type_32, %.loc8_26.1 [template = i32] +// CHECK:STDOUT: %a.param: %TupleAdapter = value_param runtime_param0 +// CHECK:STDOUT: %a: %TupleAdapter = bind_name a, %a.param +// CHECK:STDOUT: %return.param: ref i32 = out_param runtime_param1 +// CHECK:STDOUT: %return: ref i32 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @TupleAdapter { +// CHECK:STDOUT: %int.make_type_32.loc5_17: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %int.make_type_32.loc5_22: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc5_25: %tuple.type.1 = tuple_literal (%int.make_type_32.loc5_17, %int.make_type_32.loc5_22) +// CHECK:STDOUT: %.loc5_26.1: type = value_of_initializer %int.make_type_32.loc5_17 [template = i32] +// CHECK:STDOUT: %.loc5_26.2: type = converted %int.make_type_32.loc5_17, %.loc5_26.1 [template = i32] +// CHECK:STDOUT: %.loc5_26.3: type = value_of_initializer %int.make_type_32.loc5_22 [template = i32] +// CHECK:STDOUT: %.loc5_26.4: type = converted %int.make_type_32.loc5_22, %.loc5_26.3 [template = i32] +// CHECK:STDOUT: %.loc5_26.5: type = converted %.loc5_25, constants.%tuple.type.2 [template = constants.%tuple.type.2] +// CHECK:STDOUT: adapt_decl %tuple.type.2 +// CHECK:STDOUT: %.loc6: = complete_type_witness %tuple.type.2 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%TupleAdapter +// CHECK:STDOUT: extend %.loc5_26.5 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%a.param_patt: %TupleAdapter) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: %TupleAdapter = name_ref a, %a +// CHECK:STDOUT: %.loc14: Core.IntLiteral = int_value 1 [template = constants.%.3] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_adapt_builtin.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %IntLiteral.type: type = fn_type @IntLiteral [template] +// CHECK:STDOUT: %IntLiteral: %IntLiteral.type = struct_value () [template] +// CHECK:STDOUT: %MakeInt.type: type = fn_type @MakeInt [template] +// CHECK:STDOUT: %MakeInt: %MakeInt.type = struct_value () [template] +// CHECK:STDOUT: %IntAdapter: type = class_type @IntAdapter [template] +// CHECK:STDOUT: %.1: Core.IntLiteral = int_value 32 [template] +// CHECK:STDOUT: %.2: type = int_type signed, %.1 [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] +// CHECK:STDOUT: %Int32.type: type = fn_type @Int32 [template] +// CHECK:STDOUT: %Int32: %Int32.type = struct_value () [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .IntLiteral = %import_ref.1 +// CHECK:STDOUT: .Int32 = %import_ref.2 +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/... +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.1: %IntLiteral.type = import_ref Core//prelude/types, inst+7, loaded [template = constants.%IntLiteral] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .MakeInt = %MakeInt.decl +// CHECK:STDOUT: .IntAdapter = %IntAdapter.decl +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %MakeInt.decl: %MakeInt.type = fn_decl @MakeInt [template = constants.%MakeInt] { +// CHECK:STDOUT: %N.patt: Core.IntLiteral = binding_pattern N +// CHECK:STDOUT: %N.param_patt: Core.IntLiteral = value_param_pattern %N.patt, runtime_param0 +// CHECK:STDOUT: %return.patt: type = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: type = out_param_pattern %return.patt, runtime_param1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %Core.ref: = name_ref Core, imports.%Core [template = imports.%Core] +// CHECK:STDOUT: %IntLiteral.ref: %IntLiteral.type = name_ref IntLiteral, imports.%import_ref.1 [template = constants.%IntLiteral] +// CHECK:STDOUT: %int_literal.make_type: init type = call %IntLiteral.ref() [template = Core.IntLiteral] +// CHECK:STDOUT: %.loc4_31.1: type = value_of_initializer %int_literal.make_type [template = Core.IntLiteral] +// CHECK:STDOUT: %.loc4_31.2: type = converted %int_literal.make_type, %.loc4_31.1 [template = Core.IntLiteral] +// CHECK:STDOUT: %N.param: Core.IntLiteral = value_param runtime_param0 +// CHECK:STDOUT: %N: Core.IntLiteral = bind_name N, %N.param +// CHECK:STDOUT: %return.param: ref type = out_param runtime_param1 +// CHECK:STDOUT: %return: ref type = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: %IntAdapter.decl: type = class_decl @IntAdapter [template = constants.%IntAdapter] {} {} +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %a.patt: %IntAdapter = binding_pattern a +// CHECK:STDOUT: %a.param_patt: %IntAdapter = value_param_pattern %a.patt, runtime_param0 +// CHECK:STDOUT: %return.patt: i32 = return_slot_pattern +// CHECK:STDOUT: %return.param_patt: i32 = out_param_pattern %return.patt, runtime_param1 +// CHECK:STDOUT: } { +// CHECK:STDOUT: %IntAdapter.ref: type = name_ref IntAdapter, file.%IntAdapter.decl [template = constants.%IntAdapter] +// CHECK:STDOUT: %int.make_type_32: init type = call constants.%Int32() [template = i32] +// CHECK:STDOUT: %.loc10_24.1: type = value_of_initializer %int.make_type_32 [template = i32] +// CHECK:STDOUT: %.loc10_24.2: type = converted %int.make_type_32, %.loc10_24.1 [template = i32] +// CHECK:STDOUT: %a.param: %IntAdapter = value_param runtime_param0 +// CHECK:STDOUT: %a: %IntAdapter = bind_name a, %a.param +// CHECK:STDOUT: %return.param: ref i32 = out_param runtime_param1 +// CHECK:STDOUT: %return: ref i32 = return_slot %return.param +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @IntAdapter { +// CHECK:STDOUT: %MakeInt.ref: %MakeInt.type = name_ref MakeInt, file.%MakeInt.decl [template = constants.%MakeInt] +// CHECK:STDOUT: %.loc7_24: Core.IntLiteral = int_value 32 [template = constants.%.1] +// CHECK:STDOUT: %int.make_type_signed: init type = call %MakeInt.ref(%.loc7_24) [template = constants.%.2] +// CHECK:STDOUT: %.loc7_27.1: type = value_of_initializer %int.make_type_signed [template = constants.%.2] +// CHECK:STDOUT: %.loc7_27.2: type = converted %int.make_type_signed, %.loc7_27.1 [template = constants.%.2] +// CHECK:STDOUT: adapt_decl %.2 +// CHECK:STDOUT: %.loc8: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%IntAdapter +// CHECK:STDOUT: extend %.loc7_27.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @MakeInt(%N.param_patt: Core.IntLiteral) -> type = "int.make_type_signed"; +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F(%a.param_patt: %IntAdapter) -> i32 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %a.ref: %IntAdapter = name_ref a, %a +// CHECK:STDOUT: %foo.ref: = name_ref foo, [template = ] +// CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_abstract.carbon b/toolchain/check/testdata/class/fail_abstract.carbon index 6d03114f2295..fadb840bc77e 100644 --- a/toolchain/check/testdata/class/fail_abstract.carbon +++ b/toolchain/check/testdata/class/fail_abstract.carbon @@ -678,6 +678,7 @@ fn CallReturnAbstract() { // CHECK:STDOUT: %d.ref: %Derived = name_ref d, %d // CHECK:STDOUT: %base.ref: %.5 = name_ref base, @Derived.%.loc9 [template = @Derived.%.loc9] // CHECK:STDOUT: %.loc15: ref %Abstract = class_element_access %d.ref, element0 +// CHECK:STDOUT: %a.ref: = name_ref a, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/class/fail_adapt_bad_decl.carbon b/toolchain/check/testdata/class/fail_adapt_bad_decl.carbon index 8e81326df916..253ef03fa257 100644 --- a/toolchain/check/testdata/class/fail_adapt_bad_decl.carbon +++ b/toolchain/check/testdata/class/fail_adapt_bad_decl.carbon @@ -197,7 +197,7 @@ class C { // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .Self = constants.%Bad -// CHECK:STDOUT: has_error +// CHECK:STDOUT: extend // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: fn @Use(%b.param_patt: %Bad) { diff --git a/toolchain/check/testdata/packages/no_prelude/export_name.carbon b/toolchain/check/testdata/packages/no_prelude/export_name.carbon index b55e95321e0e..3a19fa4cc010 100644 --- a/toolchain/check/testdata/packages/no_prelude/export_name.carbon +++ b/toolchain/check/testdata/packages/no_prelude/export_name.carbon @@ -818,6 +818,7 @@ private export C; // CHECK:STDOUT: %C.ref: = name_ref C, [template = ] // CHECK:STDOUT: %Local: = bind_alias Local, [template = ] // CHECK:STDOUT: %NS.ref: = name_ref NS, [template = ] +// CHECK:STDOUT: %NSC.ref: = name_ref NSC, [template = ] // CHECK:STDOUT: %NSLocal: = bind_alias NSLocal, [template = ] // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/pointer/fail_deref_error.carbon b/toolchain/check/testdata/pointer/fail_deref_error.carbon index 8d2e66850574..f418207acc39 100644 --- a/toolchain/check/testdata/pointer/fail_deref_error.carbon +++ b/toolchain/check/testdata/pointer/fail_deref_error.carbon @@ -55,6 +55,7 @@ let n2: i32 = undeclared->foo; // CHECK:STDOUT: %n: i32 = bind_name n, // CHECK:STDOUT: %undeclared.ref.loc19: = name_ref undeclared, [template = ] // CHECK:STDOUT: %.loc19: ref = deref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [template = ] // CHECK:STDOUT: %n2: i32 = bind_name n2, // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/pointer/fail_deref_function.carbon b/toolchain/check/testdata/pointer/fail_deref_function.carbon index 1f8453c3f75f..e5581afc0b75 100644 --- a/toolchain/check/testdata/pointer/fail_deref_function.carbon +++ b/toolchain/check/testdata/pointer/fail_deref_function.carbon @@ -49,6 +49,7 @@ fn A() { // CHECK:STDOUT: %.loc16: ref = deref // CHECK:STDOUT: %A.ref.loc20: %A.type = name_ref A, file.%A.decl [template = constants.%A] // CHECK:STDOUT: %.loc20: ref = deref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/pointer/fail_deref_namespace.carbon b/toolchain/check/testdata/pointer/fail_deref_namespace.carbon index bb5f090da91b..70209f14436f 100644 --- a/toolchain/check/testdata/pointer/fail_deref_namespace.carbon +++ b/toolchain/check/testdata/pointer/fail_deref_namespace.carbon @@ -53,6 +53,7 @@ fn F() { // CHECK:STDOUT: %.loc18: ref = deref // CHECK:STDOUT: %A.ref.loc22: = name_ref A, file.%A [template = file.%A] // CHECK:STDOUT: %.loc22: ref = deref +// CHECK:STDOUT: %foo.ref: = name_ref foo, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/pointer/fail_deref_not_pointer.carbon b/toolchain/check/testdata/pointer/fail_deref_not_pointer.carbon index e4139f89eb28..a3149384f683 100644 --- a/toolchain/check/testdata/pointer/fail_deref_not_pointer.carbon +++ b/toolchain/check/testdata/pointer/fail_deref_not_pointer.carbon @@ -85,6 +85,7 @@ fn Deref(n: i32) { // CHECK:STDOUT: %.loc16: ref = deref %n.ref.loc16 // CHECK:STDOUT: %n.ref.loc21: i32 = name_ref n, %n // CHECK:STDOUT: %.loc21: ref = deref %n.ref.loc21 +// CHECK:STDOUT: %foo.ref.loc21: = name_ref foo, [template = ] // CHECK:STDOUT: %.loc26_5.1: %empty_tuple.type = tuple_literal () // CHECK:STDOUT: %empty_tuple.loc26: %empty_tuple.type = tuple_value () [template = constants.%empty_tuple] // CHECK:STDOUT: %.loc26_5.2: %empty_tuple.type = converted %.loc26_5.1, %empty_tuple.loc26 [template = constants.%empty_tuple] @@ -93,6 +94,7 @@ fn Deref(n: i32) { // CHECK:STDOUT: %empty_tuple.loc31: %empty_tuple.type = tuple_value () [template = constants.%empty_tuple] // CHECK:STDOUT: %.loc31_4.2: %empty_tuple.type = converted %.loc31_4.1, %empty_tuple.loc31 [template = constants.%empty_tuple] // CHECK:STDOUT: %.loc31_5: ref = deref %.loc31_4.2 +// CHECK:STDOUT: %foo.ref.loc31: = name_ref foo, [template = ] // CHECK:STDOUT: %.loc36_5.1: %.1 = struct_literal () // CHECK:STDOUT: %struct.loc36: %.1 = struct_value () [template = constants.%struct] // CHECK:STDOUT: %.loc36_5.2: %.1 = converted %.loc36_5.1, %struct.loc36 [template = constants.%struct] @@ -101,6 +103,7 @@ fn Deref(n: i32) { // CHECK:STDOUT: %struct.loc40: %.1 = struct_value () [template = constants.%struct] // CHECK:STDOUT: %.loc40_4.2: %.1 = converted %.loc40_4.1, %struct.loc40 [template = constants.%struct] // CHECK:STDOUT: %.loc40_5: ref = deref %.loc40_4.2 +// CHECK:STDOUT: %foo.ref.loc40: = name_ref foo, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/pointer/fail_deref_type.carbon b/toolchain/check/testdata/pointer/fail_deref_type.carbon index 739afc0e1962..18ea0b8e564f 100644 --- a/toolchain/check/testdata/pointer/fail_deref_type.carbon +++ b/toolchain/check/testdata/pointer/fail_deref_type.carbon @@ -53,6 +53,7 @@ var p2: i32->foo; // CHECK:STDOUT: %.loc22_9.1: type = value_of_initializer %int.make_type_32.loc22 [template = i32] // CHECK:STDOUT: %.loc22_9.2: type = converted %int.make_type_32.loc22, %.loc22_9.1 [template = i32] // CHECK:STDOUT: %.loc22_12: ref = deref %.loc22_9.2 +// CHECK:STDOUT: %foo.ref: = name_ref foo, [template = ] // CHECK:STDOUT: %p2.var: ref = var p2 // CHECK:STDOUT: %p2: ref = bind_name p2, %p2.var // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/struct/fail_access_into_invalid.carbon b/toolchain/check/testdata/struct/fail_access_into_invalid.carbon index 2aab8c214c8e..47327304a954 100644 --- a/toolchain/check/testdata/struct/fail_access_into_invalid.carbon +++ b/toolchain/check/testdata/struct/fail_access_into_invalid.carbon @@ -40,6 +40,7 @@ fn F() { a.b; } // CHECK:STDOUT: fn @F() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %a.ref: = name_ref a, [template = ] +// CHECK:STDOUT: %b.ref: = name_ref b, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/struct/fail_duplicate_name.carbon b/toolchain/check/testdata/struct/fail_duplicate_name.carbon index 34bacc81a271..f97e40f6d38c 100644 --- a/toolchain/check/testdata/struct/fail_duplicate_name.carbon +++ b/toolchain/check/testdata/struct/fail_duplicate_name.carbon @@ -143,6 +143,7 @@ var y: {.b: i32, .c: i32} = {.b = 3, .b = 4}; // CHECK:STDOUT: %v: = bind_name v, // CHECK:STDOUT: %.loc36_22: Core.IntLiteral = int_value 1 [template = constants.%.1] // CHECK:STDOUT: %.loc36_32: Core.IntLiteral = int_value 2 [template = constants.%.3] +// CHECK:STDOUT: %def.ref: = name_ref def, [template = ] // CHECK:STDOUT: %w: i32 = bind_name w, // CHECK:STDOUT: %.loc45_26: Core.IntLiteral = int_value 1 [template = constants.%.1] // CHECK:STDOUT: %.loc45_34: Core.IntLiteral = int_value 2 [template = constants.%.3] diff --git a/toolchain/check/testdata/struct/fail_member_of_function.carbon b/toolchain/check/testdata/struct/fail_member_of_function.carbon index 7002c2b1c6cd..c8198ca2a0af 100644 --- a/toolchain/check/testdata/struct/fail_member_of_function.carbon +++ b/toolchain/check/testdata/struct/fail_member_of_function.carbon @@ -41,6 +41,7 @@ fn A() { // CHECK:STDOUT: fn @A() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %A.ref: %A.type = name_ref A, file.%A.decl [template = constants.%A] +// CHECK:STDOUT: %y.ref: = name_ref y, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/struct/no_prelude/fail_nested_incomplete.carbon b/toolchain/check/testdata/struct/no_prelude/fail_nested_incomplete.carbon index 0d44aefd951a..2b0a5f31ad4e 100644 --- a/toolchain/check/testdata/struct/no_prelude/fail_nested_incomplete.carbon +++ b/toolchain/check/testdata/struct/no_prelude/fail_nested_incomplete.carbon @@ -50,7 +50,8 @@ var p: Incomplete* = &s.a; // CHECK:STDOUT: fn @__global_init() { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %s.ref: ref = name_ref s, file.%s -// CHECK:STDOUT: %.loc21: = addr_of [template = ] +// CHECK:STDOUT: %a.ref: = name_ref a, [template = ] +// CHECK:STDOUT: %.loc21: = addr_of %a.ref [template = ] // CHECK:STDOUT: assign file.%p.var, // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/where_expr/designator.carbon b/toolchain/check/testdata/where_expr/designator.carbon index ef58a2944b00..71344665cb88 100644 --- a/toolchain/check/testdata/where_expr/designator.carbon +++ b/toolchain/check/testdata/where_expr/designator.carbon @@ -331,6 +331,7 @@ class D { // CHECK:STDOUT: %x.var: ref %empty_tuple.type = var x // CHECK:STDOUT: %x: ref %empty_tuple.type = bind_name x, %x.var // CHECK:STDOUT: %.Self.ref: = name_ref .Self, [template = ] +// CHECK:STDOUT: %x.ref: = name_ref x, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: @@ -369,6 +370,7 @@ class D { // CHECK:STDOUT: fn @Bar() -> %empty_tuple.type { // CHECK:STDOUT: !entry: // CHECK:STDOUT: %.Self.ref: = name_ref .Self, [template = ] +// CHECK:STDOUT: %undef.ref: = name_ref undef, [template = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/check/testdata/where_expr/fail_not_facet.carbon b/toolchain/check/testdata/where_expr/fail_not_facet.carbon index 481f2ce7eee1..dc803f0173e7 100644 --- a/toolchain/check/testdata/where_expr/fail_not_facet.carbon +++ b/toolchain/check/testdata/where_expr/fail_not_facet.carbon @@ -173,9 +173,10 @@ var v: e where .x = 3; // CHECK:STDOUT: %e.ref: = name_ref e, [template = ] // CHECK:STDOUT: %.Self: = bind_symbolic_name .Self, 0 [symbolic = constants.%.Self] // CHECK:STDOUT: %.Self.ref: = name_ref .Self, %.Self [symbolic = constants.%.Self] +// CHECK:STDOUT: %x.ref: = name_ref x, [template = ] // CHECK:STDOUT: %.loc7_21: Core.IntLiteral = int_value 3 [template = constants.%.1] // CHECK:STDOUT: %.loc7_10: type = where_expr %.Self [template = ] { -// CHECK:STDOUT: requirement_rewrite , +// CHECK:STDOUT: requirement_rewrite %x.ref, // CHECK:STDOUT: } // CHECK:STDOUT: %v.var: ref = var v // CHECK:STDOUT: %v: ref = bind_name v, %v.var