From f3d67de480e4a727dcde5e25d091ddc74c1368ec Mon Sep 17 00:00:00 2001 From: Richard Smith Date: Tue, 15 Sep 2026 23:11:58 +0000 Subject: [PATCH] Start to preserve type sugar in diagnostics. (#7768) Instead of always printing types as canonical, attempt to find a sugared type where possible, and include that type in the diagnostic. We can only do this when given the instruction whose type is being printed (`TypeOfInstId`) rather than the canonical type ID. Initial support here is intentionally minimal: just looking through calls to the callee's declared return type, and looking through pointer dereferences and corresponding pointer types, to build out the initial infrastructure. More cases can be added later; this degrades gracefully to using the canonical type if a better type can't be found. Assisted-by: Claude Opus 5 via Antigravity --- toolchain/check/diagnostic_emitter.cpp | 9 +- .../alias/preserve_in_type_printing.carbon | 28 ++ .../impl/fail_impl_bad_assoc_fn.carbon | 261 +++++++++--------- toolchain/language_server/handle_position.cpp | 14 +- toolchain/sem_ir/BUILD | 14 + toolchain/sem_ir/stringify.cpp | 5 + toolchain/sem_ir/stringify.h | 6 + toolchain/sem_ir/sugared_type.cpp | 209 ++++++++++++++ toolchain/sem_ir/sugared_type.h | 35 +++ 9 files changed, 435 insertions(+), 146 deletions(-) create mode 100644 toolchain/sem_ir/sugared_type.cpp create mode 100644 toolchain/sem_ir/sugared_type.h diff --git a/toolchain/check/diagnostic_emitter.cpp b/toolchain/check/diagnostic_emitter.cpp index 0c2070167fa6..49532d45c4cb 100644 --- a/toolchain/check/diagnostic_emitter.cpp +++ b/toolchain/check/diagnostic_emitter.cpp @@ -92,14 +92,7 @@ auto DiagnosticEmitter::ConvertArg(llvm::Any arg) const -> llvm::Any { if (!type_of_expr->inst_id.has_value()) { return ""; } - // TODO: Where possible, produce a better description of the type based on - // the expression. - return "`" + - StringifyConstantInst( - *sem_ir_, - sem_ir_->types().GetTypeInstId( - sem_ir_->insts().Get(type_of_expr->inst_id).type_id())) + - "`"; + return "`" + StringifyTypeOfInst(*sem_ir_, type_of_expr->inst_id) + "`"; } if (auto* expr = llvm::any_cast(&arg)) { return "`" + StringifyConstantInst(*sem_ir_, expr->inst_id) + "`"; diff --git a/toolchain/check/testdata/alias/preserve_in_type_printing.carbon b/toolchain/check/testdata/alias/preserve_in_type_printing.carbon index 1e9b5cc37d82..db6bdd6edb2d 100644 --- a/toolchain/check/testdata/alias/preserve_in_type_printing.carbon +++ b/toolchain/check/testdata/alias/preserve_in_type_printing.carbon @@ -51,3 +51,31 @@ fn H() -> const A* { return; } // CHECK:STDERR: ^~~~~~~~~~~~ // CHECK:STDERR: fn I() -> array(A, 42) { return; } + +// --- fail_alias_in_type_of_expr.carbon + +library "[[@TEST_NAME]]"; + +class C {} +alias A = C; + +fn MakePtr() -> A*; + +// The diagnostics below should describe the types of the expressions using the +// spelling `A` from the declaration of the callee, not the canonical `C`. + +fn F() { + // The type of a call is the declared return type of the callee. + // CHECK:STDERR: fail_alias_in_type_of_expr.carbon:[[@LINE+4]]:3: error: type `A*` does not support qualified expressions [QualifiedExprUnsupported] + // CHECK:STDERR: MakePtr().missing; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~ + // CHECK:STDERR: + MakePtr().missing; + + // The type of a dereference is the pointee type of the pointer's type. + // CHECK:STDERR: fail_alias_in_type_of_expr.carbon:[[@LINE+4]]:3: error: value of type `A` is not callable [CallToNonCallable] + // CHECK:STDERR: (*MakePtr())(); + // CHECK:STDERR: ^~~~~~~~~~~~~~ + // CHECK:STDERR: + (*MakePtr())(); +} diff --git a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon index 93aef73ec5e6..627ee600eca4 100644 --- a/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon +++ b/toolchain/check/testdata/impl/fail_impl_bad_assoc_fn.carbon @@ -163,13 +163,14 @@ class FDifferentImplicitParamType { class FDifferentReturnType { impl as J { - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+12]]:5: error: cannot implicitly convert expression of type `FDifferentReturnType` to `bool` [ConversionFailure] + // TODO: Include an "aka" in this diagnostic to explain that the type `Self` is `FDifferentReturnType`. + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+12]]:5: error: cannot implicitly convert expression of type `Self` to `bool` [ConversionFailure] // CHECK:STDERR: fn F(self: bool, b: bool) -> Self; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE+9]]:5: note: type `FDifferentReturnType` does not implement interface `Core.ImplicitAs(bool)` [MissingImplInMemberAccessInContext] // CHECK:STDERR: fn F(self: bool, b: bool) -> Self; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-85]]:15: note: while building thunk to match the signature of this function [ThunkSignature] + // CHECK:STDERR: fail_impl_bad_assoc_fn.carbon:[[@LINE-86]]:15: note: while building thunk to match the signature of this function [ThunkSignature] // CHECK:STDERR: interface J { fn F(self: bool, b: bool) -> bool; } // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: @@ -361,12 +362,12 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %pattern_type.b9f: type = pattern_type %FDifferentReturnType [concrete] // CHECK:STDOUT: %return.param_patt.f37: %pattern_type.b9f = out_param_pattern [concrete] // CHECK:STDOUT: %return.patt.e4f: %pattern_type.b9f = return_slot_pattern %return.param_patt.f37, %FDifferentReturnType [concrete] -// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.type.ff55f4.1: type = fn_type @FDifferentReturnType.as.J.impl.F.loc178_38.1 [concrete] +// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.type.ff55f4.1: type = fn_type @FDifferentReturnType.as.J.impl.F.loc179_38.1 [concrete] // CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.9725a5.1: %FDifferentReturnType.as.J.impl.F.type.ff55f4.1 = struct_value () [concrete] // CHECK:STDOUT: %J.facet.6a7: %J.type = facet_value %FDifferentReturnType, (%J.impl_witness.6a4) [concrete] // CHECK:STDOUT: %J.WithSelf.F.type.1a1: type = fn_type @J.WithSelf.F, @J.WithSelf(%J.facet.6a7) [concrete] // CHECK:STDOUT: %J.WithSelf.F.efe: %J.WithSelf.F.type.1a1 = struct_value () [concrete] -// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.type.ff55f4.2: type = fn_type @FDifferentReturnType.as.J.impl.F.loc178_38.2 [concrete] +// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.type.ff55f4.2: type = fn_type @FDifferentReturnType.as.J.impl.F.loc179_38.2 [concrete] // CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.9725a5.2: %FDifferentReturnType.as.J.impl.F.type.ff55f4.2 = struct_value () [concrete] // CHECK:STDOUT: %SelfNested.type: type = facet_type <@SelfNested> [concrete] // CHECK:STDOUT: %Self.e81: %SelfNested.type = symbolic_binding Self, 0 [symbolic] @@ -408,7 +409,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %pattern_type.3a0: type = pattern_type %array_type.291 [concrete] // CHECK:STDOUT: %return.param_patt.489: %pattern_type.3a0 = out_param_pattern [concrete] // CHECK:STDOUT: %return.patt.98a: %pattern_type.3a0 = return_slot_pattern %return.param_patt.489, %array_type.291 [concrete] -// CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.1: type = fn_type @SelfNestedBadParam.as.SelfNested.impl.F.loc195_87.1 [concrete] +// CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.1: type = fn_type @SelfNestedBadParam.as.SelfNested.impl.F.loc196_87.1 [concrete] // CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.5fd896.1: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.1 = struct_value () [concrete] // CHECK:STDOUT: %SelfNested.facet.d0d: %SelfNested.type = facet_value %SelfNestedBadParam, (%SelfNested.impl_witness.09d) [concrete] // CHECK:STDOUT: %SelfNested.WithSelf.F.type.398: type = fn_type @SelfNested.WithSelf.F, @SelfNested.WithSelf(%SelfNested.facet.d0d) [concrete] @@ -419,7 +420,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %pattern_type.94f: type = pattern_type %tuple.type.9ab [concrete] // CHECK:STDOUT: %x.param_patt.7b9: %pattern_type.94f = value_param_pattern [concrete] // CHECK:STDOUT: %x.patt.961: %pattern_type.94f = wrapper_binding_pattern x, %x.param_patt.7b9 [concrete] -// CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.2: type = fn_type @SelfNestedBadParam.as.SelfNested.impl.F.loc195_87.2 [concrete] +// CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.2: type = fn_type @SelfNestedBadParam.as.SelfNested.impl.F.loc196_87.2 [concrete] // CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.5fd896.2: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.2 = struct_value () [concrete] // CHECK:STDOUT: %ImplicitAs.type.914: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete] // CHECK:STDOUT: %ImplicitAs.assoc_type.e23: type = assoc_entity_type @ImplicitAs, @ImplicitAs(%i32) [concrete] @@ -434,7 +435,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %pattern_type.5c2: type = pattern_type %tuple.type.829 [concrete] // CHECK:STDOUT: %x.param_patt.7be: %pattern_type.5c2 = value_param_pattern [concrete] // CHECK:STDOUT: %x.patt.608: %pattern_type.5c2 = wrapper_binding_pattern x, %x.param_patt.7be [concrete] -// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.1: type = fn_type @SelfNestedBadReturnType.as.SelfNested.impl.F.loc211_112.1 [concrete] +// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.1: type = fn_type @SelfNestedBadReturnType.as.SelfNested.impl.F.loc212_112.1 [concrete] // CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.5a7d54.1: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.1 = struct_value () [concrete] // CHECK:STDOUT: %SelfNested.facet.e71: %SelfNested.type = facet_value %SelfNestedBadReturnType, (%SelfNested.impl_witness.849) [concrete] // CHECK:STDOUT: %SelfNested.WithSelf.F.type.20c: type = fn_type @SelfNested.WithSelf.F, @SelfNested.WithSelf(%SelfNested.facet.e71) [concrete] @@ -444,7 +445,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %pattern_type.f0d: type = pattern_type %array_type.a08 [concrete] // CHECK:STDOUT: %return.param_patt.039: %pattern_type.f0d = out_param_pattern [concrete] // CHECK:STDOUT: %return.patt.3c4: %pattern_type.f0d = return_slot_pattern %return.param_patt.039, %array_type.a08 [concrete] -// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.2: type = fn_type @SelfNestedBadReturnType.as.SelfNested.impl.F.loc211_112.2 [concrete] +// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.2: type = fn_type @SelfNestedBadReturnType.as.SelfNested.impl.F.loc212_112.2 [concrete] // CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.5a7d54.2: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.2 = struct_value () [concrete] // CHECK:STDOUT: } // CHECK:STDOUT: @@ -559,34 +560,34 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: // CHECK:STDOUT: !with Self: // CHECK:STDOUT: %SelfNested.WithSelf.F.decl: @SelfNested.WithSelf.%SelfNested.WithSelf.F.type (%SelfNested.WithSelf.F.type.702) = fn_decl @SelfNested.WithSelf.F [symbolic = @SelfNested.WithSelf.%SelfNested.WithSelf.F (constants.%SelfNested.WithSelf.F.eec)] { -// CHECK:STDOUT: %x.param_patt.loc183_9.1: @SelfNested.WithSelf.F.%pattern_type.loc183_9 (%pattern_type.60a) = value_param_pattern [symbolic = %x.param_patt.loc183_9.2 (constants.%x.param_patt.e85)] -// CHECK:STDOUT: %x.patt.loc183_9.1: @SelfNested.WithSelf.F.%pattern_type.loc183_9 (%pattern_type.60a) = wrapper_binding_pattern x, %x.param_patt.loc183_9.1 [symbolic = %x.patt.loc183_9.2 (constants.%x.patt.6af)] -// CHECK:STDOUT: %return.param_patt.loc183_57.1: @SelfNested.WithSelf.F.%pattern_type.loc183_57 (%pattern_type.2ab) = out_param_pattern [symbolic = %return.param_patt.loc183_57.2 (constants.%return.param_patt.439)] -// CHECK:STDOUT: %return.patt.loc183_41.1: @SelfNested.WithSelf.F.%pattern_type.loc183_57 (%pattern_type.2ab) = return_slot_pattern %return.param_patt.loc183_57.1, %array_type.loc183_57.2 [symbolic = %return.patt.loc183_41.2 (constants.%return.patt.869)] +// CHECK:STDOUT: %x.param_patt.loc184_9.1: @SelfNested.WithSelf.F.%pattern_type.loc184_9 (%pattern_type.60a) = value_param_pattern [symbolic = %x.param_patt.loc184_9.2 (constants.%x.param_patt.e85)] +// CHECK:STDOUT: %x.patt.loc184_9.1: @SelfNested.WithSelf.F.%pattern_type.loc184_9 (%pattern_type.60a) = wrapper_binding_pattern x, %x.param_patt.loc184_9.1 [symbolic = %x.patt.loc184_9.2 (constants.%x.patt.6af)] +// CHECK:STDOUT: %return.param_patt.loc184_57.1: @SelfNested.WithSelf.F.%pattern_type.loc184_57 (%pattern_type.2ab) = out_param_pattern [symbolic = %return.param_patt.loc184_57.2 (constants.%return.param_patt.439)] +// CHECK:STDOUT: %return.patt.loc184_41.1: @SelfNested.WithSelf.F.%pattern_type.loc184_57 (%pattern_type.2ab) = return_slot_pattern %return.param_patt.loc184_57.1, %array_type.loc184_57.2 [symbolic = %return.patt.loc184_41.2 (constants.%return.patt.869)] // CHECK:STDOUT: } { -// CHECK:STDOUT: %Self.ref.loc183_50: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.e81)] +// CHECK:STDOUT: %Self.ref.loc184_50: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.e81)] // CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4] -// CHECK:STDOUT: %Self.as_type.loc183_50: type = facet_access_type %Self.ref.loc183_50 [symbolic = %Self.as_type.loc183_16.1 (constants.%Self.as_type.8ab)] -// CHECK:STDOUT: %.loc183_50: type = converted %Self.ref.loc183_50, %Self.as_type.loc183_50 [symbolic = %Self.as_type.loc183_16.1 (constants.%Self.as_type.8ab)] -// CHECK:STDOUT: %array_type.loc183_57.2: type = array_type %int_4, %.loc183_50 [symbolic = %array_type.loc183_57.1 (constants.%array_type.4e4)] -// CHECK:STDOUT: %.loc183_57.2: Core.Form = init_form %array_type.loc183_57.2 [symbolic = %.loc183_57.1 (constants.%.f45)] +// CHECK:STDOUT: %Self.as_type.loc184_50: type = facet_access_type %Self.ref.loc184_50 [symbolic = %Self.as_type.loc184_16.1 (constants.%Self.as_type.8ab)] +// CHECK:STDOUT: %.loc184_50: type = converted %Self.ref.loc184_50, %Self.as_type.loc184_50 [symbolic = %Self.as_type.loc184_16.1 (constants.%Self.as_type.8ab)] +// CHECK:STDOUT: %array_type.loc184_57.2: type = array_type %int_4, %.loc184_50 [symbolic = %array_type.loc184_57.1 (constants.%array_type.4e4)] +// CHECK:STDOUT: %.loc184_57.2: Core.Form = init_form %array_type.loc184_57.2 [symbolic = %.loc184_57.1 (constants.%.f45)] // CHECK:STDOUT: %x.param: @SelfNested.WithSelf.F.%tuple.type (%tuple.type.c49) = value_param call_param0 -// CHECK:STDOUT: %.loc183_38.1: type = splice_block %.loc183_38.3 [symbolic = %tuple.type (constants.%tuple.type.c49)] { -// CHECK:STDOUT: %Self.ref.loc183_12: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.e81)] -// CHECK:STDOUT: %Self.as_type.loc183_16.2: type = facet_access_type %Self.ref.loc183_12 [symbolic = %Self.as_type.loc183_16.1 (constants.%Self.as_type.8ab)] -// CHECK:STDOUT: %.loc183_16: type = converted %Self.ref.loc183_12, %Self.as_type.loc183_16.2 [symbolic = %Self.as_type.loc183_16.1 (constants.%Self.as_type.8ab)] -// CHECK:STDOUT: %ptr.loc183_16.2: type = ptr_type %.loc183_16 [symbolic = %ptr.loc183_16.1 (constants.%ptr.a16)] -// CHECK:STDOUT: %Self.ref.loc183_24: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.e81)] -// CHECK:STDOUT: %Self.as_type.loc183_24: type = facet_access_type %Self.ref.loc183_24 [symbolic = %Self.as_type.loc183_16.1 (constants.%Self.as_type.8ab)] -// CHECK:STDOUT: %.loc183_24: type = converted %Self.ref.loc183_24, %Self.as_type.loc183_24 [symbolic = %Self.as_type.loc183_16.1 (constants.%Self.as_type.8ab)] +// CHECK:STDOUT: %.loc184_38.1: type = splice_block %.loc184_38.3 [symbolic = %tuple.type (constants.%tuple.type.c49)] { +// CHECK:STDOUT: %Self.ref.loc184_12: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.e81)] +// CHECK:STDOUT: %Self.as_type.loc184_16.2: type = facet_access_type %Self.ref.loc184_12 [symbolic = %Self.as_type.loc184_16.1 (constants.%Self.as_type.8ab)] +// CHECK:STDOUT: %.loc184_16: type = converted %Self.ref.loc184_12, %Self.as_type.loc184_16.2 [symbolic = %Self.as_type.loc184_16.1 (constants.%Self.as_type.8ab)] +// CHECK:STDOUT: %ptr.loc184_16.2: type = ptr_type %.loc184_16 [symbolic = %ptr.loc184_16.1 (constants.%ptr.a16)] +// CHECK:STDOUT: %Self.ref.loc184_24: %SelfNested.type = name_ref Self, @SelfNested.%Self [symbolic = %Self (constants.%Self.e81)] +// CHECK:STDOUT: %Self.as_type.loc184_24: type = facet_access_type %Self.ref.loc184_24 [symbolic = %Self.as_type.loc184_16.1 (constants.%Self.as_type.8ab)] +// CHECK:STDOUT: %.loc184_24: type = converted %Self.ref.loc184_24, %Self.as_type.loc184_24 [symbolic = %Self.as_type.loc184_16.1 (constants.%Self.as_type.8ab)] // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %struct_type.x.y.loc183_37.2: type = struct_type {.x: @SelfNested.WithSelf.F.%Self.as_type.loc183_16.1 (%Self.as_type.8ab), .y: %i32} [symbolic = %struct_type.x.y.loc183_37.1 (constants.%struct_type.x.y.4c5)] -// CHECK:STDOUT: %.loc183_38.2: %tuple.type.24b = tuple_literal (%ptr.loc183_16.2, %struct_type.x.y.loc183_37.2) [symbolic = %tuple (constants.%tuple.b6a)] -// CHECK:STDOUT: %.loc183_38.3: type = converted %.loc183_38.2, constants.%tuple.type.c49 [symbolic = %tuple.type (constants.%tuple.type.c49)] +// CHECK:STDOUT: %struct_type.x.y.loc184_37.2: type = struct_type {.x: @SelfNested.WithSelf.F.%Self.as_type.loc184_16.1 (%Self.as_type.8ab), .y: %i32} [symbolic = %struct_type.x.y.loc184_37.1 (constants.%struct_type.x.y.4c5)] +// CHECK:STDOUT: %.loc184_38.2: %tuple.type.24b = tuple_literal (%ptr.loc184_16.2, %struct_type.x.y.loc184_37.2) [symbolic = %tuple (constants.%tuple.b6a)] +// CHECK:STDOUT: %.loc184_38.3: type = converted %.loc184_38.2, constants.%tuple.type.c49 [symbolic = %tuple.type (constants.%tuple.type.c49)] // CHECK:STDOUT: } // CHECK:STDOUT: %x: @SelfNested.WithSelf.F.%tuple.type (%tuple.type.c49) = wrapper_binding x, %x.param -// CHECK:STDOUT: %return.param: ref @SelfNested.WithSelf.F.%array_type.loc183_57.1 (%array_type.4e4) = out_param call_param1 -// CHECK:STDOUT: %return: ref @SelfNested.WithSelf.F.%array_type.loc183_57.1 (%array_type.4e4) = return_slot %return.param +// CHECK:STDOUT: %return.param: ref @SelfNested.WithSelf.F.%array_type.loc184_57.1 (%array_type.4e4) = out_param call_param1 +// CHECK:STDOUT: %return: ref @SelfNested.WithSelf.F.%array_type.loc184_57.1 (%array_type.4e4) = return_slot %return.param // CHECK:STDOUT: } // CHECK:STDOUT: %assoc0: %SelfNested.assoc_type = assoc_entity element0, %SelfNested.WithSelf.F.decl [concrete = constants.%assoc0.219] // CHECK:STDOUT: @@ -888,7 +889,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @FDifferentReturnType.as.J.impl: %Self.ref as %J.ref { -// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.decl.loc178_38.1: %FDifferentReturnType.as.J.impl.F.type.ff55f4.1 = fn_decl @FDifferentReturnType.as.J.impl.F.loc178_38.1 [concrete = constants.%FDifferentReturnType.as.J.impl.F.9725a5.1] { +// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.decl.loc179_38.1: %FDifferentReturnType.as.J.impl.F.type.ff55f4.1 = fn_decl @FDifferentReturnType.as.J.impl.F.loc179_38.1 [concrete = constants.%FDifferentReturnType.as.J.impl.F.9725a5.1] { // CHECK:STDOUT: %self.param_patt: %pattern_type.831 = value_param_pattern [concrete = constants.%self.param_patt.210] // CHECK:STDOUT: %self.patt: %pattern_type.831 = wrapper_binding_pattern self, %self.param_patt [concrete = constants.%self.patt.3a9] // CHECK:STDOUT: %b.param_patt: %pattern_type.831 = value_param_pattern [concrete = constants.%b.param_patt.792] @@ -897,19 +898,19 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %return.patt: %pattern_type.b9f = return_slot_pattern %return.param_patt, %Self.ref [concrete = constants.%return.patt.e4f] // CHECK:STDOUT: } { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%FDifferentReturnType [concrete = constants.%FDifferentReturnType] -// CHECK:STDOUT: %.loc178_34: Core.Form = init_form %Self.ref [concrete = constants.%.1f5] +// CHECK:STDOUT: %.loc179_34: Core.Form = init_form %Self.ref [concrete = constants.%.1f5] // CHECK:STDOUT: %self.param: bool = value_param call_param0 -// CHECK:STDOUT: %.loc178_16: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %.loc179_16: type = type_literal bool [concrete = bool] // CHECK:STDOUT: %self: bool = wrapper_binding self, %self.param // CHECK:STDOUT: %b.param: bool = value_param call_param1 -// CHECK:STDOUT: %.loc178_25: type = type_literal bool [concrete = bool] +// CHECK:STDOUT: %.loc179_25: type = type_literal bool [concrete = bool] // CHECK:STDOUT: %b: bool = wrapper_binding b, %b.param // CHECK:STDOUT: %return.param: ref %FDifferentReturnType = out_param call_param2 // CHECK:STDOUT: %return: ref %FDifferentReturnType = return_slot %return.param // CHECK:STDOUT: } // CHECK:STDOUT: %.loc87_44.1: type = specific_constant @J.WithSelf.F.%.loc87_44.1, @J.WithSelf.F(constants.%J.facet.6a7) [concrete = bool] // CHECK:STDOUT: %.loc87_44.2: Core.Form = specific_constant @J.WithSelf.F.%.loc87_44.2, @J.WithSelf.F(constants.%J.facet.6a7) [concrete = constants.%.f34] -// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.decl.loc178_38.2: %FDifferentReturnType.as.J.impl.F.type.ff55f4.2 = fn_decl @FDifferentReturnType.as.J.impl.F.loc178_38.2 [concrete = constants.%FDifferentReturnType.as.J.impl.F.9725a5.2] { +// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.decl.loc179_38.2: %FDifferentReturnType.as.J.impl.F.type.ff55f4.2 = fn_decl @FDifferentReturnType.as.J.impl.F.loc179_38.2 [concrete = constants.%FDifferentReturnType.as.J.impl.F.9725a5.2] { // CHECK:STDOUT: %.1: %pattern_type.831 = specific_constant constants.%self.param_patt.210, @J.WithSelf.F(constants.%J.facet.6a7) [concrete = constants.%self.param_patt.210] // CHECK:STDOUT: %self.patt: %pattern_type.831 = wrapper_binding_pattern self, %.1 [concrete = constants.%self.patt.3a9] // CHECK:STDOUT: %.2: %pattern_type.831 = specific_constant constants.%b.param_patt.792, @J.WithSelf.F(constants.%J.facet.6a7) [concrete = constants.%b.param_patt.792] @@ -923,43 +924,43 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %return.param: ref bool = out_param call_param2 // CHECK:STDOUT: %return: ref bool = return_slot %return.param // CHECK:STDOUT: } -// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (%FDifferentReturnType.as.J.impl.F.decl.loc178_38.2), @FDifferentReturnType.as.J.impl [concrete] +// CHECK:STDOUT: %J.impl_witness_table = impl_witness_table (%FDifferentReturnType.as.J.impl.F.decl.loc179_38.2), @FDifferentReturnType.as.J.impl [concrete] // CHECK:STDOUT: %J.impl_witness: = impl_witness %J.impl_witness_table [concrete = constants.%J.impl_witness.6a4] // CHECK:STDOUT: // CHECK:STDOUT: !members: -// CHECK:STDOUT: .F = %FDifferentReturnType.as.J.impl.F.decl.loc178_38.1 +// CHECK:STDOUT: .F = %FDifferentReturnType.as.J.impl.F.decl.loc179_38.1 // CHECK:STDOUT: extend %J.ref // CHECK:STDOUT: witness = %J.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @SelfNestedBadParam.as.SelfNested.impl: %Self.ref as %SelfNested.ref { -// CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc195_87.1: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.1 = fn_decl @SelfNestedBadParam.as.SelfNested.impl.F.loc195_87.1 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.5fd896.1] { +// CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc196_87.1: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.1 = fn_decl @SelfNestedBadParam.as.SelfNested.impl.F.loc196_87.1 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.5fd896.1] { // CHECK:STDOUT: %x.param_patt: %pattern_type.a68 = value_param_pattern [concrete = constants.%x.param_patt.140] // CHECK:STDOUT: %x.patt: %pattern_type.a68 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt.870] // CHECK:STDOUT: %return.param_patt: %pattern_type.3a0 = out_param_pattern [concrete = constants.%return.param_patt.489] // CHECK:STDOUT: %return.patt: %pattern_type.3a0 = return_slot_pattern %return.param_patt, %array_type [concrete = constants.%return.patt.98a] // CHECK:STDOUT: } { -// CHECK:STDOUT: %SelfNestedBadParam.ref.loc195_65: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] +// CHECK:STDOUT: %SelfNestedBadParam.ref.loc196_65: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] // CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4] -// CHECK:STDOUT: %array_type: type = array_type %int_4, %SelfNestedBadParam.ref.loc195_65 [concrete = constants.%array_type.291] -// CHECK:STDOUT: %.loc195_86: Core.Form = init_form %array_type [concrete = constants.%.cc2] +// CHECK:STDOUT: %array_type: type = array_type %int_4, %SelfNestedBadParam.ref.loc196_65 [concrete = constants.%array_type.291] +// CHECK:STDOUT: %.loc196_86: Core.Form = init_form %array_type [concrete = constants.%.cc2] // CHECK:STDOUT: %x.param: %tuple.type.e57 = value_param call_param0 -// CHECK:STDOUT: %.loc195_53.1: type = splice_block %.loc195_53.3 [concrete = constants.%tuple.type.e57] { -// CHECK:STDOUT: %SelfNestedBadParam.ref.loc195_14: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] -// CHECK:STDOUT: %ptr: type = ptr_type %SelfNestedBadParam.ref.loc195_14 [concrete = constants.%ptr.52e] -// CHECK:STDOUT: %i32.loc195_40: type = type_literal constants.%i32 [concrete = constants.%i32] -// CHECK:STDOUT: %i32.loc195_49: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %.loc196_53.1: type = splice_block %.loc196_53.3 [concrete = constants.%tuple.type.e57] { +// CHECK:STDOUT: %SelfNestedBadParam.ref.loc196_14: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] +// CHECK:STDOUT: %ptr: type = ptr_type %SelfNestedBadParam.ref.loc196_14 [concrete = constants.%ptr.52e] +// CHECK:STDOUT: %i32.loc196_40: type = type_literal constants.%i32 [concrete = constants.%i32] +// CHECK:STDOUT: %i32.loc196_49: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %struct_type.x.y: type = struct_type {.x: %i32, .y: %i32} [concrete = constants.%struct_type.x.y.fb8] -// CHECK:STDOUT: %.loc195_53.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) [concrete = constants.%tuple.991] -// CHECK:STDOUT: %.loc195_53.3: type = converted %.loc195_53.2, constants.%tuple.type.e57 [concrete = constants.%tuple.type.e57] +// CHECK:STDOUT: %.loc196_53.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) [concrete = constants.%tuple.991] +// CHECK:STDOUT: %.loc196_53.3: type = converted %.loc196_53.2, constants.%tuple.type.e57 [concrete = constants.%tuple.type.e57] // CHECK:STDOUT: } // CHECK:STDOUT: %x: %tuple.type.e57 = wrapper_binding x, %x.param // CHECK:STDOUT: %return.param: ref %array_type.291 = out_param call_param1 // CHECK:STDOUT: %return: ref %array_type.291 = return_slot %return.param // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc183_57.1: type = specific_constant @SelfNested.WithSelf.F.%array_type.loc183_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d) [concrete = constants.%array_type.291] -// CHECK:STDOUT: %.loc183_57.2: Core.Form = specific_constant @SelfNested.WithSelf.F.%.loc183_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d) [concrete = constants.%.cc2] -// CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc195_87.2: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.2 = fn_decl @SelfNestedBadParam.as.SelfNested.impl.F.loc195_87.2 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.5fd896.2] { +// CHECK:STDOUT: %.loc184_57.1: type = specific_constant @SelfNested.WithSelf.F.%array_type.loc184_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d) [concrete = constants.%array_type.291] +// CHECK:STDOUT: %.loc184_57.2: Core.Form = specific_constant @SelfNested.WithSelf.F.%.loc184_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d) [concrete = constants.%.cc2] +// CHECK:STDOUT: %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc196_87.2: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.2 = fn_decl @SelfNestedBadParam.as.SelfNested.impl.F.loc196_87.2 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.5fd896.2] { // CHECK:STDOUT: %.1: %pattern_type.94f = specific_constant constants.%x.param_patt.7b9, @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d) [concrete = constants.%x.param_patt.7b9] // CHECK:STDOUT: %x.patt: %pattern_type.94f = wrapper_binding_pattern x, %.1 [concrete = constants.%x.patt.961] // CHECK:STDOUT: %.2: %pattern_type.3a0 = specific_constant constants.%return.patt.98a, @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d) [concrete = constants.%return.patt.98a] @@ -969,18 +970,18 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %return.param: ref %array_type.291 = out_param call_param1 // CHECK:STDOUT: %return: ref %array_type.291 = return_slot %return.param // CHECK:STDOUT: } -// CHECK:STDOUT: %SelfNested.impl_witness_table = impl_witness_table (%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc195_87.2), @SelfNestedBadParam.as.SelfNested.impl [concrete] +// CHECK:STDOUT: %SelfNested.impl_witness_table = impl_witness_table (%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc196_87.2), @SelfNestedBadParam.as.SelfNested.impl [concrete] // CHECK:STDOUT: %SelfNested.impl_witness: = impl_witness %SelfNested.impl_witness_table [concrete = constants.%SelfNested.impl_witness.09d] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .SelfNestedBadParam = -// CHECK:STDOUT: .F = %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc195_87.1 +// CHECK:STDOUT: .F = %SelfNestedBadParam.as.SelfNested.impl.F.decl.loc196_87.1 // CHECK:STDOUT: extend %SelfNested.ref // CHECK:STDOUT: witness = %SelfNested.impl_witness // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: impl @SelfNestedBadReturnType.as.SelfNested.impl: %Self.ref as %SelfNested.ref { -// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc211_112.1: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.1 = fn_decl @SelfNestedBadReturnType.as.SelfNested.impl.F.loc211_112.1 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.5a7d54.1] { +// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc212_112.1: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.1 = fn_decl @SelfNestedBadReturnType.as.SelfNested.impl.F.loc212_112.1 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.5a7d54.1] { // CHECK:STDOUT: %x.param_patt: %pattern_type.5c2 = value_param_pattern [concrete = constants.%x.param_patt.7be] // CHECK:STDOUT: %x.patt: %pattern_type.5c2 = wrapper_binding_pattern x, %x.param_patt [concrete = constants.%x.patt.608] // CHECK:STDOUT: %return.param_patt: %pattern_type.3a0 = out_param_pattern [concrete = constants.%return.param_patt.489] @@ -989,24 +990,24 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %SelfNestedBadParam.ref: type = name_ref SelfNestedBadParam, file.%SelfNestedBadParam.decl [concrete = constants.%SelfNestedBadParam] // CHECK:STDOUT: %int_4: Core.IntLiteral = int_value 4 [concrete = constants.%int_4] // CHECK:STDOUT: %array_type: type = array_type %int_4, %SelfNestedBadParam.ref [concrete = constants.%array_type.291] -// CHECK:STDOUT: %.loc211_111: Core.Form = init_form %array_type [concrete = constants.%.cc2] +// CHECK:STDOUT: %.loc212_111: Core.Form = init_form %array_type [concrete = constants.%.cc2] // CHECK:STDOUT: %x.param: %tuple.type.829 = value_param call_param0 -// CHECK:STDOUT: %.loc211_78.1: type = splice_block %.loc211_78.3 [concrete = constants.%tuple.type.829] { -// CHECK:STDOUT: %SelfNestedBadReturnType.ref.loc211_14: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType] -// CHECK:STDOUT: %ptr: type = ptr_type %SelfNestedBadReturnType.ref.loc211_14 [concrete = constants.%ptr.f55] -// CHECK:STDOUT: %SelfNestedBadReturnType.ref.loc211_45: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType] +// CHECK:STDOUT: %.loc212_78.1: type = splice_block %.loc212_78.3 [concrete = constants.%tuple.type.829] { +// CHECK:STDOUT: %SelfNestedBadReturnType.ref.loc212_14: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType] +// CHECK:STDOUT: %ptr: type = ptr_type %SelfNestedBadReturnType.ref.loc212_14 [concrete = constants.%ptr.f55] +// CHECK:STDOUT: %SelfNestedBadReturnType.ref.loc212_45: type = name_ref SelfNestedBadReturnType, file.%SelfNestedBadReturnType.decl [concrete = constants.%SelfNestedBadReturnType] // CHECK:STDOUT: %i32: type = type_literal constants.%i32 [concrete = constants.%i32] // CHECK:STDOUT: %struct_type.x.y: type = struct_type {.x: %SelfNestedBadReturnType, .y: %i32} [concrete = constants.%struct_type.x.y.f6a] -// CHECK:STDOUT: %.loc211_78.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) [concrete = constants.%tuple.96d] -// CHECK:STDOUT: %.loc211_78.3: type = converted %.loc211_78.2, constants.%tuple.type.829 [concrete = constants.%tuple.type.829] +// CHECK:STDOUT: %.loc212_78.2: %tuple.type.24b = tuple_literal (%ptr, %struct_type.x.y) [concrete = constants.%tuple.96d] +// CHECK:STDOUT: %.loc212_78.3: type = converted %.loc212_78.2, constants.%tuple.type.829 [concrete = constants.%tuple.type.829] // CHECK:STDOUT: } // CHECK:STDOUT: %x: %tuple.type.829 = wrapper_binding x, %x.param // CHECK:STDOUT: %return.param: ref %array_type.291 = out_param call_param1 // CHECK:STDOUT: %return: ref %array_type.291 = return_slot %return.param // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc183_57.1: type = specific_constant @SelfNested.WithSelf.F.%array_type.loc183_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71) [concrete = constants.%array_type.a08] -// CHECK:STDOUT: %.loc183_57.2: Core.Form = specific_constant @SelfNested.WithSelf.F.%.loc183_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71) [concrete = constants.%.442] -// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc211_112.2: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.2 = fn_decl @SelfNestedBadReturnType.as.SelfNested.impl.F.loc211_112.2 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.5a7d54.2] { +// CHECK:STDOUT: %.loc184_57.1: type = specific_constant @SelfNested.WithSelf.F.%array_type.loc184_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71) [concrete = constants.%array_type.a08] +// CHECK:STDOUT: %.loc184_57.2: Core.Form = specific_constant @SelfNested.WithSelf.F.%.loc184_57.2, @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71) [concrete = constants.%.442] +// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc212_112.2: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.2 = fn_decl @SelfNestedBadReturnType.as.SelfNested.impl.F.loc212_112.2 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.5a7d54.2] { // CHECK:STDOUT: %.1: %pattern_type.5c2 = specific_constant constants.%x.param_patt.7be, @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71) [concrete = constants.%x.param_patt.7be] // CHECK:STDOUT: %x.patt: %pattern_type.5c2 = wrapper_binding_pattern x, %.1 [concrete = constants.%x.patt.608] // CHECK:STDOUT: %.2: %pattern_type.f0d = specific_constant constants.%return.patt.3c4, @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71) [concrete = constants.%return.patt.3c4] @@ -1016,13 +1017,13 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %return.param: ref %array_type.a08 = out_param call_param1 // CHECK:STDOUT: %return: ref %array_type.a08 = return_slot %return.param // CHECK:STDOUT: } -// CHECK:STDOUT: %SelfNested.impl_witness_table = impl_witness_table (%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc211_112.2), @SelfNestedBadReturnType.as.SelfNested.impl [concrete] +// CHECK:STDOUT: %SelfNested.impl_witness_table = impl_witness_table (%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc212_112.2), @SelfNestedBadReturnType.as.SelfNested.impl [concrete] // CHECK:STDOUT: %SelfNested.impl_witness: = impl_witness %SelfNested.impl_witness_table [concrete = constants.%SelfNested.impl_witness.849] // CHECK:STDOUT: // CHECK:STDOUT: !members: // CHECK:STDOUT: .SelfNestedBadReturnType = // CHECK:STDOUT: .SelfNestedBadParam = -// CHECK:STDOUT: .F = %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc211_112.1 +// CHECK:STDOUT: .F = %SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc212_112.1 // CHECK:STDOUT: extend %SelfNested.ref // CHECK:STDOUT: witness = %SelfNested.impl_witness // CHECK:STDOUT: } @@ -1188,7 +1189,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%SelfNestedBadParam [concrete = constants.%SelfNestedBadParam] // CHECK:STDOUT: %SelfNested.ref: type = name_ref SelfNested, file.%SelfNested.decl [concrete = constants.%SelfNested.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc187: = impl_self_witness @SelfNestedBadParam.as.SelfNested.impl.%Self.ref, @SelfNested [concrete = constants.%.83b] +// CHECK:STDOUT: %.loc188: = impl_self_witness @SelfNestedBadParam.as.SelfNested.impl.%Self.ref, @SelfNested [concrete = constants.%.83b] // CHECK:STDOUT: %complete_type: = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type // CHECK:STDOUT: @@ -1203,7 +1204,7 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%SelfNestedBadReturnType [concrete = constants.%SelfNestedBadReturnType] // CHECK:STDOUT: %SelfNested.ref: type = name_ref SelfNested, file.%SelfNested.decl [concrete = constants.%SelfNested.type] // CHECK:STDOUT: } -// CHECK:STDOUT: %.loc200: = impl_self_witness @SelfNestedBadReturnType.as.SelfNested.impl.%Self.ref, @SelfNested [concrete = constants.%.020] +// CHECK:STDOUT: %.loc201: = impl_self_witness @SelfNestedBadReturnType.as.SelfNested.impl.%Self.ref, @SelfNested [concrete = constants.%.020] // CHECK:STDOUT: %complete_type: = complete_type_witness constants.%empty_struct_type [concrete = constants.%complete_type.357] // CHECK:STDOUT: complete_type_witness = %complete_type // CHECK:STDOUT: @@ -1297,42 +1298,42 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: return %FDifferentImplicitParamType.as.J.impl.F.call // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @FDifferentReturnType.as.J.impl.F.loc178_38.1(%self.param: bool, %b.param: bool) -> out %return.param: %FDifferentReturnType; +// CHECK:STDOUT: fn @FDifferentReturnType.as.J.impl.F.loc179_38.1(%self.param: bool, %b.param: bool) -> out %return.param: %FDifferentReturnType; // CHECK:STDOUT: -// CHECK:STDOUT: fn @FDifferentReturnType.as.J.impl.F.loc178_38.2(%self.param: bool, %b.param: bool) -> out %return.param: bool [thunk @FDifferentReturnType.as.J.impl.%FDifferentReturnType.as.J.impl.F.decl.loc178_38.1 for @J.WithSelf.%J.WithSelf.F.decl, @J.WithSelf.F(constants.%J.facet.6a7)] { +// CHECK:STDOUT: fn @FDifferentReturnType.as.J.impl.F.loc179_38.2(%self.param: bool, %b.param: bool) -> out %return.param: bool [thunk @FDifferentReturnType.as.J.impl.%FDifferentReturnType.as.J.impl.F.decl.loc179_38.1 for @J.WithSelf.%J.WithSelf.F.decl, @J.WithSelf.F(constants.%J.facet.6a7)] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %F.ref: %FDifferentReturnType.as.J.impl.F.type.ff55f4.1 = name_ref F, @FDifferentReturnType.as.J.impl.%FDifferentReturnType.as.J.impl.F.decl.loc178_38.1 [concrete = constants.%FDifferentReturnType.as.J.impl.F.9725a5.1] +// CHECK:STDOUT: %F.ref: %FDifferentReturnType.as.J.impl.F.type.ff55f4.1 = name_ref F, @FDifferentReturnType.as.J.impl.%FDifferentReturnType.as.J.impl.F.decl.loc179_38.1 [concrete = constants.%FDifferentReturnType.as.J.impl.F.9725a5.1] // CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.bound: = bound_method %self.param, %F.ref -// CHECK:STDOUT: %.loc178_38.1: ref %FDifferentReturnType = temporary_storage -// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.call: init %FDifferentReturnType to %.loc178_38.1 = call %FDifferentReturnType.as.J.impl.F.bound(%self.param, %b.param) -// CHECK:STDOUT: %.loc178_38.2: bool = converted %FDifferentReturnType.as.J.impl.F.call, [concrete = ] +// CHECK:STDOUT: %.loc179_38.1: ref %FDifferentReturnType = temporary_storage +// CHECK:STDOUT: %FDifferentReturnType.as.J.impl.F.call: init %FDifferentReturnType to %.loc179_38.1 = call %FDifferentReturnType.as.J.impl.F.bound(%self.param, %b.param) +// CHECK:STDOUT: %.loc179_38.2: bool = converted %FDifferentReturnType.as.J.impl.F.call, [concrete = ] // CHECK:STDOUT: return // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: generic fn @SelfNested.WithSelf.F(@SelfNested.%Self: %SelfNested.type) { // CHECK:STDOUT: %Self: %SelfNested.type = symbolic_binding Self, 0 [symbolic = %Self (constants.%Self.e81)] -// CHECK:STDOUT: %Self.as_type.loc183_16.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc183_16.1 (constants.%Self.as_type.8ab)] -// CHECK:STDOUT: %ptr.loc183_16.1: type = ptr_type %Self.as_type.loc183_16.1 [symbolic = %ptr.loc183_16.1 (constants.%ptr.a16)] -// CHECK:STDOUT: %struct_type.x.y.loc183_37.1: type = struct_type {.x: @SelfNested.WithSelf.F.%Self.as_type.loc183_16.1 (%Self.as_type.8ab), .y: %i32} [symbolic = %struct_type.x.y.loc183_37.1 (constants.%struct_type.x.y.4c5)] -// CHECK:STDOUT: %tuple: %tuple.type.24b = tuple_value (%ptr.loc183_16.1, %struct_type.x.y.loc183_37.1) [symbolic = %tuple (constants.%tuple.b6a)] -// CHECK:STDOUT: %tuple.type: type = tuple_type (%ptr.loc183_16.1, %struct_type.x.y.loc183_37.1) [symbolic = %tuple.type (constants.%tuple.type.c49)] -// CHECK:STDOUT: %pattern_type.loc183_9: type = pattern_type %tuple.type [symbolic = %pattern_type.loc183_9 (constants.%pattern_type.60a)] -// CHECK:STDOUT: %x.param_patt.loc183_9.2: @SelfNested.WithSelf.F.%pattern_type.loc183_9 (%pattern_type.60a) = value_param_pattern [symbolic = %x.param_patt.loc183_9.2 (constants.%x.param_patt.e85)] -// CHECK:STDOUT: %x.patt.loc183_9.2: @SelfNested.WithSelf.F.%pattern_type.loc183_9 (%pattern_type.60a) = wrapper_binding_pattern x, %x.param_patt.loc183_9.2 [symbolic = %x.patt.loc183_9.2 (constants.%x.patt.6af)] -// CHECK:STDOUT: %array_type.loc183_57.1: type = array_type constants.%int_4, %Self.as_type.loc183_16.1 [symbolic = %array_type.loc183_57.1 (constants.%array_type.4e4)] -// CHECK:STDOUT: %.loc183_57.1: Core.Form = init_form %array_type.loc183_57.1 [symbolic = %.loc183_57.1 (constants.%.f45)] -// CHECK:STDOUT: %pattern_type.loc183_57: type = pattern_type %array_type.loc183_57.1 [symbolic = %pattern_type.loc183_57 (constants.%pattern_type.2ab)] -// CHECK:STDOUT: %return.param_patt.loc183_57.2: @SelfNested.WithSelf.F.%pattern_type.loc183_57 (%pattern_type.2ab) = out_param_pattern [symbolic = %return.param_patt.loc183_57.2 (constants.%return.param_patt.439)] -// CHECK:STDOUT: %return.patt.loc183_41.2: @SelfNested.WithSelf.F.%pattern_type.loc183_57 (%pattern_type.2ab) = return_slot_pattern %return.param_patt.loc183_57.2, %array_type.loc183_57.1 [symbolic = %return.patt.loc183_41.2 (constants.%return.patt.869)] +// CHECK:STDOUT: %Self.as_type.loc184_16.1: type = facet_access_type %Self [symbolic = %Self.as_type.loc184_16.1 (constants.%Self.as_type.8ab)] +// CHECK:STDOUT: %ptr.loc184_16.1: type = ptr_type %Self.as_type.loc184_16.1 [symbolic = %ptr.loc184_16.1 (constants.%ptr.a16)] +// CHECK:STDOUT: %struct_type.x.y.loc184_37.1: type = struct_type {.x: @SelfNested.WithSelf.F.%Self.as_type.loc184_16.1 (%Self.as_type.8ab), .y: %i32} [symbolic = %struct_type.x.y.loc184_37.1 (constants.%struct_type.x.y.4c5)] +// CHECK:STDOUT: %tuple: %tuple.type.24b = tuple_value (%ptr.loc184_16.1, %struct_type.x.y.loc184_37.1) [symbolic = %tuple (constants.%tuple.b6a)] +// CHECK:STDOUT: %tuple.type: type = tuple_type (%ptr.loc184_16.1, %struct_type.x.y.loc184_37.1) [symbolic = %tuple.type (constants.%tuple.type.c49)] +// CHECK:STDOUT: %pattern_type.loc184_9: type = pattern_type %tuple.type [symbolic = %pattern_type.loc184_9 (constants.%pattern_type.60a)] +// CHECK:STDOUT: %x.param_patt.loc184_9.2: @SelfNested.WithSelf.F.%pattern_type.loc184_9 (%pattern_type.60a) = value_param_pattern [symbolic = %x.param_patt.loc184_9.2 (constants.%x.param_patt.e85)] +// CHECK:STDOUT: %x.patt.loc184_9.2: @SelfNested.WithSelf.F.%pattern_type.loc184_9 (%pattern_type.60a) = wrapper_binding_pattern x, %x.param_patt.loc184_9.2 [symbolic = %x.patt.loc184_9.2 (constants.%x.patt.6af)] +// CHECK:STDOUT: %array_type.loc184_57.1: type = array_type constants.%int_4, %Self.as_type.loc184_16.1 [symbolic = %array_type.loc184_57.1 (constants.%array_type.4e4)] +// CHECK:STDOUT: %.loc184_57.1: Core.Form = init_form %array_type.loc184_57.1 [symbolic = %.loc184_57.1 (constants.%.f45)] +// CHECK:STDOUT: %pattern_type.loc184_57: type = pattern_type %array_type.loc184_57.1 [symbolic = %pattern_type.loc184_57 (constants.%pattern_type.2ab)] +// CHECK:STDOUT: %return.param_patt.loc184_57.2: @SelfNested.WithSelf.F.%pattern_type.loc184_57 (%pattern_type.2ab) = out_param_pattern [symbolic = %return.param_patt.loc184_57.2 (constants.%return.param_patt.439)] +// CHECK:STDOUT: %return.patt.loc184_41.2: @SelfNested.WithSelf.F.%pattern_type.loc184_57 (%pattern_type.2ab) = return_slot_pattern %return.param_patt.loc184_57.2, %array_type.loc184_57.1 [symbolic = %return.patt.loc184_41.2 (constants.%return.patt.869)] // CHECK:STDOUT: -// CHECK:STDOUT: fn(%x.param: @SelfNested.WithSelf.F.%tuple.type (%tuple.type.c49)) -> out %return.param: @SelfNested.WithSelf.F.%array_type.loc183_57.1 (%array_type.4e4); +// CHECK:STDOUT: fn(%x.param: @SelfNested.WithSelf.F.%tuple.type (%tuple.type.c49)) -> out %return.param: @SelfNested.WithSelf.F.%array_type.loc184_57.1 (%array_type.4e4); // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @SelfNestedBadParam.as.SelfNested.impl.F.loc195_87.1(%x.param: %tuple.type.e57) -> out %return.param: %array_type.291; +// CHECK:STDOUT: fn @SelfNestedBadParam.as.SelfNested.impl.F.loc196_87.1(%x.param: %tuple.type.e57) -> out %return.param: %array_type.291; // CHECK:STDOUT: -// CHECK:STDOUT: fn @SelfNestedBadParam.as.SelfNested.impl.F.loc195_87.2(%x.param: %tuple.type.9ab) -> out %return.param: %array_type.291 [thunk @SelfNestedBadParam.as.SelfNested.impl.%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc195_87.1 for @SelfNested.WithSelf.%SelfNested.WithSelf.F.decl, @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d)] { +// CHECK:STDOUT: fn @SelfNestedBadParam.as.SelfNested.impl.F.loc196_87.2(%x.param: %tuple.type.9ab) -> out %return.param: %array_type.291 [thunk @SelfNestedBadParam.as.SelfNested.impl.%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc196_87.1 for @SelfNested.WithSelf.%SelfNested.WithSelf.F.decl, @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d)] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %F.ref: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.1 = name_ref F, @SelfNestedBadParam.as.SelfNested.impl.%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc195_87.1 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.5fd896.1] +// CHECK:STDOUT: %F.ref: %SelfNestedBadParam.as.SelfNested.impl.F.type.4325e7.1 = name_ref F, @SelfNestedBadParam.as.SelfNested.impl.%SelfNestedBadParam.as.SelfNested.impl.F.decl.loc196_87.1 [concrete = constants.%SelfNestedBadParam.as.SelfNested.impl.F.5fd896.1] // CHECK:STDOUT: %.3: ref %array_type.291 = splice_block %return.param {} // CHECK:STDOUT: %tuple.elem0: %ptr.52e = tuple_access %x.param, element0 // CHECK:STDOUT: %tuple.elem1: %struct_type.x.y.da2 = tuple_access %x.param, element1 @@ -1345,14 +1346,14 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: return %SelfNestedBadParam.as.SelfNested.impl.F.call to %return.param // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: fn @SelfNestedBadReturnType.as.SelfNested.impl.F.loc211_112.1(%x.param: %tuple.type.829) -> out %return.param: %array_type.291; +// CHECK:STDOUT: fn @SelfNestedBadReturnType.as.SelfNested.impl.F.loc212_112.1(%x.param: %tuple.type.829) -> out %return.param: %array_type.291; // CHECK:STDOUT: -// CHECK:STDOUT: fn @SelfNestedBadReturnType.as.SelfNested.impl.F.loc211_112.2(%x.param: %tuple.type.829) -> out %return.param: %array_type.a08 [thunk @SelfNestedBadReturnType.as.SelfNested.impl.%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc211_112.1 for @SelfNested.WithSelf.%SelfNested.WithSelf.F.decl, @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71)] { +// CHECK:STDOUT: fn @SelfNestedBadReturnType.as.SelfNested.impl.F.loc212_112.2(%x.param: %tuple.type.829) -> out %return.param: %array_type.a08 [thunk @SelfNestedBadReturnType.as.SelfNested.impl.%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc212_112.1 for @SelfNested.WithSelf.%SelfNested.WithSelf.F.decl, @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71)] { // CHECK:STDOUT: !entry: -// CHECK:STDOUT: %F.ref: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.1 = name_ref F, @SelfNestedBadReturnType.as.SelfNested.impl.%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc211_112.1 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.5a7d54.1] -// CHECK:STDOUT: %.loc211_112.1: ref %array_type.291 = temporary_storage -// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.call: init %array_type.291 to %.loc211_112.1 = call %F.ref(%x.param) -// CHECK:STDOUT: %.loc211_112.2: %array_type.a08 = converted %SelfNestedBadReturnType.as.SelfNested.impl.F.call, [concrete = ] +// CHECK:STDOUT: %F.ref: %SelfNestedBadReturnType.as.SelfNested.impl.F.type.1cbabe.1 = name_ref F, @SelfNestedBadReturnType.as.SelfNested.impl.%SelfNestedBadReturnType.as.SelfNested.impl.F.decl.loc212_112.1 [concrete = constants.%SelfNestedBadReturnType.as.SelfNested.impl.F.5a7d54.1] +// CHECK:STDOUT: %.loc212_112.1: ref %array_type.291 = temporary_storage +// CHECK:STDOUT: %SelfNestedBadReturnType.as.SelfNested.impl.F.call: init %array_type.291 to %.loc212_112.1 = call %F.ref(%x.param) +// CHECK:STDOUT: %.loc212_112.2: %array_type.a08 = converted %SelfNestedBadReturnType.as.SelfNested.impl.F.call, [concrete = ] // CHECK:STDOUT: return to %return.param // CHECK:STDOUT: } // CHECK:STDOUT: @@ -1478,19 +1479,19 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: // CHECK:STDOUT: specific @SelfNested.WithSelf.F(constants.%Self.e81) { // CHECK:STDOUT: %Self => constants.%Self.e81 -// CHECK:STDOUT: %Self.as_type.loc183_16.1 => constants.%Self.as_type.8ab -// CHECK:STDOUT: %ptr.loc183_16.1 => constants.%ptr.a16 -// CHECK:STDOUT: %struct_type.x.y.loc183_37.1 => constants.%struct_type.x.y.4c5 +// CHECK:STDOUT: %Self.as_type.loc184_16.1 => constants.%Self.as_type.8ab +// CHECK:STDOUT: %ptr.loc184_16.1 => constants.%ptr.a16 +// CHECK:STDOUT: %struct_type.x.y.loc184_37.1 => constants.%struct_type.x.y.4c5 // CHECK:STDOUT: %tuple => constants.%tuple.b6a // CHECK:STDOUT: %tuple.type => constants.%tuple.type.c49 -// CHECK:STDOUT: %pattern_type.loc183_9 => constants.%pattern_type.60a -// CHECK:STDOUT: %x.param_patt.loc183_9.2 => constants.%x.param_patt.e85 -// CHECK:STDOUT: %x.patt.loc183_9.2 => constants.%x.patt.6af -// CHECK:STDOUT: %array_type.loc183_57.1 => constants.%array_type.4e4 -// CHECK:STDOUT: %.loc183_57.1 => constants.%.f45 -// CHECK:STDOUT: %pattern_type.loc183_57 => constants.%pattern_type.2ab -// CHECK:STDOUT: %return.param_patt.loc183_57.2 => constants.%return.param_patt.439 -// CHECK:STDOUT: %return.patt.loc183_41.2 => constants.%return.patt.869 +// CHECK:STDOUT: %pattern_type.loc184_9 => constants.%pattern_type.60a +// CHECK:STDOUT: %x.param_patt.loc184_9.2 => constants.%x.param_patt.e85 +// CHECK:STDOUT: %x.patt.loc184_9.2 => constants.%x.patt.6af +// CHECK:STDOUT: %array_type.loc184_57.1 => constants.%array_type.4e4 +// CHECK:STDOUT: %.loc184_57.1 => constants.%.f45 +// CHECK:STDOUT: %pattern_type.loc184_57 => constants.%pattern_type.2ab +// CHECK:STDOUT: %return.param_patt.loc184_57.2 => constants.%return.param_patt.439 +// CHECK:STDOUT: %return.patt.loc184_41.2 => constants.%return.patt.869 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @SelfNested.WithSelf(constants.%SelfNested.facet.d0d) { @@ -1502,19 +1503,19 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: // CHECK:STDOUT: specific @SelfNested.WithSelf.F(constants.%SelfNested.facet.d0d) { // CHECK:STDOUT: %Self => constants.%SelfNested.facet.d0d -// CHECK:STDOUT: %Self.as_type.loc183_16.1 => constants.%SelfNestedBadParam -// CHECK:STDOUT: %ptr.loc183_16.1 => constants.%ptr.52e -// CHECK:STDOUT: %struct_type.x.y.loc183_37.1 => constants.%struct_type.x.y.da2 +// CHECK:STDOUT: %Self.as_type.loc184_16.1 => constants.%SelfNestedBadParam +// CHECK:STDOUT: %ptr.loc184_16.1 => constants.%ptr.52e +// CHECK:STDOUT: %struct_type.x.y.loc184_37.1 => constants.%struct_type.x.y.da2 // CHECK:STDOUT: %tuple => constants.%tuple.09d // CHECK:STDOUT: %tuple.type => constants.%tuple.type.9ab -// CHECK:STDOUT: %pattern_type.loc183_9 => constants.%pattern_type.94f -// CHECK:STDOUT: %x.param_patt.loc183_9.2 => constants.%x.param_patt.7b9 -// CHECK:STDOUT: %x.patt.loc183_9.2 => constants.%x.patt.961 -// CHECK:STDOUT: %array_type.loc183_57.1 => constants.%array_type.291 -// CHECK:STDOUT: %.loc183_57.1 => constants.%.cc2 -// CHECK:STDOUT: %pattern_type.loc183_57 => constants.%pattern_type.3a0 -// CHECK:STDOUT: %return.param_patt.loc183_57.2 => constants.%return.param_patt.489 -// CHECK:STDOUT: %return.patt.loc183_41.2 => constants.%return.patt.98a +// CHECK:STDOUT: %pattern_type.loc184_9 => constants.%pattern_type.94f +// CHECK:STDOUT: %x.param_patt.loc184_9.2 => constants.%x.param_patt.7b9 +// CHECK:STDOUT: %x.patt.loc184_9.2 => constants.%x.patt.961 +// CHECK:STDOUT: %array_type.loc184_57.1 => constants.%array_type.291 +// CHECK:STDOUT: %.loc184_57.1 => constants.%.cc2 +// CHECK:STDOUT: %pattern_type.loc184_57 => constants.%pattern_type.3a0 +// CHECK:STDOUT: %return.param_patt.loc184_57.2 => constants.%return.param_patt.489 +// CHECK:STDOUT: %return.patt.loc184_41.2 => constants.%return.patt.98a // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @SelfNested.WithSelf(constants.%SelfNested.facet.e71) { @@ -1526,18 +1527,18 @@ class SelfNestedBadReturnType { // CHECK:STDOUT: // CHECK:STDOUT: specific @SelfNested.WithSelf.F(constants.%SelfNested.facet.e71) { // CHECK:STDOUT: %Self => constants.%SelfNested.facet.e71 -// CHECK:STDOUT: %Self.as_type.loc183_16.1 => constants.%SelfNestedBadReturnType -// CHECK:STDOUT: %ptr.loc183_16.1 => constants.%ptr.f55 -// CHECK:STDOUT: %struct_type.x.y.loc183_37.1 => constants.%struct_type.x.y.f6a +// CHECK:STDOUT: %Self.as_type.loc184_16.1 => constants.%SelfNestedBadReturnType +// CHECK:STDOUT: %ptr.loc184_16.1 => constants.%ptr.f55 +// CHECK:STDOUT: %struct_type.x.y.loc184_37.1 => constants.%struct_type.x.y.f6a // CHECK:STDOUT: %tuple => constants.%tuple.96d // CHECK:STDOUT: %tuple.type => constants.%tuple.type.829 -// CHECK:STDOUT: %pattern_type.loc183_9 => constants.%pattern_type.5c2 -// CHECK:STDOUT: %x.param_patt.loc183_9.2 => constants.%x.param_patt.7be -// CHECK:STDOUT: %x.patt.loc183_9.2 => constants.%x.patt.608 -// CHECK:STDOUT: %array_type.loc183_57.1 => constants.%array_type.a08 -// CHECK:STDOUT: %.loc183_57.1 => constants.%.442 -// CHECK:STDOUT: %pattern_type.loc183_57 => constants.%pattern_type.f0d -// CHECK:STDOUT: %return.param_patt.loc183_57.2 => constants.%return.param_patt.039 -// CHECK:STDOUT: %return.patt.loc183_41.2 => constants.%return.patt.3c4 +// CHECK:STDOUT: %pattern_type.loc184_9 => constants.%pattern_type.5c2 +// CHECK:STDOUT: %x.param_patt.loc184_9.2 => constants.%x.param_patt.7be +// CHECK:STDOUT: %x.patt.loc184_9.2 => constants.%x.patt.608 +// CHECK:STDOUT: %array_type.loc184_57.1 => constants.%array_type.a08 +// CHECK:STDOUT: %.loc184_57.1 => constants.%.442 +// CHECK:STDOUT: %pattern_type.loc184_57 => constants.%pattern_type.f0d +// CHECK:STDOUT: %return.param_patt.loc184_57.2 => constants.%return.param_patt.039 +// CHECK:STDOUT: %return.patt.loc184_41.2 => constants.%return.patt.3c4 // CHECK:STDOUT: } // CHECK:STDOUT: diff --git a/toolchain/language_server/handle_position.cpp b/toolchain/language_server/handle_position.cpp index 891b81434e0a..9e82788dec79 100644 --- a/toolchain/language_server/handle_position.cpp +++ b/toolchain/language_server/handle_position.cpp @@ -20,18 +20,16 @@ namespace Carbon::LanguageServer { // if it has no type. Instructions that aren't values, such as declarations of // namespaces, have no type to show. // -// TODO: `StringifyConstantInst` renders some types as placeholders such as +// TODO: `StringifyTypeOfInst` renders some types as placeholders such as // `` for a function and `` for a binding pattern, // which is unhelpful as hover text. Show the signature for a function, and the // bound type rather than the pattern type for a binding. -static auto StringifyTypeOfInst(const SemIR::File& sem_ir, - SemIR::InstId inst_id) -> std::string { - auto type_id = sem_ir.insts().Get(inst_id).type_id(); - if (!type_id.has_value()) { +static auto StringifyTypeForHover(const SemIR::File& sem_ir, + SemIR::InstId inst_id) -> std::string { + if (!sem_ir.insts().Get(inst_id).type_id().has_value()) { return ""; } - return SemIR::StringifyConstantInst(sem_ir, - sem_ir.types().GetTypeInstId(type_id)); + return SemIR::StringifyTypeOfInst(sem_ir, inst_id); } // Given a position-based query, returns the corresponding position information. @@ -78,7 +76,7 @@ auto HandleHover( const auto& sem_ir = *info.file->sem_ir(); RawStringOstream text; text << "```carbon\n" << info.file->tokens().GetTokenText(info.token); - if (auto type = StringifyTypeOfInst(sem_ir, info.inst_id); !type.empty()) { + if (auto type = StringifyTypeForHover(sem_ir, info.inst_id); !type.empty()) { text << ": " << type; } text << "\n```"; diff --git a/toolchain/sem_ir/BUILD b/toolchain/sem_ir/BUILD index 29ddb43f0f39..c08c174cf2dc 100644 --- a/toolchain/sem_ir/BUILD +++ b/toolchain/sem_ir/BUILD @@ -201,12 +201,26 @@ cc_library( ], ) +cc_library( + name = "sugared_type", + srcs = ["sugared_type.cpp"], + hdrs = ["sugared_type.h"], + deps = [ + ":file", + ":typed_insts", + "//common:check", + "//toolchain/base:kind_switch", + "@llvm-project//llvm:Support", + ], +) + cc_library( name = "stringify", srcs = ["stringify.cpp"], hdrs = ["stringify.h"], deps = [ ":file", + ":sugared_type", ":typed_insts", "//common:check", "//common:concepts", diff --git a/toolchain/sem_ir/stringify.cpp b/toolchain/sem_ir/stringify.cpp index e098f818ba61..7f3145a71172 100644 --- a/toolchain/sem_ir/stringify.cpp +++ b/toolchain/sem_ir/stringify.cpp @@ -19,6 +19,7 @@ #include "toolchain/sem_ir/singleton_insts.h" #include "toolchain/sem_ir/specific_interface.h" #include "toolchain/sem_ir/struct_type_field.h" +#include "toolchain/sem_ir/sugared_type.h" #include "toolchain/sem_ir/type_info.h" #include "toolchain/sem_ir/typed_insts.h" @@ -876,6 +877,10 @@ auto StringifyConstantInst(const File& sem_ir, InstId outer_inst_id) return Stringify(sem_ir, step_stack); } +auto StringifyTypeOfInst(const File& sem_ir, InstId inst_id) -> std::string { + return StringifyConstantInst(sem_ir, GetSugaredTypeOfInst(sem_ir, inst_id)); +} + auto StringifySpecific(const File& sem_ir, SpecificId specific_id) -> std::string { StepStack step_stack(&sem_ir); diff --git a/toolchain/sem_ir/stringify.h b/toolchain/sem_ir/stringify.h index fcc470deaef9..6fb309214b31 100644 --- a/toolchain/sem_ir/stringify.h +++ b/toolchain/sem_ir/stringify.h @@ -19,6 +19,12 @@ namespace Carbon::SemIR { auto StringifyConstantInst(const File& sem_ir, InstId outer_inst_id) -> std::string; +// Produces a string version of the type of an instruction, describing the type +// the way it was written in the source where we can determine that. Generally, +// this should not be called directly. To format the type of an expression into +// a diagnostic, use a diagnostic parameter of type `TypeOfInstId`. +auto StringifyTypeOfInst(const File& sem_ir, InstId inst_id) -> std::string; + // Produces a string version of the name of a specific. Generally, this should // not be called directly. To format a string into a diagnostic, use a // diagnostic parameter of type `SpecificId`. diff --git a/toolchain/sem_ir/sugared_type.cpp b/toolchain/sem_ir/sugared_type.cpp new file mode 100644 index 000000000000..80cceed3ffbb --- /dev/null +++ b/toolchain/sem_ir/sugared_type.cpp @@ -0,0 +1,209 @@ +// 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/sem_ir/sugared_type.h" + +#include + +#include "common/check.h" +#include "llvm/ADT/STLExtras.h" +#include "llvm/ADT/SmallVector.h" +#include "toolchain/base/kind_switch.h" +#include "toolchain/sem_ir/function.h" +#include "toolchain/sem_ir/ids.h" +#include "toolchain/sem_ir/inst.h" +#include "toolchain/sem_ir/inst_categories.h" +#include "toolchain/sem_ir/typed_insts.h" + +namespace Carbon::SemIR { + +namespace { + +// Searches for an instruction that describes how the type of a given +// instruction was written. See `GetSugaredTypeOfInst`. +class SugaredTypeFinder { + public: + explicit SugaredTypeFinder(const File* sem_ir) : sem_ir_(sem_ir) {} + + // Finds the best spelling we can for the type of `inst_id`. + auto Find(InstId inst_id) -> TypeInstId; + + private: + // A transformation that is applied to a type that we find in order to produce + // the type of the instruction that the search started from. + enum class TypeTransformStep { + // Replace a pointer type `T*` with its pointee type `T`. + Pointee, + }; + + // Walks from `inst_id` towards the instructions that determined its type, + // until we find an instruction that tracks how its type was written, adding + // to `steps_` as we go. Returns `None` if no such instruction is found. + auto FindSpelledType(InstId inst_id) -> TypeInstId; + + // Finds the declared return type of `call`, as written. + auto FindCallReturnType(Call call) -> TypeInstId; + + // Applies `step` to `type_inst_id`, desugaring it if necessary. Returns + // `None` if the step can't be applied. + auto ApplyStep(TypeTransformStep step, TypeInstId type_inst_id) -> TypeInstId; + + // Returns `operand_id` if it has type `type_id`, and `None` otherwise. This + // is used when looking through an instruction that is expected to have the + // same type as one of its operands: if that turns out not to hold, we stop + // the search rather than describing the wrong type. + auto LookThrough(TypeId type_id, InstId operand_id) -> InstId; + + const File* sem_ir_; + + // The steps to apply to the type that we find, in reverse order. + llvm::SmallVector steps_; +}; + +auto SugaredTypeFinder::LookThrough(TypeId type_id, InstId operand_id) + -> InstId { + if (!operand_id.has_value() || + sem_ir_->insts().Get(operand_id).type_id() != type_id) { + return InstId::None; + } + return operand_id; +} + +auto SugaredTypeFinder::FindCallReturnType(Call call) -> TypeInstId { + auto callee = GetCallee(*sem_ir_, call.callee_id); + auto* function_callee = std::get_if(&callee); + if (!function_callee) { + return TypeInstId::None; + } + + // TODO: For a call to a generic function, substitute the call's arguments + // into the declared return type so that we can describe how it was written. + if (function_callee->enclosing_specific_id.has_value() || + function_callee->resolved_specific_id.has_value()) { + return TypeInstId::None; + } + + // This is `None` if no return type was declared, in which case we have no + // spelling to offer. + return sem_ir_->functions() + .Get(function_callee->function_id) + .return_type_inst_id; +} + +auto SugaredTypeFinder::ApplyStep(TypeTransformStep step, + TypeInstId type_inst_id) -> TypeInstId { + switch (step) { + case TypeTransformStep::Pointee: { + auto pointer_type = sem_ir_->insts().TryGetAs(type_inst_id); + if (!pointer_type) { + // The spelling we found isn't syntactically a pointer type, for example + // because the pointer type was named by an alias. Desugar it and try + // again: the canonical instruction for a pointer type is a + // `PointerType`. + type_inst_id = sem_ir_->types().GetTypeInstId( + sem_ir_->types().GetTypeIdForTypeInstId(type_inst_id)); + pointer_type = sem_ir_->insts().TryGetAs(type_inst_id); + if (!pointer_type) { + return TypeInstId::None; + } + } + return pointer_type->pointee_id; + } + } +} + +auto SugaredTypeFinder::FindSpelledType(InstId inst_id) -> TypeInstId { + while (inst_id.has_value()) { + auto inst = sem_ir_->insts().Get(inst_id); + CARBON_KIND_SWITCH(inst) { + // The type of a call is the declared return type of the callee. + case CARBON_KIND(Call call): { + return FindCallReturnType(call); + } + + // The type of a dereference is the pointee type of the pointer. + case CARBON_KIND(Deref deref): { + steps_.push_back(TypeTransformStep::Pointee); + inst_id = deref.pointer_id; + continue; + } + + // The following instructions have the same type as one of their operands, + // so look through them to that operand. + case CARBON_KIND(NameRef name_ref): { + inst_id = LookThrough(inst.type_id(), name_ref.value_id); + continue; + } + case CARBON_KIND_ANY(AnyBinding, binding): { + inst_id = LookThrough(inst.type_id(), binding.value_id); + continue; + } + case CARBON_KIND(AcquireValue acquire_value): { + inst_id = LookThrough(inst.type_id(), acquire_value.value_id); + continue; + } + case CARBON_KIND(Converted converted): { + inst_id = LookThrough(inst.type_id(), converted.result_id); + continue; + } + case CARBON_KIND(SpliceBlock splice_block): { + inst_id = LookThrough(inst.type_id(), splice_block.result_id); + continue; + } + case CARBON_KIND(Temporary temporary): { + inst_id = LookThrough(inst.type_id(), temporary.init_id); + continue; + } + case CARBON_KIND(ValueOfInitializer value_of_initializer): { + inst_id = LookThrough(inst.type_id(), value_of_initializer.init_id); + continue; + } + + default: { + // TODO: Handle more cases here. For example, the type of a name + // reference to a binding or field should use the type as written in + // the declaration of that binding or field, and the type of an index + // into an array should be the element type as written in the array + // type. + return TypeInstId::None; + } + } + } + return TypeInstId::None; +} + +auto SugaredTypeFinder::Find(InstId inst_id) -> TypeInstId { + auto type_id = sem_ir_->insts().Get(inst_id).type_id(); + if (!type_id.has_value()) { + return TypeInstId::None; + } + + auto result = FindSpelledType(inst_id); + for (auto step : llvm::reverse(steps_)) { + if (!result.has_value()) { + break; + } + result = ApplyStep(step, result); + } + + if (!result.has_value()) { + // We've no better spelling for this type, so use the canonical one. + return sem_ir_->types().GetTypeInstId(type_id); + } + + CARBON_CHECK(sem_ir_->types().GetTypeIdForTypeInstId(result) == type_id, + "Spelling {0} found for the type of {1} describes type {2}, but " + "its type is {3}", + result, inst_id, sem_ir_->types().GetTypeIdForTypeInstId(result), + type_id); + return result; +} + +} // namespace + +auto GetSugaredTypeOfInst(const File& sem_ir, InstId inst_id) -> TypeInstId { + return SugaredTypeFinder(&sem_ir).Find(inst_id); +} + +} // namespace Carbon::SemIR diff --git a/toolchain/sem_ir/sugared_type.h b/toolchain/sem_ir/sugared_type.h new file mode 100644 index 000000000000..f0f05c2f009f --- /dev/null +++ b/toolchain/sem_ir/sugared_type.h @@ -0,0 +1,35 @@ +// 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 + +#ifndef CARBON_TOOLCHAIN_SEM_IR_SUGARED_TYPE_H_ +#define CARBON_TOOLCHAIN_SEM_IR_SUGARED_TYPE_H_ + +#include "toolchain/sem_ir/file.h" +#include "toolchain/sem_ir/ids.h" + +namespace Carbon::SemIR { + +// Returns an instruction describing the type of `inst_id`, preferring an +// instruction that reflects how the type was written in the source over the +// canonical instruction for the type. +// +// The type of an instruction is tracked as a `TypeId`, which is canonical, and +// so says nothing about how the type was spelled: for example, a type named by +// an alias is indistinguishable from the type that the alias names. However, +// the instructions that formed the type as written are usually still present, +// and can often be found by looking at the instruction that has the type, +// rather than at the type itself. For example, the type of a call to a +// non-generic function is the declared return type of that function, and the +// function tracks the instruction for its return type as written. +// +// This process is opportunistic: where we can't do better, the canonical type +// instruction is returned. The result always describes the same type as +// `sem_ir.insts().Get(inst_id).type_id()`; only the spelling can differ. +// +// Returns `None` if `inst_id` has no type. +auto GetSugaredTypeOfInst(const File& sem_ir, InstId inst_id) -> TypeInstId; + +} // namespace Carbon::SemIR + +#endif // CARBON_TOOLCHAIN_SEM_IR_SUGARED_TYPE_H_