From 49a8efbe1bd5e83e25ee5c10c5cc65d226149a26 Mon Sep 17 00:00:00 2001 From: josh11b <15258583+josh11b@users.noreply.github.com> Date: Tue, 24 Sep 2024 19:44:12 -0700 Subject: [PATCH] `where` check stage, step 1: designators (#4329) Right now, there is no checking of `where` requirements. The result of a where expression is just the type on the left-hand side. It does now introduce `.Self` so that it is available in expressions on the right-hand side, in addition to designators corresponding to the members of type on the left-hand side. Note, though, that diagnostics could still be improved significantly. --------- Co-authored-by: Josh L Co-authored-by: Jon Ross-Perkins --- toolchain/check/handle_name.cpp | 58 +- toolchain/check/handle_where.cpp | 82 ++- toolchain/check/node_stack.h | 5 +- .../impl/fail_todo_impl_assoc_const.carbon | 44 +- .../testdata/where_expr/constraints.carbon | 554 ++++++++++++++++++ .../where_expr/no_prelude/designator.carbon | 373 ++++++++++++ .../no_prelude/fail_designator.carbon | 129 ---- toolchain/diagnostics/diagnostic_kind.def | 5 +- toolchain/sem_ir/ids.h | 13 +- toolchain/sem_ir/name.cpp | 2 + 10 files changed, 1096 insertions(+), 169 deletions(-) create mode 100644 toolchain/check/testdata/where_expr/constraints.carbon create mode 100644 toolchain/check/testdata/where_expr/no_prelude/designator.carbon delete mode 100644 toolchain/check/testdata/where_expr/no_prelude/fail_designator.carbon diff --git a/toolchain/check/handle_name.cpp b/toolchain/check/handle_name.cpp index a28213456839..2be40d3bb097 100644 --- a/toolchain/check/handle_name.cpp +++ b/toolchain/check/handle_name.cpp @@ -99,7 +99,7 @@ static auto GetIdentifierAsName(Context& context, Parse::NodeId node_id) // Handle a name that is used as an expression by performing unqualified name // lookup. static auto HandleNameAsExpr(Context& context, Parse::NodeId node_id, - SemIR::NameId name_id) -> bool { + SemIR::NameId name_id) -> SemIR::InstId { auto result = context.LookupUnqualifiedName(node_id, name_id); auto value = context.insts().Get(result.inst_id); auto type_id = SemIR::GetTypeInSpecific(context.sem_ir(), result.specific_id, @@ -116,10 +116,9 @@ static auto HandleNameAsExpr(Context& context, Parse::NodeId node_id, .specific_id = result.specific_id}); } - context.AddInstAndPush( + return context.AddInst( node_id, {.type_id = type_id, .name_id = name_id, .value_id = result.inst_id}); - return true; } auto HandleParseNode(Context& context, Parse::IdentifierNameId node_id) @@ -139,7 +138,9 @@ auto HandleParseNode(Context& context, Parse::IdentifierNameExprId node_id) if (!name_id) { return context.TODO(node_id, "Error recovery from keyword name."); } - return HandleNameAsExpr(context, node_id, *name_id); + context.node_stack().Push(node_id, + HandleNameAsExpr(context, node_id, *name_id)); + return true; } auto HandleParseNode(Context& context, Parse::BaseNameId node_id) -> bool { @@ -147,9 +148,16 @@ auto HandleParseNode(Context& context, Parse::BaseNameId node_id) -> bool { return true; } +auto HandleParseNode(Context& context, Parse::SelfTypeNameId node_id) -> bool { + context.node_stack().Push(node_id, SemIR::NameId::SelfType); + return true; +} + auto HandleParseNode(Context& context, Parse::SelfTypeNameExprId node_id) -> bool { - return HandleNameAsExpr(context, node_id, SemIR::NameId::SelfType); + context.node_stack().Push( + node_id, HandleNameAsExpr(context, node_id, SemIR::NameId::SelfType)); + return true; } auto HandleParseNode(Context& context, Parse::SelfValueNameId node_id) -> bool { @@ -159,7 +167,9 @@ auto HandleParseNode(Context& context, Parse::SelfValueNameId node_id) -> bool { auto HandleParseNode(Context& context, Parse::SelfValueNameExprId node_id) -> bool { - return HandleNameAsExpr(context, node_id, SemIR::NameId::SelfValue); + context.node_stack().Push( + node_id, HandleNameAsExpr(context, node_id, SemIR::NameId::SelfValue)); + return true; } auto HandleParseNode(Context& context, Parse::NameQualifierId /*node_id*/) @@ -168,6 +178,42 @@ auto HandleParseNode(Context& context, Parse::NameQualifierId /*node_id*/) return true; } +auto HandleParseNode(Context& context, Parse::DesignatorExprId node_id) + -> bool { + SemIR::NameId name_id = context.node_stack().PopName(); + + if (name_id == SemIR::NameId::SelfType) { + // Look up `.Self`. + SemIR::InstId period_self_id = + HandleNameAsExpr(context, node_id, SemIR::NameId::PeriodSelf); + context.node_stack().Push(node_id, period_self_id); + } else { + // Otherwise this is `.Member`, so look up `.Self` and then `Member` in + // `.Self`. + SemIR::InstId period_self_id = SemIR::InstId::Invalid; + { + // TODO: Instead of annotating the diagnostic, should change + // `HandleNameAsExpr` to optionally allow us to produce the diagnostic + // instead so we can generate a "name `.Self` implicitly referenced by + // designated expression, but not found" diagnostic instead of adding a + // note to the current "name `.Self` not found" message. + DiagnosticAnnotationScope annotate_diagnostics( + &context.emitter(), [&](auto& builder) { + CARBON_DIAGNOSTIC( + NoPeriodSelfForDesignator, Note, + "designator may only be used when `.Self` is in scope"); + builder.Note(SemIR::LocId::Invalid, NoPeriodSelfForDesignator); + }); + period_self_id = + HandleNameAsExpr(context, node_id, SemIR::NameId::PeriodSelf); + } + auto member_id = + PerformMemberAccess(context, node_id, period_self_id, name_id); + context.node_stack().Push(node_id, member_id); + } + return true; +} + auto HandleParseNode(Context& context, Parse::PackageExprId node_id) -> bool { context.AddInstAndPush( node_id, diff --git a/toolchain/check/handle_where.cpp b/toolchain/check/handle_where.cpp index b41f4f0eebca..5f229bfc5883 100644 --- a/toolchain/check/handle_where.cpp +++ b/toolchain/check/handle_where.cpp @@ -8,41 +8,77 @@ namespace Carbon::Check { -auto HandleParseNode(Context& context, Parse::SelfTypeNameId node_id) -> bool { - return context.TODO(node_id, "HandleSelfTypeName"); -} - -auto HandleParseNode(Context& context, Parse::DesignatorExprId node_id) +auto HandleParseNode(Context& context, Parse::WhereOperandId /*node_id*/) -> bool { - return context.TODO(node_id, "HandleDesignatorExpr"); + // The expression at the top of the stack represents a constraint type that + // is being modified by the `where` operator. It would be `MyInterface` in + // `MyInterface where .Member = i32`. + auto [self_node, self_id] = context.node_stack().PopExprWithNodeId(); + auto self_type_id = ExprAsType(context, self_node, self_id); + // TODO: Do this instead once `WhereExpr` is ready to consume this: + // context.node_stack().Push(node_id, self_type_id); + context.node_stack().Push(self_node, self_id); + + // Introduce a name scope so that we can remove the `.Self` entry we are + // adding to name lookup at the end of the `where` expression. + context.scope_stack().Push(); + // Introduce `.Self` as a symbolic binding. Its type is the value of the + // expression to the left of `where`, so `MyInterface` in the example above. + // Because there is no equivalent non-symbolic value, we use `Invalid` as + // the `value_id` on the `BindSymbolicName`. + auto entity_name_id = context.entity_names().Add( + {.name_id = SemIR::NameId::PeriodSelf, + .parent_scope_id = context.decl_name_stack().PeekParentScopeId(), + .bind_index = context.scope_stack().AddCompileTimeBinding()}); + auto inst_id = + context.AddInst(SemIR::LocIdAndInst::NoLoc( + {.type_id = self_type_id, + .entity_name_id = entity_name_id, + .value_id = SemIR::InstId::Invalid})); + context.scope_stack().PushCompileTimeBinding(inst_id); + auto existing = + context.scope_stack().LookupOrAddName(SemIR::NameId::PeriodSelf, inst_id); + // Shouldn't have any names in newly created scope. + CARBON_CHECK(!existing.is_valid()); + return true; } -auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool { - return context.TODO(node_id, "HandleWhereOperand"); -} - -auto HandleParseNode(Context& context, Parse::RequirementEqualId node_id) +auto HandleParseNode(Context& context, Parse::RequirementEqualId /*node_id*/) -> bool { - return context.TODO(node_id, "HandleRequirementEqual"); + // TODO: Implement + context.node_stack().PopExpr(); + context.node_stack().PopExpr(); + return true; } -auto HandleParseNode(Context& context, Parse::RequirementEqualEqualId node_id) +auto HandleParseNode(Context& context, + Parse::RequirementEqualEqualId /*node_id*/) -> bool { + // TODO: Implement + context.node_stack().PopExpr(); + context.node_stack().PopExpr(); + return true; +} + +auto HandleParseNode(Context& context, Parse::RequirementImplsId /*node_id*/) -> bool { - return context.TODO(node_id, "HandleRequirementEqualEqual"); + // TODO: Implement + context.node_stack().PopExpr(); + context.node_stack().PopExpr(); + return true; } -auto HandleParseNode(Context& context, Parse::RequirementImplsId node_id) +auto HandleParseNode(Context& /*context*/, Parse::RequirementAndId /*node_id*/) -> bool { - return context.TODO(node_id, "HandleRequirementImpls"); + // Nothing to do. + return true; } -auto HandleParseNode(Context& context, Parse::RequirementAndId node_id) - -> bool { - return context.TODO(node_id, "HandleRequirementAnd"); -} - -auto HandleParseNode(Context& context, Parse::WhereExprId node_id) -> bool { - return context.TODO(node_id, "HandleWhereExpr"); +auto HandleParseNode(Context& context, Parse::WhereExprId /*node_id*/) -> bool { + // Remove `PeriodSelf` from name lookup, undoing the `Push` done for the + // `WhereOperand`. + context.scope_stack().Pop(); + // TODO: Output instruction for newly formed restricted constraint type. + return true; } } // namespace Carbon::Check diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index 02c68da70583..eb0f389304c1 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -443,11 +443,14 @@ class NodeStack { return Id::KindFor(); case Parse::NodeKind::ImplDefinitionStart: return Id::KindFor(); + case Parse::NodeKind::SelfTypeName: case Parse::NodeKind::SelfValueName: return Id::KindFor(); case Parse::NodeKind::DefaultLibrary: case Parse::NodeKind::LibraryName: return Id::KindFor(); + case Parse::NodeKind::WhereOperand: + return Id::KindFor(); case Parse::NodeKind::ArrayExprSemi: case Parse::NodeKind::BuiltinName: case Parse::NodeKind::ClassIntroducer: @@ -623,7 +626,6 @@ class NodeStack { case Parse::NodeKind::RequirementEqualEqual: case Parse::NodeKind::RequirementImpls: case Parse::NodeKind::ReturnStatement: - case Parse::NodeKind::SelfTypeName: case Parse::NodeKind::SelfTypeNameExpr: case Parse::NodeKind::SelfValueNameExpr: case Parse::NodeKind::ShortCircuitOperatorAnd: @@ -643,7 +645,6 @@ class NodeStack { case Parse::NodeKind::VariableDecl: case Parse::NodeKind::VirtualModifier: case Parse::NodeKind::WhereExpr: - case Parse::NodeKind::WhereOperand: case Parse::NodeKind::WhileStatement: return Id::Kind::Invalid; } diff --git a/toolchain/check/testdata/impl/fail_todo_impl_assoc_const.carbon b/toolchain/check/testdata/impl/fail_todo_impl_assoc_const.carbon index 9f99d151f22c..7d166b73adcb 100644 --- a/toolchain/check/testdata/impl/fail_todo_impl_assoc_const.carbon +++ b/toolchain/check/testdata/impl/fail_todo_impl_assoc_const.carbon @@ -10,9 +10,9 @@ interface I { let T:! type; } -// CHECK:STDERR: fail_todo_impl_assoc_const.carbon:[[@LINE+3]]:14: error: semantics TODO: `HandleWhereOperand` +// CHECK:STDERR: fail_todo_impl_assoc_const.carbon:[[@LINE+3]]:1: error: semantics TODO: `impl of interface with associated constant` // CHECK:STDERR: impl bool as I where .T = bool {} -// CHECK:STDERR: ^~~~~~~ +// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ impl bool as I where .T = bool {} // CHECK:STDOUT: --- fail_todo_impl_assoc_const.carbon @@ -25,9 +25,42 @@ impl bool as I where .T = bool {} // CHECK:STDOUT: %Bool.type: type = fn_type @Bool [template] // CHECK:STDOUT: %.4: type = tuple_type () [template] // CHECK:STDOUT: %Bool: %Bool.type = struct_value () [template] +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic] // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: file {} +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .Bool = %import_ref +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref: %Bool.type = import_ref Core//prelude/types/bool, inst+2, loaded [template = constants.%Bool] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %bool.make_type.loc16_6: init type = call constants.%Bool() [template = bool] +// CHECK:STDOUT: %.loc16_6.1: type = value_of_initializer %bool.make_type.loc16_6 [template = bool] +// CHECK:STDOUT: %.loc16_6.2: type = converted %bool.make_type.loc16_6, %.loc16_6.1 [template = bool] +// CHECK:STDOUT: %I.ref: type = name_ref I, %I.decl [template = constants.%.1] +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = constants.%.Self] +// CHECK:STDOUT: %.Self.ref: %.1 = name_ref .Self, %.Self [symbolic = constants.%.Self] +// CHECK:STDOUT: %T.ref: %.2 = name_ref T, @I.%.loc11 [template = constants.%.3] +// CHECK:STDOUT: %bool.make_type.loc16_27: init type = call constants.%Bool() [template = bool] +// CHECK:STDOUT: } +// CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: interface @I { // CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self] @@ -40,5 +73,10 @@ impl bool as I where .T = bool {} // CHECK:STDOUT: witness = (%T) // CHECK:STDOUT: } // CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: bool as %.1 { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = +// CHECK:STDOUT: } +// CHECK:STDOUT: // CHECK:STDOUT: fn @Bool() -> type = "bool.make_type"; // CHECK:STDOUT: diff --git a/toolchain/check/testdata/where_expr/constraints.carbon b/toolchain/check/testdata/where_expr/constraints.carbon new file mode 100644 index 000000000000..612ce86520d5 --- /dev/null +++ b/toolchain/check/testdata/where_expr/constraints.carbon @@ -0,0 +1,554 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/where_expr/constraints.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/where_expr/constraints.carbon + +// --- state_constraints.carbon + +library "[[@TEST_NAME]]"; + +interface J {} + +interface I { + let Member:! type; + let Second:! J; +} + +fn Equal(T:! I where .Member = {}); + +fn EqualEqual(U:! I where .Self == ()); + +fn Impls(V:! J where .Self impls I); + +fn And(W:! I where .Second impls I and .Member = .Second); + +// --- todo_check_constraints.carbon + +library "[[@TEST_NAME]]"; + +import library "state_constraints"; + +// TODO: Should fail since `2` can't be converted to the type of `I.Member`, +// but constraints are not yet type checked. +fn TypeMismatch(X:! I where .Member = 2); + +// --- fail_todo_enforce_constraint.carbon + +library "[[@TEST_NAME]]"; + +import library "state_constraints"; + +// C implements J but not I. +class C {} +impl C as J {} + +// TODO: Should report that `C` does not meet the constraint. +fn DoesNotImplI() { + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+11]]:3: error: cannot implicitly convert from `type` to `J` + // CHECK:STDERR: Impls(C); + // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+8]]:3: note: type `type` does not implement interface `ImplicitAs` + // CHECK:STDERR: Impls(C); + // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE-14]]:1: in import + // CHECK:STDERR: state_constraints.carbon:15:10: note: initializing generic parameter `V` declared here + // CHECK:STDERR: fn Impls(V:! J where .Self impls I); + // CHECK:STDERR: ^ + // CHECK:STDERR: + Impls(C); +} + +fn EmptyStruct(Y:! J where .Self == {}); + +// TODO: Should report that `C` does not meeet the constraint. +fn NotEmptyStruct() { + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+9]]:3: error: cannot implicitly convert from `type` to `J` + // CHECK:STDERR: EmptyStruct(C); + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE+6]]:3: note: type `type` does not implement interface `ImplicitAs` + // CHECK:STDERR: EmptyStruct(C); + // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_enforce_constraint.carbon:[[@LINE-10]]:16: note: initializing generic parameter `Y` declared here + // CHECK:STDERR: fn EmptyStruct(Y:! J where .Self == {}); + // CHECK:STDERR: ^ + EmptyStruct(C); +} + +// CHECK:STDOUT: --- state_constraints.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @J [template] +// CHECK:STDOUT: %Self.1: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = interface_type @I [template] +// CHECK:STDOUT: %Self.2: %.2 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.3: type = assoc_entity_type %.2, type [template] +// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, @I.%Member [template] +// CHECK:STDOUT: %.5: type = tuple_type () [template] +// CHECK:STDOUT: %.6: type = assoc_entity_type %.2, %.1 [template] +// CHECK:STDOUT: %.7: %.6 = assoc_entity element1, @I.%Second [template] +// CHECK:STDOUT: %.Self.1: %.2 = bind_symbolic_name .Self 0 [symbolic] +// CHECK:STDOUT: %.8: type = struct_type {} [template] +// CHECK:STDOUT: %T: %.2 = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %Equal.type: type = fn_type @Equal [template] +// CHECK:STDOUT: %Equal: %Equal.type = struct_value () [template] +// CHECK:STDOUT: %U: %.2 = bind_symbolic_name U 0 [symbolic] +// CHECK:STDOUT: %EqualEqual.type: type = fn_type @EqualEqual [template] +// CHECK:STDOUT: %EqualEqual: %EqualEqual.type = struct_value () [template] +// CHECK:STDOUT: %.Self.2: %.1 = bind_symbolic_name .Self 0 [symbolic] +// CHECK:STDOUT: %V: %.1 = bind_symbolic_name V 0 [symbolic] +// CHECK:STDOUT: %Impls.type: type = fn_type @Impls [template] +// CHECK:STDOUT: %Impls: %Impls.type = struct_value () [template] +// CHECK:STDOUT: %W: %.2 = bind_symbolic_name W 0 [symbolic] +// CHECK:STDOUT: %And.type: type = fn_type @And [template] +// CHECK:STDOUT: %And: %And.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .J = %J.decl +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .Equal = %Equal.decl +// CHECK:STDOUT: .EqualEqual = %EqualEqual.decl +// CHECK:STDOUT: .Impls = %Impls.decl +// CHECK:STDOUT: .And = %And.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %J.decl: type = interface_decl @J [template = constants.%.1] {} +// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.2] {} +// CHECK:STDOUT: %Equal.decl: %Equal.type = fn_decl @Equal [template = constants.%Equal] { +// CHECK:STDOUT: %I.ref.loc11: type = name_ref I, %I.decl [template = constants.%.2] +// CHECK:STDOUT: %.Self.1: %.2 = bind_symbolic_name .Self 0 [symbolic = @Equal.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %.Self.ref.loc11: %.2 = name_ref .Self, %.Self.1 [symbolic = @Equal.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %Member.ref.loc11: %.3 = name_ref Member, @I.%.loc7 [template = constants.%.4] +// CHECK:STDOUT: %.loc11: %.8 = struct_literal () +// CHECK:STDOUT: %T.loc11_10.1: %.2 = param T, runtime_param +// CHECK:STDOUT: @Equal.%T.loc11: %.2 = bind_symbolic_name T 0, %T.loc11_10.1 [symbolic = @Equal.%T.1 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %EqualEqual.decl: %EqualEqual.type = fn_decl @EqualEqual [template = constants.%EqualEqual] { +// CHECK:STDOUT: %I.ref.loc13: type = name_ref I, %I.decl [template = constants.%.2] +// CHECK:STDOUT: %.Self.2: %.2 = bind_symbolic_name .Self 0 [symbolic = @EqualEqual.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %.Self.ref.loc13: %.2 = name_ref .Self, %.Self.2 [symbolic = @EqualEqual.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %.loc13: %.5 = tuple_literal () +// CHECK:STDOUT: %U.loc13_15.1: %.2 = param U, runtime_param +// CHECK:STDOUT: @EqualEqual.%U.loc13: %.2 = bind_symbolic_name U 0, %U.loc13_15.1 [symbolic = @EqualEqual.%U.1 (constants.%U)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %Impls.decl: %Impls.type = fn_decl @Impls [template = constants.%Impls] { +// CHECK:STDOUT: %J.ref: type = name_ref J, %J.decl [template = constants.%.1] +// CHECK:STDOUT: %.Self.3: %.1 = bind_symbolic_name .Self 0 [symbolic = @Impls.%.Self (constants.%.Self.2)] +// CHECK:STDOUT: %.Self.ref.loc15: %.1 = name_ref .Self, %.Self.3 [symbolic = @Impls.%.Self (constants.%.Self.2)] +// CHECK:STDOUT: %I.ref.loc15: type = name_ref I, %I.decl [template = constants.%.2] +// CHECK:STDOUT: %V.loc15_10.1: %.1 = param V, runtime_param +// CHECK:STDOUT: @Impls.%V.loc15: %.1 = bind_symbolic_name V 0, %V.loc15_10.1 [symbolic = @Impls.%V.1 (constants.%V)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %And.decl: %And.type = fn_decl @And [template = constants.%And] { +// CHECK:STDOUT: %I.ref.loc17_12: type = name_ref I, %I.decl [template = constants.%.2] +// CHECK:STDOUT: %.Self.4: %.2 = bind_symbolic_name .Self 0 [symbolic = @And.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %.Self.ref.loc17_20: %.2 = name_ref .Self, %.Self.4 [symbolic = @And.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %Second.ref.loc17_20: %.6 = name_ref Second, @I.%.loc8 [template = constants.%.7] +// CHECK:STDOUT: %I.ref.loc17_34: type = name_ref I, %I.decl [template = constants.%.2] +// CHECK:STDOUT: %.Self.ref.loc17_40: %.2 = name_ref .Self, %.Self.4 [symbolic = @And.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %Member.ref.loc17: %.3 = name_ref Member, @I.%.loc7 [template = constants.%.4] +// CHECK:STDOUT: %.Self.ref.loc17_50: %.2 = name_ref .Self, %.Self.4 [symbolic = @And.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %Second.ref.loc17_50: %.6 = name_ref Second, @I.%.loc8 [template = constants.%.7] +// CHECK:STDOUT: %W.loc17_8.1: %.2 = param W, runtime_param +// CHECK:STDOUT: @And.%W.loc17: %.2 = bind_symbolic_name W 0, %W.loc17_8.1 [symbolic = @And.%W.1 (constants.%W)] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @J { +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self.1] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %.2 = bind_symbolic_name Self 0 [symbolic = constants.%Self.2] +// CHECK:STDOUT: %Member: type = assoc_const_decl Member [template] +// CHECK:STDOUT: %.loc7: %.3 = assoc_entity element0, %Member [template = constants.%.4] +// CHECK:STDOUT: %J.ref: type = name_ref J, file.%J.decl [template = constants.%.1] +// CHECK:STDOUT: %Second: %.1 = assoc_const_decl Second [template] +// CHECK:STDOUT: %.loc8: %.6 = assoc_entity element1, %Second [template = constants.%.7] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Member = %.loc7 +// CHECK:STDOUT: .Second = %.loc8 +// CHECK:STDOUT: witness = (%Member, %Second) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Equal(%T.loc11: %.2) { +// CHECK:STDOUT: %.Self: %.2 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.1)] +// CHECK:STDOUT: %T.1: %.2 = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%T.loc11: %.2); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @EqualEqual(%U.loc13: %.2) { +// CHECK:STDOUT: %.Self: %.2 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.1)] +// CHECK:STDOUT: %U.1: %.2 = bind_symbolic_name U 0 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%U.loc13: %.2); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Impls(%V.loc15: %.1) { +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.2)] +// CHECK:STDOUT: %V.1: %.1 = bind_symbolic_name V 0 [symbolic = %V.1 (constants.%V)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%V.loc15: %.1); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @And(%W.loc17: %.2) { +// CHECK:STDOUT: %.Self: %.2 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.1)] +// CHECK:STDOUT: %W.1: %.2 = bind_symbolic_name W 0 [symbolic = %W.1 (constants.%W)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%W.loc17: %.2); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Equal(constants.%T) { +// CHECK:STDOUT: %.Self => constants.%T +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @EqualEqual(constants.%U) { +// CHECK:STDOUT: %.Self => constants.%U +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Impls(constants.%V) { +// CHECK:STDOUT: %.Self => constants.%V +// CHECK:STDOUT: %V.1 => constants.%V +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @And(constants.%W) { +// CHECK:STDOUT: %.Self => constants.%W +// CHECK:STDOUT: %W.1 => constants.%W +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- todo_check_constraints.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @I [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = tuple_type () [template] +// CHECK:STDOUT: %.3: type = assoc_entity_type %.1, type [template] +// CHECK:STDOUT: %.4: %.3 = assoc_entity element0, imports.%import_ref.12 [template] +// CHECK:STDOUT: %.5: i32 = int_literal 2 [template] +// CHECK:STDOUT: %X: %.1 = bind_symbolic_name X 0 [symbolic] +// CHECK:STDOUT: %TypeMismatch.type: type = fn_type @TypeMismatch [template] +// CHECK:STDOUT: %TypeMismatch: %TypeMismatch.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1 = import_ref Main//state_constraints, inst+3, unloaded +// CHECK:STDOUT: %import_ref.2: type = import_ref Main//state_constraints, inst+7, loaded [template = constants.%.1] +// CHECK:STDOUT: %import_ref.3 = import_ref Main//state_constraints, inst+31, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//state_constraints, inst+43, unloaded +// CHECK:STDOUT: %import_ref.5 = import_ref Main//state_constraints, inst+56, unloaded +// CHECK:STDOUT: %import_ref.6 = import_ref Main//state_constraints, inst+73, unloaded +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.7 = import_ref Main//state_constraints, inst+9, unloaded +// CHECK:STDOUT: %import_ref.8: %.3 = import_ref Main//state_constraints, inst+13, loaded [template = constants.%.4] +// CHECK:STDOUT: %import_ref.9 = import_ref Main//state_constraints, inst+19, unloaded +// CHECK:STDOUT: %import_ref.10 = import_ref Main//state_constraints, inst+11, unloaded +// CHECK:STDOUT: %import_ref.11 = import_ref Main//state_constraints, inst+17, unloaded +// CHECK:STDOUT: %import_ref.12 = import_ref Main//state_constraints, inst+11, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .J = imports.%import_ref.1 +// CHECK:STDOUT: .I = imports.%import_ref.2 +// CHECK:STDOUT: .Equal = imports.%import_ref.3 +// CHECK:STDOUT: .EqualEqual = imports.%import_ref.4 +// CHECK:STDOUT: .Impls = imports.%import_ref.5 +// CHECK:STDOUT: .And = imports.%import_ref.6 +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .TypeMismatch = %TypeMismatch.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %TypeMismatch.decl: %TypeMismatch.type = fn_decl @TypeMismatch [template = constants.%TypeMismatch] { +// CHECK:STDOUT: %I.ref: type = name_ref I, imports.%import_ref.2 [template = constants.%.1] +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = @TypeMismatch.%.Self (constants.%.Self)] +// CHECK:STDOUT: %.Self.ref: %.1 = name_ref .Self, %.Self [symbolic = @TypeMismatch.%.Self (constants.%.Self)] +// CHECK:STDOUT: %Member.ref: %.3 = name_ref Member, imports.%import_ref.8 [template = constants.%.4] +// CHECK:STDOUT: %.loc8: i32 = int_literal 2 [template = constants.%.5] +// CHECK:STDOUT: %X.loc8_17.1: %.1 = param X, runtime_param +// CHECK:STDOUT: @TypeMismatch.%X.loc8: %.1 = bind_symbolic_name X 0, %X.loc8_17.1 [symbolic = @TypeMismatch.%X.1 (constants.%X)] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.7 +// CHECK:STDOUT: .Member = imports.%import_ref.8 +// CHECK:STDOUT: .Second = imports.%import_ref.9 +// CHECK:STDOUT: witness = (imports.%import_ref.10, imports.%import_ref.11) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @TypeMismatch(%X.loc8: %.1) { +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self)] +// CHECK:STDOUT: %X.1: %.1 = bind_symbolic_name X 0 [symbolic = %X.1 (constants.%X)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%X.loc8: %.1); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @TypeMismatch(constants.%X) { +// CHECK:STDOUT: %.Self => constants.%X +// CHECK:STDOUT: %X.1 => constants.%X +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_todo_enforce_constraint.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %.1: type = struct_type {} [template] +// CHECK:STDOUT: %.2: = complete_type_witness %.1 [template] +// CHECK:STDOUT: %.3: type = interface_type @J [template] +// CHECK:STDOUT: %Self.1: %.3 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %.5: = interface_witness () [template] +// CHECK:STDOUT: %DoesNotImplI.type: type = fn_type @DoesNotImplI [template] +// CHECK:STDOUT: %DoesNotImplI: %DoesNotImplI.type = struct_value () [template] +// CHECK:STDOUT: %Impls.type: type = fn_type @Impls [template] +// CHECK:STDOUT: %Impls: %Impls.type = struct_value () [template] +// CHECK:STDOUT: %V: %.3 = bind_symbolic_name V 0 [symbolic] +// CHECK:STDOUT: %.Self.1: %.3 = bind_symbolic_name .Self 0 [symbolic] +// CHECK:STDOUT: %ImplicitAs.type: type = generic_interface_type @ImplicitAs [template] +// CHECK:STDOUT: %ImplicitAs: %ImplicitAs.type = struct_value () [template] +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest 0 [symbolic] +// CHECK:STDOUT: %.6: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Self.2: @ImplicitAs.%.1 (%.6) = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %Self.3: %.6 = bind_symbolic_name Self 1 [symbolic] +// CHECK:STDOUT: %Convert.type.1: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic] +// CHECK:STDOUT: %Convert.1: %Convert.type.1 = struct_value () [symbolic] +// CHECK:STDOUT: %.7: type = assoc_entity_type %.6, %Convert.type.1 [symbolic] +// CHECK:STDOUT: %.8: %.7 = assoc_entity element0, imports.%import_ref.12 [symbolic] +// CHECK:STDOUT: %.9: type = interface_type @ImplicitAs, @ImplicitAs(%.3) [template] +// CHECK:STDOUT: %Convert.type.2: type = fn_type @Convert, @ImplicitAs(%.3) [template] +// CHECK:STDOUT: %Convert.2: %Convert.type.2 = struct_value () [template] +// CHECK:STDOUT: %.10: type = assoc_entity_type %.9, %Convert.type.2 [template] +// CHECK:STDOUT: %.11: %.10 = assoc_entity element0, imports.%import_ref.12 [template] +// CHECK:STDOUT: %.12: %.7 = assoc_entity element0, imports.%import_ref.13 [symbolic] +// CHECK:STDOUT: %.Self.2: %.3 = bind_symbolic_name .Self 0 [symbolic] +// CHECK:STDOUT: %Y: %.3 = bind_symbolic_name Y 0 [symbolic] +// CHECK:STDOUT: %EmptyStruct.type: type = fn_type @EmptyStruct [template] +// CHECK:STDOUT: %EmptyStruct: %EmptyStruct.type = struct_value () [template] +// CHECK:STDOUT: %NotEmptyStruct.type: type = fn_type @NotEmptyStruct [template] +// CHECK:STDOUT: %NotEmptyStruct: %NotEmptyStruct.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: imports { +// CHECK:STDOUT: %import_ref.1: type = import_ref Main//state_constraints, inst+3, loaded [template = constants.%.3] +// CHECK:STDOUT: %import_ref.2 = import_ref Main//state_constraints, inst+7, unloaded +// CHECK:STDOUT: %import_ref.3 = import_ref Main//state_constraints, inst+31, unloaded +// CHECK:STDOUT: %import_ref.4 = import_ref Main//state_constraints, inst+43, unloaded +// CHECK:STDOUT: %import_ref.5: %Impls.type = import_ref Main//state_constraints, inst+56, loaded [template = constants.%Impls] +// CHECK:STDOUT: %import_ref.6 = import_ref Main//state_constraints, inst+73, unloaded +// CHECK:STDOUT: %Core: = namespace file.%Core.import, [template] { +// CHECK:STDOUT: .ImplicitAs = %import_ref.8 +// CHECK:STDOUT: import Core//prelude +// CHECK:STDOUT: import Core//prelude/operators +// CHECK:STDOUT: import Core//prelude/types +// CHECK:STDOUT: import Core//prelude/operators/arithmetic +// CHECK:STDOUT: import Core//prelude/operators/as +// CHECK:STDOUT: import Core//prelude/operators/bitwise +// CHECK:STDOUT: import Core//prelude/operators/comparison +// CHECK:STDOUT: import Core//prelude/types/bool +// CHECK:STDOUT: } +// CHECK:STDOUT: %import_ref.7 = import_ref Main//state_constraints, inst+5, unloaded +// CHECK:STDOUT: %import_ref.8: %ImplicitAs.type = import_ref Core//prelude/operators/as, inst+37, loaded [template = constants.%ImplicitAs] +// CHECK:STDOUT: %import_ref.9 = import_ref Core//prelude/operators/as, inst+42, unloaded +// CHECK:STDOUT: %import_ref.10: @ImplicitAs.%.2 (%.7) = import_ref Core//prelude/operators/as, inst+59, loaded [symbolic = @ImplicitAs.%.3 (constants.%.12)] +// CHECK:STDOUT: %import_ref.11 = import_ref Core//prelude/operators/as, inst+52, unloaded +// CHECK:STDOUT: %import_ref.12 = import_ref Core//prelude/operators/as, inst+52, unloaded +// CHECK:STDOUT: %import_ref.13 = import_ref Core//prelude/operators/as, inst+52, unloaded +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .J = imports.%import_ref.1 +// CHECK:STDOUT: .I = imports.%import_ref.2 +// CHECK:STDOUT: .Equal = imports.%import_ref.3 +// CHECK:STDOUT: .EqualEqual = imports.%import_ref.4 +// CHECK:STDOUT: .Impls = imports.%import_ref.5 +// CHECK:STDOUT: .And = imports.%import_ref.6 +// CHECK:STDOUT: .Core = imports.%Core +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: .DoesNotImplI = %DoesNotImplI.decl +// CHECK:STDOUT: .EmptyStruct = %EmptyStruct.decl +// CHECK:STDOUT: .NotEmptyStruct = %NotEmptyStruct.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Core.import = import Core +// CHECK:STDOUT: %default.import = import +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: impl_decl @impl { +// CHECK:STDOUT: %C.ref: type = name_ref C, %C.decl [template = constants.%C] +// CHECK:STDOUT: %J.ref.loc8: type = name_ref J, imports.%import_ref.1 [template = constants.%.3] +// CHECK:STDOUT: } +// CHECK:STDOUT: %DoesNotImplI.decl: %DoesNotImplI.type = fn_decl @DoesNotImplI [template = constants.%DoesNotImplI] {} +// CHECK:STDOUT: %EmptyStruct.decl: %EmptyStruct.type = fn_decl @EmptyStruct [template = constants.%EmptyStruct] { +// CHECK:STDOUT: %J.ref.loc26: type = name_ref J, imports.%import_ref.1 [template = constants.%.3] +// CHECK:STDOUT: %.Self: %.3 = bind_symbolic_name .Self 0 [symbolic = @EmptyStruct.%.Self (constants.%.Self.2)] +// CHECK:STDOUT: %.Self.ref: %.3 = name_ref .Self, %.Self [symbolic = @EmptyStruct.%.Self (constants.%.Self.2)] +// CHECK:STDOUT: %.loc26: %.1 = struct_literal () +// CHECK:STDOUT: %Y.loc26_16.1: %.3 = param Y, runtime_param +// CHECK:STDOUT: @EmptyStruct.%Y.loc26: %.3 = bind_symbolic_name Y 0, %Y.loc26_16.1 [symbolic = @EmptyStruct.%Y.1 (constants.%Y)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %NotEmptyStruct.decl: %NotEmptyStruct.type = fn_decl @NotEmptyStruct [template = constants.%NotEmptyStruct] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @J { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.7 +// CHECK:STDOUT: witness = () +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic interface @ImplicitAs(constants.%Dest: type) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %.1 (constants.%.6)] +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.3)] +// CHECK:STDOUT: %Convert.type: type = fn_type @Convert, @ImplicitAs(%Dest) [symbolic = %Convert.type (constants.%Convert.type.1)] +// CHECK:STDOUT: %Convert: @ImplicitAs.%Convert.type (%Convert.type.1) = struct_value () [symbolic = %Convert (constants.%Convert.1)] +// CHECK:STDOUT: %.2: type = assoc_entity_type @ImplicitAs.%.1 (%.6), @ImplicitAs.%Convert.type (%Convert.type.1) [symbolic = %.2 (constants.%.7)] +// CHECK:STDOUT: %.3: @ImplicitAs.%.2 (%.7) = assoc_entity element0, imports.%import_ref.12 [symbolic = %.3 (constants.%.8)] +// CHECK:STDOUT: +// CHECK:STDOUT: interface { +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = imports.%import_ref.9 +// CHECK:STDOUT: .Convert = imports.%import_ref.10 +// CHECK:STDOUT: witness = (imports.%import_ref.11) +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: impl @impl: %C as %.3 { +// CHECK:STDOUT: %.loc8: = interface_witness () [template = constants.%.5] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: witness = %.loc8 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %.loc7: = complete_type_witness %.1 [template = constants.%.2] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @DoesNotImplI() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Impls.ref: %Impls.type = name_ref Impls, imports.%import_ref.5 [template = constants.%Impls] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc23_8.1: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.3) [template = constants.%.9] +// CHECK:STDOUT: %.loc23_8.2: %.10 = specific_constant imports.%import_ref.10, @ImplicitAs(constants.%.3) [template = constants.%.11] +// CHECK:STDOUT: %Convert.ref: %.10 = name_ref Convert, %.loc23_8.2 [template = constants.%.11] +// CHECK:STDOUT: %.loc23_8.3: %.3 = converted %C.ref, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Impls(constants.%V: %.3) { +// CHECK:STDOUT: %.Self: %.3 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.1)] +// CHECK:STDOUT: %V.2: %.3 = bind_symbolic_name V 0 [symbolic = %V.2 (constants.%V)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%V.1: %.3); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @Convert(constants.%Dest: type, constants.%Self.2: @ImplicitAs.%.1 (%.6)) { +// CHECK:STDOUT: %Dest: type = bind_symbolic_name Dest 0 [symbolic = %Dest (constants.%Dest)] +// CHECK:STDOUT: %.1: type = interface_type @ImplicitAs, @ImplicitAs(%Dest) [symbolic = %.1 (constants.%.6)] +// CHECK:STDOUT: %Self: %.6 = bind_symbolic_name Self 1 [symbolic = %Self (constants.%Self.3)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn[%self: @Convert.%Self (%Self.3)]() -> @Convert.%Dest (%Dest); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @EmptyStruct(%Y.loc26: %.3) { +// CHECK:STDOUT: %.Self: %.3 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.2)] +// CHECK:STDOUT: %Y.1: %.3 = bind_symbolic_name Y 0 [symbolic = %Y.1 (constants.%Y)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%Y.loc26: %.3); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @NotEmptyStruct() { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %EmptyStruct.ref: %EmptyStruct.type = name_ref EmptyStruct, file.%EmptyStruct.decl [template = constants.%EmptyStruct] +// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [template = constants.%C] +// CHECK:STDOUT: %.loc39_14.1: type = interface_type @ImplicitAs, @ImplicitAs(constants.%.3) [template = constants.%.9] +// CHECK:STDOUT: %.loc39_14.2: %.10 = specific_constant imports.%import_ref.10, @ImplicitAs(constants.%.3) [template = constants.%.11] +// CHECK:STDOUT: %Convert.ref: %.10 = name_ref Convert, %.loc39_14.2 [template = constants.%.11] +// CHECK:STDOUT: %.loc39_14.3: %.3 = converted %C.ref, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Impls(constants.%V) { +// CHECK:STDOUT: %.Self => constants.%V +// CHECK:STDOUT: %V.2 => constants.%V +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@ImplicitAs.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(@Convert.%Dest) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @Convert(constants.%Dest, constants.%Self.2) { +// CHECK:STDOUT: %Dest => constants.%Dest +// CHECK:STDOUT: %.1 => constants.%.6 +// CHECK:STDOUT: %Self => constants.%Self.2 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @ImplicitAs(constants.%.3) { +// CHECK:STDOUT: %Dest => constants.%.3 +// CHECK:STDOUT: +// CHECK:STDOUT: !definition: +// CHECK:STDOUT: %.1 => constants.%.9 +// CHECK:STDOUT: %Self => constants.%Self.3 +// CHECK:STDOUT: %Convert.type => constants.%Convert.type.2 +// CHECK:STDOUT: %Convert => constants.%Convert.2 +// CHECK:STDOUT: %.2 => constants.%.10 +// CHECK:STDOUT: %.3 => constants.%.11 +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @EmptyStruct(constants.%Y) { +// CHECK:STDOUT: %.Self => constants.%Y +// CHECK:STDOUT: %Y.1 => constants.%Y +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/where_expr/no_prelude/designator.carbon b/toolchain/check/testdata/where_expr/no_prelude/designator.carbon new file mode 100644 index 000000000000..622180099333 --- /dev/null +++ b/toolchain/check/testdata/where_expr/no_prelude/designator.carbon @@ -0,0 +1,373 @@ +// Part of the Carbon Language project, under the Apache License v2.0 with LLVM +// Exceptions. See /LICENSE for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +// AUTOUPDATE +// TIP: To test this file alone, run: +// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/where_expr/no_prelude/designator.carbon +// TIP: To dump output, run: +// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/where_expr/no_prelude/designator.carbon + +// --- success.carbon + +library "[[@TEST_NAME]]"; + +interface I { + let Member:! type; +} + +fn PeriodSelf(T:! I where .Self == ()); + +fn PeriodMember(U:! I where .Member = {}); + +fn TypeSelfImpls(V:! type where .Self impls I); + +// --- fail_wrong_member.carbon + +library "[[@TEST_NAME]]"; + +interface J { + let Member:! type; +} + +// CHECK:STDERR: fail_wrong_member.carbon:[[@LINE+4]]:31: error: name `Mismatch` not found +// CHECK:STDERR: fn PeriodMismatch(W:! J where .Mismatch = {}); +// CHECK:STDERR: ^~~~~~~~~ +// CHECK:STDERR: +fn PeriodMismatch(W:! J where .Mismatch = {}); + +// --- fail_designator_matches_var.carbon + +library "[[@TEST_NAME]]"; + +fn Foo() -> () { + var x: (); + // CHECK:STDERR: fail_designator_matches_var.carbon:[[@LINE+5]]:10: error: name `.Self` not found + // CHECK:STDERR: return .x; + // CHECK:STDERR: ^~ + // CHECK:STDERR: fail_designator_matches_var.carbon: note: designator may only be used when `.Self` is in scope + // CHECK:STDERR: + return .x; +} + +// --- fail_unknown_designator.carbon + +library "[[@TEST_NAME]]"; + +fn Bar() -> () { + // CHECK:STDERR: fail_unknown_designator.carbon:[[@LINE+5]]:10: error: name `.Self` not found + // CHECK:STDERR: return .undef; + // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: fail_unknown_designator.carbon: note: designator may only be used when `.Self` is in scope + // CHECK:STDERR: + return .undef; +} + +// --- fail_dot_self_method_return_value.carbon + +library "[[@TEST_NAME]]"; + +class C { + // CHECK:STDERR: fail_dot_self_method_return_value.carbon:[[@LINE+4]]:27: error: name `.Self` not found + // CHECK:STDERR: fn F() -> Self { return .Self; } + // CHECK:STDERR: ^~~~~ + // CHECK:STDERR: + fn F() -> Self { return .Self; } +} + +// --- fail_dot_self_method_return_type.carbon + +library "[[@TEST_NAME]]"; + +class D { + // CHECK:STDERR: fail_dot_self_method_return_type.carbon:[[@LINE+3]]:13: error: name `.Self` not found + // CHECK:STDERR: fn G() -> .Self { return Self; } + // CHECK:STDERR: ^~~~~ + fn G() -> .Self { return Self; } +} + +// CHECK:STDOUT: --- success.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @I [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = assoc_entity_type %.1, type [template] +// CHECK:STDOUT: %.3: %.2 = assoc_entity element0, @I.%Member [template] +// CHECK:STDOUT: %.Self.1: %.1 = bind_symbolic_name .Self 0 [symbolic] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %T: %.1 = bind_symbolic_name T 0 [symbolic] +// CHECK:STDOUT: %PeriodSelf.type: type = fn_type @PeriodSelf [template] +// CHECK:STDOUT: %PeriodSelf: %PeriodSelf.type = struct_value () [template] +// CHECK:STDOUT: %.5: type = struct_type {} [template] +// CHECK:STDOUT: %U: %.1 = bind_symbolic_name U 0 [symbolic] +// CHECK:STDOUT: %PeriodMember.type: type = fn_type @PeriodMember [template] +// CHECK:STDOUT: %PeriodMember: %PeriodMember.type = struct_value () [template] +// CHECK:STDOUT: %.Self.2: type = bind_symbolic_name .Self 0 [symbolic] +// CHECK:STDOUT: %V: type = bind_symbolic_name V 0 [symbolic] +// CHECK:STDOUT: %TypeSelfImpls.type: type = fn_type @TypeSelfImpls [template] +// CHECK:STDOUT: %TypeSelfImpls: %TypeSelfImpls.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .I = %I.decl +// CHECK:STDOUT: .PeriodSelf = %PeriodSelf.decl +// CHECK:STDOUT: .PeriodMember = %PeriodMember.decl +// CHECK:STDOUT: .TypeSelfImpls = %TypeSelfImpls.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %I.decl: type = interface_decl @I [template = constants.%.1] {} +// CHECK:STDOUT: %PeriodSelf.decl: %PeriodSelf.type = fn_decl @PeriodSelf [template = constants.%PeriodSelf] { +// CHECK:STDOUT: %I.ref.loc8: type = name_ref I, %I.decl [template = constants.%.1] +// CHECK:STDOUT: %.Self.1: %.1 = bind_symbolic_name .Self 0 [symbolic = @PeriodSelf.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %.Self.ref.loc8: %.1 = name_ref .Self, %.Self.1 [symbolic = @PeriodSelf.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %.loc8: %.4 = tuple_literal () +// CHECK:STDOUT: %T.loc8_15.1: %.1 = param T, runtime_param +// CHECK:STDOUT: @PeriodSelf.%T.loc8: %.1 = bind_symbolic_name T 0, %T.loc8_15.1 [symbolic = @PeriodSelf.%T.1 (constants.%T)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %PeriodMember.decl: %PeriodMember.type = fn_decl @PeriodMember [template = constants.%PeriodMember] { +// CHECK:STDOUT: %I.ref.loc10: type = name_ref I, %I.decl [template = constants.%.1] +// CHECK:STDOUT: %.Self.2: %.1 = bind_symbolic_name .Self 0 [symbolic = @PeriodMember.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %.Self.ref.loc10: %.1 = name_ref .Self, %.Self.2 [symbolic = @PeriodMember.%.Self (constants.%.Self.1)] +// CHECK:STDOUT: %Member.ref: %.2 = name_ref Member, @I.%.loc5 [template = constants.%.3] +// CHECK:STDOUT: %.loc10: %.5 = struct_literal () +// CHECK:STDOUT: %U.loc10_17.1: %.1 = param U, runtime_param +// CHECK:STDOUT: @PeriodMember.%U.loc10: %.1 = bind_symbolic_name U 0, %U.loc10_17.1 [symbolic = @PeriodMember.%U.1 (constants.%U)] +// CHECK:STDOUT: } +// CHECK:STDOUT: %TypeSelfImpls.decl: %TypeSelfImpls.type = fn_decl @TypeSelfImpls [template = constants.%TypeSelfImpls] { +// CHECK:STDOUT: %.Self.3: type = bind_symbolic_name .Self 0 [symbolic = @TypeSelfImpls.%.Self (constants.%.Self.2)] +// CHECK:STDOUT: %.Self.ref.loc12: type = name_ref .Self, %.Self.3 [symbolic = @TypeSelfImpls.%.Self (constants.%.Self.2)] +// CHECK:STDOUT: %I.ref.loc12: type = name_ref I, %I.decl [template = constants.%.1] +// CHECK:STDOUT: %V.loc12_18.1: type = param V, runtime_param +// CHECK:STDOUT: @TypeSelfImpls.%V.loc12: type = bind_symbolic_name V 0, %V.loc12_18.1 [symbolic = @TypeSelfImpls.%V.1 (constants.%V)] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @I { +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %Member: type = assoc_const_decl Member [template] +// CHECK:STDOUT: %.loc5: %.2 = assoc_entity element0, %Member [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Member = %.loc5 +// CHECK:STDOUT: witness = (%Member) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @PeriodSelf(%T.loc8: %.1) { +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.1)] +// CHECK:STDOUT: %T.1: %.1 = bind_symbolic_name T 0 [symbolic = %T.1 (constants.%T)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%T.loc8: %.1); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @PeriodMember(%U.loc10: %.1) { +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.1)] +// CHECK:STDOUT: %U.1: %.1 = bind_symbolic_name U 0 [symbolic = %U.1 (constants.%U)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%U.loc10: %.1); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @TypeSelfImpls(%V.loc12: type) { +// CHECK:STDOUT: %.Self: type = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self.2)] +// CHECK:STDOUT: %V.1: type = bind_symbolic_name V 0 [symbolic = %V.1 (constants.%V)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%V.loc12: type); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @PeriodSelf(constants.%T) { +// CHECK:STDOUT: %.Self => constants.%T +// CHECK:STDOUT: %T.1 => constants.%T +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @PeriodMember(constants.%U) { +// CHECK:STDOUT: %.Self => constants.%U +// CHECK:STDOUT: %U.1 => constants.%U +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @TypeSelfImpls(constants.%V) { +// CHECK:STDOUT: %.Self => constants.%V +// CHECK:STDOUT: %V.1 => constants.%V +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_wrong_member.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = interface_type @J [template] +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic] +// CHECK:STDOUT: %.2: type = assoc_entity_type %.1, type [template] +// CHECK:STDOUT: %.3: %.2 = assoc_entity element0, @J.%Member [template] +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic] +// CHECK:STDOUT: %.4: type = tuple_type () [template] +// CHECK:STDOUT: %.5: type = struct_type {} [template] +// CHECK:STDOUT: %W: %.1 = bind_symbolic_name W 0 [symbolic] +// CHECK:STDOUT: %PeriodMismatch.type: type = fn_type @PeriodMismatch [template] +// CHECK:STDOUT: %PeriodMismatch: %PeriodMismatch.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .J = %J.decl +// CHECK:STDOUT: .PeriodMismatch = %PeriodMismatch.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %J.decl: type = interface_decl @J [template = constants.%.1] {} +// CHECK:STDOUT: %PeriodMismatch.decl: %PeriodMismatch.type = fn_decl @PeriodMismatch [template = constants.%PeriodMismatch] { +// CHECK:STDOUT: %J.ref: type = name_ref J, %J.decl [template = constants.%.1] +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = @PeriodMismatch.%.Self (constants.%.Self)] +// CHECK:STDOUT: %.Self.ref: %.1 = name_ref .Self, %.Self [symbolic = @PeriodMismatch.%.Self (constants.%.Self)] +// CHECK:STDOUT: %Mismatch.ref: = name_ref Mismatch, [template = ] +// CHECK:STDOUT: %.loc12: %.5 = struct_literal () +// CHECK:STDOUT: %W.loc12_19.1: %.1 = param W, runtime_param +// CHECK:STDOUT: @PeriodMismatch.%W.loc12: %.1 = bind_symbolic_name W 0, %W.loc12_19.1 [symbolic = @PeriodMismatch.%W.1 (constants.%W)] +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: interface @J { +// CHECK:STDOUT: %Self: %.1 = bind_symbolic_name Self 0 [symbolic = constants.%Self] +// CHECK:STDOUT: %Member: type = assoc_const_decl Member [template] +// CHECK:STDOUT: %.loc5: %.2 = assoc_entity element0, %Member [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = %Self +// CHECK:STDOUT: .Member = %.loc5 +// CHECK:STDOUT: witness = (%Member) +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: generic fn @PeriodMismatch(%W.loc12: %.1) { +// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = %.Self (constants.%.Self)] +// CHECK:STDOUT: %W.1: %.1 = bind_symbolic_name W 0 [symbolic = %W.1 (constants.%W)] +// CHECK:STDOUT: +// CHECK:STDOUT: fn(%W.loc12: %.1); +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: specific @PeriodMismatch(constants.%W) { +// CHECK:STDOUT: %.Self => constants.%W +// CHECK:STDOUT: %W.1 => constants.%W +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_designator_matches_var.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] +// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Foo = %Foo.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Foo.decl: %Foo.type = fn_decl @Foo [template = constants.%Foo] { +// CHECK:STDOUT: %.loc4_14.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc4_14.2: type = converted %.loc4_14.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: @Foo.%return: ref %.1 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Foo() -> %.1 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.loc5_11.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc5_11.2: type = converted %.loc5_11.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: %x.var: ref %.1 = var x +// CHECK:STDOUT: %x: ref %.1 = bind_name x, %x.var +// CHECK:STDOUT: %.Self.ref: = name_ref .Self, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_unknown_designator.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %Bar.type: type = fn_type @Bar [template] +// CHECK:STDOUT: %Bar: %Bar.type = struct_value () [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .Bar = %Bar.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %Bar.decl: %Bar.type = fn_decl @Bar [template = constants.%Bar] { +// CHECK:STDOUT: %.loc4_14.1: %.1 = tuple_literal () +// CHECK:STDOUT: %.loc4_14.2: type = converted %.loc4_14.1, constants.%.1 [template = constants.%.1] +// CHECK:STDOUT: @Bar.%return: ref %.1 = var +// CHECK:STDOUT: } +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @Bar() -> %.1 { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.Self.ref: = name_ref .Self, [template = ] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_dot_self_method_return_value.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %C: type = class_type @C [template] +// CHECK:STDOUT: %F.type: type = fn_type @F [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %F: %F.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] +// CHECK:STDOUT: %.4: type = ptr_type %.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .C = %C.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %C.decl: type = class_decl @C [template = constants.%C] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @C { +// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C] +// CHECK:STDOUT: %return.var: ref %C = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc10: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%C +// CHECK:STDOUT: .F = %F.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @F() -> @C.%return.var: %C { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %.Self.ref: = name_ref .Self, [template = ] +// CHECK:STDOUT: return to @C.%return.var +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: --- fail_dot_self_method_return_type.carbon +// CHECK:STDOUT: +// CHECK:STDOUT: constants { +// CHECK:STDOUT: %D: type = class_type @D [template] +// CHECK:STDOUT: %G.type: type = fn_type @G [template] +// CHECK:STDOUT: %.1: type = tuple_type () [template] +// CHECK:STDOUT: %G: %G.type = struct_value () [template] +// CHECK:STDOUT: %.2: type = struct_type {} [template] +// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: file { +// CHECK:STDOUT: package: = namespace [template] { +// CHECK:STDOUT: .D = %D.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: %D.decl: type = class_decl @D [template = constants.%D] {} +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: class @D { +// CHECK:STDOUT: %G.decl: %G.type = fn_decl @G [template = constants.%G] { +// CHECK:STDOUT: %.Self.ref: = name_ref .Self, [template = ] +// CHECK:STDOUT: %return.var: ref = var +// CHECK:STDOUT: } +// CHECK:STDOUT: %.loc9: = complete_type_witness %.2 [template = constants.%.3] +// CHECK:STDOUT: +// CHECK:STDOUT: !members: +// CHECK:STDOUT: .Self = constants.%D +// CHECK:STDOUT: .G = %G.decl +// CHECK:STDOUT: } +// CHECK:STDOUT: +// CHECK:STDOUT: fn @G() -> { +// CHECK:STDOUT: !entry: +// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%D [template = constants.%D] +// CHECK:STDOUT: return +// CHECK:STDOUT: } +// CHECK:STDOUT: diff --git a/toolchain/check/testdata/where_expr/no_prelude/fail_designator.carbon b/toolchain/check/testdata/where_expr/no_prelude/fail_designator.carbon deleted file mode 100644 index e084fd6ab9c3..000000000000 --- a/toolchain/check/testdata/where_expr/no_prelude/fail_designator.carbon +++ /dev/null @@ -1,129 +0,0 @@ -// Part of the Carbon Language project, under the Apache License v2.0 with LLVM -// Exceptions. See /LICENSE for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -// AUTOUPDATE -// TIP: To test this file alone, run: -// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/where_expr/no_prelude/fail_designator.carbon -// TIP: To dump output, run: -// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/where_expr/no_prelude/fail_designator.carbon - -// --- fail_designator_matches_var.carbon - -library "[[@TEST_NAME]]"; - -fn Foo() -> () { - var x: (); - // CHECK:STDERR: fail_designator_matches_var.carbon:[[@LINE+4]]:10: error: semantics TODO: `HandleDesignatorExpr` - // CHECK:STDERR: return .x; - // CHECK:STDERR: ^~ - // CHECK:STDERR: - return .x; -} - -// --- fail_unknown_designator.carbon - -library "[[@TEST_NAME]]"; - -fn Bar() -> () { - // CHECK:STDERR: fail_unknown_designator.carbon:[[@LINE+4]]:10: error: semantics TODO: `HandleDesignatorExpr` - // CHECK:STDERR: return .undef; - // CHECK:STDERR: ^~~~~~ - // CHECK:STDERR: - return .undef; -} - -// --- fail_dot_self_method_return_value.carbon - -library "[[@TEST_NAME]]"; - -class C { - // CHECK:STDERR: fail_dot_self_method_return_value.carbon:[[@LINE+4]]:28: error: semantics TODO: `HandleSelfTypeName` - // CHECK:STDERR: fn F() -> Self { return .Self; } - // CHECK:STDERR: ^~~~ - // CHECK:STDERR: - fn F() -> Self { return .Self; } -} - -// --- fail_dot_self_method_return_type.carbon - -library "[[@TEST_NAME]]"; - -class D { - // CHECK:STDERR: fail_dot_self_method_return_type.carbon:[[@LINE+3]]:14: error: semantics TODO: `HandleSelfTypeName` - // CHECK:STDERR: fn G() -> .Self { return Self; } - // CHECK:STDERR: ^~~~ - fn G() -> .Self { return Self; } -} - -// CHECK:STDOUT: --- fail_designator_matches_var.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %Foo.type: type = fn_type @Foo [template] -// CHECK:STDOUT: %Foo: %Foo.type = struct_value () [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file {} -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Foo() -> %.1 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_unknown_designator.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %Bar.type: type = fn_type @Bar [template] -// CHECK:STDOUT: %Bar: %Bar.type = struct_value () [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file {} -// CHECK:STDOUT: -// CHECK:STDOUT: fn @Bar() -> %.1 { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_dot_self_method_return_value.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %C: type = class_type @C [template] -// CHECK:STDOUT: %F.type: type = fn_type @F [template] -// CHECK:STDOUT: %.1: type = tuple_type () [template] -// CHECK:STDOUT: %F: %F.type = struct_value () [template] -// CHECK:STDOUT: %.2: type = struct_type {} [template] -// CHECK:STDOUT: %.3: = complete_type_witness %.2 [template] -// CHECK:STDOUT: %.4: type = ptr_type %.2 [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file {} -// CHECK:STDOUT: -// CHECK:STDOUT: class @C { -// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [template = constants.%F] { -// CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%C [template = constants.%C] -// CHECK:STDOUT: %return.var: ref %C = var -// CHECK:STDOUT: } -// CHECK:STDOUT: %.loc10: = complete_type_witness %.2 [template = constants.%.3] -// CHECK:STDOUT: -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%C -// CHECK:STDOUT: .F = %F.decl -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: fn @F() -> @C.%return.var: %C { -// CHECK:STDOUT: !entry: -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: --- fail_dot_self_method_return_type.carbon -// CHECK:STDOUT: -// CHECK:STDOUT: constants { -// CHECK:STDOUT: %D: type = class_type @D [template] -// CHECK:STDOUT: } -// CHECK:STDOUT: -// CHECK:STDOUT: file {} -// CHECK:STDOUT: -// CHECK:STDOUT: class @D { -// CHECK:STDOUT: !members: -// CHECK:STDOUT: .Self = constants.%D -// CHECK:STDOUT: } -// CHECK:STDOUT: diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index e01f3386d00d..2092ed7765aa 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -265,6 +265,9 @@ CARBON_DIAGNOSTIC_KIND(QualifiedDeclInUndefinedInterfaceScope) // Name lookup. CARBON_DIAGNOSTIC_KIND(InNameLookup) +CARBON_DIAGNOSTIC_KIND(NameAmbiguousDueToExtend) +CARBON_DIAGNOSTIC_KIND(NameNotFound) +CARBON_DIAGNOSTIC_KIND(NoPeriodSelfForDesignator) CARBON_DIAGNOSTIC_KIND(AddrOfEphemeralRef) CARBON_DIAGNOSTIC_KIND(AddrOfNonRef) @@ -292,8 +295,6 @@ CARBON_DIAGNOSTIC_KIND(CompileTimeBindingInVarDecl) CARBON_DIAGNOSTIC_KIND(CompoundMemberAccessDoesNotUseBase) CARBON_DIAGNOSTIC_KIND(RealMantissaTooLargeForI64) CARBON_DIAGNOSTIC_KIND(RealExponentTooLargeForI64) -CARBON_DIAGNOSTIC_KIND(NameAmbiguousDueToExtend) -CARBON_DIAGNOSTIC_KIND(NameNotFound) CARBON_DIAGNOSTIC_KIND(NameDeclDuplicate) CARBON_DIAGNOSTIC_KIND(NameDeclPrevious) CARBON_DIAGNOSTIC_KIND(RepeatedConst) diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 4af6dd102d20..37bfee3d8239 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -513,6 +513,8 @@ struct NameId : public IdBase, public Printable { static const NameId SelfValue; // The name of `Self`. static const NameId SelfType; + // The name of `.Self`. + static const NameId PeriodSelf; // The name of the return slot in a function. static const NameId ReturnSlot; // The name of `package`. @@ -549,6 +551,8 @@ struct NameId : public IdBase, public Printable { out << "SelfValue"; } else if (*this == SelfType) { out << "SelfType"; + } else if (*this == PeriodSelf) { + out << "PeriodSelf"; } else if (*this == ReturnSlot) { out << "ReturnSlot"; } else if (*this == PackageNamespace) { @@ -565,10 +569,11 @@ struct NameId : public IdBase, public Printable { constexpr NameId NameId::Invalid = NameId(InvalidIndex); constexpr NameId NameId::SelfValue = NameId(InvalidIndex - 1); constexpr NameId NameId::SelfType = NameId(InvalidIndex - 2); -constexpr NameId NameId::ReturnSlot = NameId(InvalidIndex - 3); -constexpr NameId NameId::PackageNamespace = NameId(InvalidIndex - 4); -constexpr NameId NameId::Base = NameId(InvalidIndex - 5); -constexpr int NameId::NonIndexValueCount = 6; +constexpr NameId NameId::PeriodSelf = NameId(InvalidIndex - 3); +constexpr NameId NameId::ReturnSlot = NameId(InvalidIndex - 4); +constexpr NameId NameId::PackageNamespace = NameId(InvalidIndex - 5); +constexpr NameId NameId::Base = NameId(InvalidIndex - 6); +constexpr int NameId::NonIndexValueCount = 7; // Enforce the link between SpecialValueCount and the last special value. static_assert(NameId::NonIndexValueCount == -NameId::Base.index); diff --git a/toolchain/sem_ir/name.cpp b/toolchain/sem_ir/name.cpp index 088580021367..a2dba588c0fa 100644 --- a/toolchain/sem_ir/name.cpp +++ b/toolchain/sem_ir/name.cpp @@ -17,6 +17,8 @@ static auto GetSpecialName(NameId name_id, bool for_ir) -> llvm::StringRef { return "self"; case NameId::SelfType.index: return "Self"; + case NameId::PeriodSelf.index: + return ".Self"; case NameId::ReturnSlot.index: return for_ir ? "return" : ""; case NameId::PackageNamespace.index: