Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

where check stage, step 2: SemIR #4349

Merged
merged 31 commits into from
Sep 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
343ddaa
Checkpoint progress.
josh11b Sep 19, 2024
cddc74a
Checkpoint progress.
josh11b Sep 19, 2024
c28c94d
Checkpoint progress.
josh11b Sep 19, 2024
b5c880e
Checkpoint progress.
josh11b Sep 19, 2024
69448d3
Add tests
josh11b Sep 19, 2024
9a54bb4
Merge remote-tracking branch 'upstream/trunk' into whereck
josh11b Sep 19, 2024
e88fd4c
Fix formatting
josh11b Sep 20, 2024
c7959f1
Checkpoint progress.
josh11b Sep 20, 2024
7a009a5
Apply suggestions from code review
josh11b Sep 20, 2024
b9c2b6d
Fix formatting
josh11b Sep 20, 2024
ca5b74a
Checkpoint progress.
josh11b Sep 20, 2024
fa152c0
Expand testing
josh11b Sep 20, 2024
70e51ca
Checkpoint progress.
josh11b Sep 20, 2024
3f2e092
Checkpoint progress.
josh11b Sep 20, 2024
8d2b455
Use HandleNameAsExpr, plus fixes
josh11b Sep 23, 2024
3c37013
TODO comment better
josh11b Sep 23, 2024
7a81ddf
Checkpoint progress.
josh11b Sep 23, 2024
3c81839
Simplify
josh11b Sep 23, 2024
531e5b5
Note on error
josh11b Sep 24, 2024
6bf6262
Remove FIXME
josh11b Sep 24, 2024
67cfc6b
Merge branch 'whereck' into req
josh11b Sep 24, 2024
3d2c642
Checkpoint progress.
josh11b Sep 25, 2024
45a000e
Merge remote-tracking branch 'upstream/trunk' into req
josh11b Sep 25, 2024
41e42af
Checkpoint progress.
josh11b Sep 25, 2024
c0cce9c
Checkpoint progress.
josh11b Sep 25, 2024
475cd90
Tests pass
josh11b Sep 26, 2024
218d4ca
Merge remote-tracking branch 'upstream/trunk' into req
josh11b Sep 26, 2024
af1685c
Attempt to fix instruction naming
josh11b Sep 26, 2024
eda6945
Checkpoint progress.
josh11b Sep 26, 2024
044ad96
Fix instruction formatting
josh11b Sep 26, 2024
c55078f
Use the `.Self` symbolic binding as 1st arg of `WhereExpr`
josh11b Sep 26, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 6 additions & 4 deletions toolchain/check/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1073,10 +1073,12 @@ class TypeCompleter {
}

template <typename InstT>
requires(InstT::Kind.template IsAnyOf<
SemIR::AssociatedEntityType, SemIR::FunctionType,
SemIR::GenericClassType, SemIR::GenericInterfaceType,
SemIR::InterfaceType, SemIR::UnboundElementType>())
requires(
InstT::Kind
.template IsAnyOf<SemIR::AssociatedEntityType, SemIR::FunctionType,
SemIR::GenericClassType,
SemIR::GenericInterfaceType, SemIR::InterfaceType,
SemIR::UnboundElementType, SemIR::WhereExpr>())
auto BuildValueReprForInst(SemIR::TypeId /*type_id*/, InstT /*inst*/) const
-> SemIR::ValueRepr {
// These types have no runtime operations, so we use an empty value
Expand Down
9 changes: 9 additions & 0 deletions toolchain/check/eval.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,12 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id,
// here. For now, we model a facet value as just a type.
return eval_context.GetConstantValue(typed_inst.facet_id);
}
case CARBON_KIND(SemIR::WhereExpr typed_inst): {
// TODO: This currently ignores the requirements and just produces the
// left-hand type argument to the `where`.
return eval_context.GetConstantValue(
eval_context.insts().Get(typed_inst.period_self_id).type_id());
}

// `not true` -> `false`, `not false` -> `true`.
// All other uses of unary `not` are non-constant.
Expand Down Expand Up @@ -1446,6 +1452,9 @@ auto TryEvalInstInContext(EvalContext& eval_context, SemIR::InstId inst_id,
case SemIR::ImplDecl::Kind:
case SemIR::ImportDecl::Kind:
case SemIR::Param::Kind:
case SemIR::RequirementEquivalent::Kind:
case SemIR::RequirementImpls::Kind:
case SemIR::RequirementRewrite::Kind:
case SemIR::ReturnExpr::Kind:
case SemIR::Return::Kind:
case SemIR::StructLiteral::Kind:
Expand Down
68 changes: 48 additions & 20 deletions toolchain/check/handle_where.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@

namespace Carbon::Check {

auto HandleParseNode(Context& context, Parse::WhereOperandId /*node_id*/)
-> bool {
auto HandleParseNode(Context& context, Parse::WhereOperandId node_id) -> bool {
// 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);
// TODO: Validate that `self_type_id` represents a facet type. Only facet
// types may have `where` restrictions.

// 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.
Expand All @@ -43,30 +41,54 @@ auto HandleParseNode(Context& context, Parse::WhereOperandId /*node_id*/)
context.scope_stack().LookupOrAddName(SemIR::NameId::PeriodSelf, inst_id);
// Shouldn't have any names in newly created scope.
CARBON_CHECK(!existing.is_valid());

// Save the `.Self` symbolic binding on the node stack. It will become the
// first argument to the `WhereExpr` instruction.
context.node_stack().Push(node_id, inst_id);

// Going to put each requirement on `args_type_info_stack`, so we can have an
// inst block with the varying number of requirements but keeping other
// instructions on the current inst block from the `inst_block_stack()`.
context.args_type_info_stack().Push();
return true;
}

auto HandleParseNode(Context& context, Parse::RequirementEqualId /*node_id*/)
auto HandleParseNode(Context& context, Parse::RequirementEqualId node_id)
-> bool {
// TODO: Implement
context.node_stack().PopExpr();
context.node_stack().PopExpr();
auto rhs = context.node_stack().PopExpr();
auto lhs = context.node_stack().PopExpr();
// TODO: convert rhs to type of lhs

// Build up the list of arguments for the `WhereExpr` inst.
context.args_type_info_stack().AddInstId(
context.AddInstInNoBlock<SemIR::RequirementRewrite>(
node_id, {.lhs_id = lhs, .rhs_id = rhs}));
return true;
}

auto HandleParseNode(Context& context,
Parse::RequirementEqualEqualId /*node_id*/) -> bool {
// TODO: Implement
context.node_stack().PopExpr();
context.node_stack().PopExpr();
auto HandleParseNode(Context& context, Parse::RequirementEqualEqualId node_id)
-> bool {
auto rhs = context.node_stack().PopExpr();
auto lhs = context.node_stack().PopExpr();
// TODO: type check lhs and rhs are compatible

// Build up the list of arguments for the `WhereExpr` inst.
context.args_type_info_stack().AddInstId(
context.AddInstInNoBlock<SemIR::RequirementEquivalent>(
node_id, {.lhs_id = lhs, .rhs_id = rhs}));
return true;
}

auto HandleParseNode(Context& context, Parse::RequirementImplsId /*node_id*/)
auto HandleParseNode(Context& context, Parse::RequirementImplsId node_id)
-> bool {
// TODO: Implement
context.node_stack().PopExpr();
context.node_stack().PopExpr();
auto rhs = context.node_stack().PopExpr();
auto lhs = context.node_stack().PopExpr();
// TODO: check lhs is a facet and rhs is a facet type

// Build up the list of arguments for the `WhereExpr` inst.
context.args_type_info_stack().AddInstId(
context.AddInstInNoBlock<SemIR::RequirementImpls>(
node_id, {.lhs_id = lhs, .rhs_id = rhs}));
return true;
}

Expand All @@ -76,14 +98,20 @@ auto HandleParseNode(Context& /*context*/, Parse::RequirementAndId /*node_id*/)
return true;
}

auto HandleParseNode(Context& context, Parse::WhereExprId /*node_id*/) -> bool {
auto HandleParseNode(Context& context, Parse::WhereExprId node_id) -> bool {
// Discard the generic region containing `.Self` and the constraints.
// TODO: Decide if we want to build a `Generic` object for this.
DiscardGenericDecl(context);
// 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.
SemIR::InstId period_self_id =
context.node_stack().Pop<Parse::NodeKind::WhereOperand>();
SemIR::InstBlockId requirements_id = context.args_type_info_stack().Pop();
context.AddInstAndPush<SemIR::WhereExpr>(
node_id, {.type_id = SemIR::TypeId::TypeType,
.period_self_id = period_self_id,
.requirements_id = requirements_id});
return true;
}

Expand Down
3 changes: 1 addition & 2 deletions toolchain/check/node_stack.h
Original file line number Diff line number Diff line change
Expand Up @@ -425,6 +425,7 @@ class NodeStack {
case Parse::NodeKind::ShortCircuitOperandOr:
case Parse::NodeKind::StructField:
case Parse::NodeKind::StructTypeField:
case Parse::NodeKind::WhereOperand:
return Id::KindFor<SemIR::InstId>();
case Parse::NodeKind::IfCondition:
case Parse::NodeKind::IfExprIf:
Expand All @@ -449,8 +450,6 @@ class NodeStack {
case Parse::NodeKind::DefaultLibrary:
case Parse::NodeKind::LibraryName:
return Id::KindFor<SemIR::LibraryNameId>();
case Parse::NodeKind::WhereOperand:
return Id::KindFor<SemIR::TypeId>();
case Parse::NodeKind::ArrayExprSemi:
case Parse::NodeKind::BuiltinName:
case Parse::NodeKind::ClassIntroducer:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ impl bool as I where .T = bool {}
// 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: %.loc16_16: type = where_expr %.Self [template = constants.%.1] {
// CHECK:STDOUT: requirement_rewrite %T.ref, %bool.make_type.loc16_27
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
Expand Down
43 changes: 31 additions & 12 deletions toolchain/check/testdata/where_expr/constraints.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,10 @@ fn NotEmptyStruct() {
// CHECK:STDOUT: %.Self: %.2 = bind_symbolic_name .Self 0 [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %.Self.ref: %.2 = name_ref .Self, %.Self [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %Member.ref: %.3 = name_ref Member, @I.%.loc7 [template = constants.%.4]
// CHECK:STDOUT: %.loc11: %.8 = struct_literal ()
// CHECK:STDOUT: %.loc11_33: %.8 = struct_literal ()
// CHECK:STDOUT: %.loc11_16: type = where_expr %.Self [template = constants.%.2] {
// CHECK:STDOUT: requirement_rewrite %Member.ref, %.loc11_33
// CHECK:STDOUT: }
// CHECK:STDOUT: %T.param: %.2 = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc11: %.2 = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T)]
// CHECK:STDOUT: }
Expand All @@ -151,7 +154,10 @@ fn NotEmptyStruct() {
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.2]
// CHECK:STDOUT: %.Self: %.2 = bind_symbolic_name .Self 0 [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %.Self.ref: %.2 = name_ref .Self, %.Self [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %.loc13: %.5 = tuple_literal ()
// CHECK:STDOUT: %.loc13_37: %.5 = tuple_literal ()
// CHECK:STDOUT: %.loc13_21: type = where_expr %.Self [template = constants.%.2] {
// CHECK:STDOUT: requirement_equivalent %.Self.ref, %.loc13_37
// CHECK:STDOUT: }
// CHECK:STDOUT: %U.param: %.2 = param U, runtime_param<invalid>
// CHECK:STDOUT: %U.loc13: %.2 = bind_symbolic_name U 0, %U.param [symbolic = %U.1 (constants.%U)]
// CHECK:STDOUT: }
Expand All @@ -162,6 +168,9 @@ fn NotEmptyStruct() {
// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = constants.%.Self.2]
// CHECK:STDOUT: %.Self.ref: %.1 = name_ref .Self, %.Self [symbolic = constants.%.Self.2]
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.2]
// CHECK:STDOUT: %.loc15: type = where_expr %.Self [template = constants.%.1] {
// CHECK:STDOUT: requirement_impls %.Self.ref, %I.ref
// CHECK:STDOUT: }
// CHECK:STDOUT: %V.param: %.1 = param V, runtime_param<invalid>
// CHECK:STDOUT: %V.loc15: %.1 = bind_symbolic_name V 0, %V.param [symbolic = %V.1 (constants.%V)]
// CHECK:STDOUT: }
Expand All @@ -177,6 +186,10 @@ fn NotEmptyStruct() {
// CHECK:STDOUT: %Member.ref: %.3 = name_ref Member, @I.%.loc7 [template = constants.%.4]
// CHECK:STDOUT: %.Self.ref.loc17_50: %.2 = name_ref .Self, %.Self [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %Second.ref.loc17_50: %.6 = name_ref Second, @I.%.loc8 [template = constants.%.7]
// CHECK:STDOUT: %.loc17: type = where_expr %.Self [template = constants.%.2] {
// CHECK:STDOUT: requirement_impls %Second.ref.loc17_20, %I.ref.loc17_34
// CHECK:STDOUT: requirement_rewrite %Member.ref, %Second.ref.loc17_50
// CHECK:STDOUT: }
// CHECK:STDOUT: %W.param: %.2 = param W, runtime_param<invalid>
// CHECK:STDOUT: %W.loc17: %.2 = bind_symbolic_name W 0, %W.param [symbolic = %W.1 (constants.%W)]
// CHECK:STDOUT: }
Expand Down Expand Up @@ -263,10 +276,10 @@ fn NotEmptyStruct() {
// 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+32, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref Main//state_constraints, inst+44, unloaded
// CHECK:STDOUT: %import_ref.5 = import_ref Main//state_constraints, inst+57, unloaded
// CHECK:STDOUT: %import_ref.6 = import_ref Main//state_constraints, inst+74, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref Main//state_constraints, inst+34, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref Main//state_constraints, inst+48, unloaded
// CHECK:STDOUT: %import_ref.5 = import_ref Main//state_constraints, inst+63, unloaded
// CHECK:STDOUT: %import_ref.6 = import_ref Main//state_constraints, inst+83, unloaded
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/operators
Expand Down Expand Up @@ -305,7 +318,10 @@ fn NotEmptyStruct() {
// 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: %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: %.loc8_39: i32 = int_literal 2 [template = constants.%.5]
// CHECK:STDOUT: %.loc8_23: type = where_expr %.Self [template = constants.%.1] {
// CHECK:STDOUT: requirement_rewrite %Member.ref, %.loc8_39
// CHECK:STDOUT: }
// CHECK:STDOUT: %X.param: %.1 = param X, runtime_param<invalid>
// CHECK:STDOUT: %X.loc8: %.1 = bind_symbolic_name X 0, %X.param [symbolic = %X.1 (constants.%X)]
// CHECK:STDOUT: }
Expand Down Expand Up @@ -371,10 +387,10 @@ fn NotEmptyStruct() {
// 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+32, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref Main//state_constraints, inst+44, unloaded
// CHECK:STDOUT: %import_ref.5: %Impls.type = import_ref Main//state_constraints, inst+57, loaded [template = constants.%Impls]
// CHECK:STDOUT: %import_ref.6 = import_ref Main//state_constraints, inst+74, unloaded
// CHECK:STDOUT: %import_ref.3 = import_ref Main//state_constraints, inst+34, unloaded
// CHECK:STDOUT: %import_ref.4 = import_ref Main//state_constraints, inst+48, unloaded
// CHECK:STDOUT: %import_ref.5: %Impls.type = import_ref Main//state_constraints, inst+63, loaded [template = constants.%Impls]
// CHECK:STDOUT: %import_ref.6 = import_ref Main//state_constraints, inst+83, unloaded
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [template] {
// CHECK:STDOUT: .ImplicitAs = %import_ref.8
// CHECK:STDOUT: import Core//prelude
Expand Down Expand Up @@ -423,7 +439,10 @@ fn NotEmptyStruct() {
// CHECK:STDOUT: %J.ref: type = name_ref J, imports.%import_ref.1 [template = constants.%.3]
// CHECK:STDOUT: %.Self: %.3 = bind_symbolic_name .Self 0 [symbolic = constants.%.Self]
// CHECK:STDOUT: %.Self.ref: %.3 = name_ref .Self, %.Self [symbolic = constants.%.Self]
// CHECK:STDOUT: %.loc26: %.1 = struct_literal ()
// CHECK:STDOUT: %.loc26_38: %.1 = struct_literal ()
// CHECK:STDOUT: %.loc26_22: type = where_expr %.Self [template = constants.%.3] {
// CHECK:STDOUT: requirement_equivalent %.Self.ref, %.loc26_38
// CHECK:STDOUT: }
// CHECK:STDOUT: %Y.param: %.3 = param Y, runtime_param<invalid>
// CHECK:STDOUT: %Y.loc26: %.3 = bind_symbolic_name Y 0, %Y.param [symbolic = %Y.1 (constants.%Y)]
// CHECK:STDOUT: }
Expand Down
18 changes: 15 additions & 3 deletions toolchain/check/testdata/where_expr/no_prelude/designator.carbon
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,10 @@ class D {
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1]
// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %.Self.ref: %.1 = name_ref .Self, %.Self [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %.loc8: %.4 = tuple_literal ()
// CHECK:STDOUT: %.loc8_37: %.4 = tuple_literal ()
// CHECK:STDOUT: %.loc8_21: type = where_expr %.Self [template = constants.%.1] {
// CHECK:STDOUT: requirement_equivalent %.Self.ref, %.loc8_37
// CHECK:STDOUT: }
// CHECK:STDOUT: %T.param: %.1 = param T, runtime_param<invalid>
// CHECK:STDOUT: %T.loc8: %.1 = bind_symbolic_name T 0, %T.param [symbolic = %T.1 (constants.%T)]
// CHECK:STDOUT: }
Expand All @@ -133,7 +136,10 @@ class D {
// CHECK:STDOUT: %.Self: %.1 = bind_symbolic_name .Self 0 [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %.Self.ref: %.1 = name_ref .Self, %.Self [symbolic = constants.%.Self.1]
// CHECK:STDOUT: %Member.ref: %.2 = name_ref Member, @I.%.loc5 [template = constants.%.3]
// CHECK:STDOUT: %.loc10: %.5 = struct_literal ()
// CHECK:STDOUT: %.loc10_40: %.5 = struct_literal ()
// CHECK:STDOUT: %.loc10_23: type = where_expr %.Self [template = constants.%.1] {
// CHECK:STDOUT: requirement_rewrite %Member.ref, %.loc10_40
// CHECK:STDOUT: }
// CHECK:STDOUT: %U.param: %.1 = param U, runtime_param<invalid>
// CHECK:STDOUT: %U.loc10: %.1 = bind_symbolic_name U 0, %U.param [symbolic = %U.1 (constants.%U)]
// CHECK:STDOUT: }
Expand All @@ -143,6 +149,9 @@ class D {
// CHECK:STDOUT: %.Self: type = bind_symbolic_name .Self 0 [symbolic = constants.%.Self.2]
// CHECK:STDOUT: %.Self.ref: type = name_ref .Self, %.Self [symbolic = constants.%.Self.2]
// CHECK:STDOUT: %I.ref: type = name_ref I, file.%I.decl [template = constants.%.1]
// CHECK:STDOUT: %.loc12: type = where_expr %.Self [template = type] {
// CHECK:STDOUT: requirement_impls %.Self.ref, %I.ref
// CHECK:STDOUT: }
// CHECK:STDOUT: %V.param: type = param V, runtime_param<invalid>
// CHECK:STDOUT: %V.loc12: type = bind_symbolic_name V 0, %V.param [symbolic = %V.1 (constants.%V)]
// CHECK:STDOUT: }
Expand Down Expand Up @@ -217,7 +226,10 @@ class D {
// 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: %Mismatch.ref: <error> = name_ref Mismatch, <error> [template = <error>]
// CHECK:STDOUT: %.loc12: %.5 = struct_literal ()
// CHECK:STDOUT: %.loc12_44: %.5 = struct_literal ()
// CHECK:STDOUT: %.loc12_25: type = where_expr %.Self [template = constants.%.1] {
// CHECK:STDOUT: requirement_rewrite %Mismatch.ref, %.loc12_44
// CHECK:STDOUT: }
// CHECK:STDOUT: %W.param: %.1 = param W, runtime_param<invalid>
// CHECK:STDOUT: %W.loc12: %.1 = bind_symbolic_name W 0, %W.param [symbolic = %W.1 (constants.%W)]
// CHECK:STDOUT: }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,10 @@ fn NotGenericF(U: I where .T = {}) {}
// 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: %.loc14: %.5 = struct_literal ()
// CHECK:STDOUT: %.loc14_33: %.5 = struct_literal ()
// CHECK:STDOUT: %.loc14_21: type = where_expr %.Self [template = constants.%.1] {
// CHECK:STDOUT: requirement_rewrite %T.ref, %.loc14_33
// CHECK:STDOUT: }
// CHECK:STDOUT: %U.param: %.1 = param U, runtime_param0
// CHECK:STDOUT: %U: %.1 = bind_name U, %U.param
// CHECK:STDOUT: }
Expand Down
2 changes: 1 addition & 1 deletion toolchain/lower/file_context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -499,7 +499,7 @@ template <typename InstT>
requires(InstT::Kind.template IsAnyOf<
SemIR::AssociatedEntityType, SemIR::FunctionType,
SemIR::GenericClassType, SemIR::GenericInterfaceType,
SemIR::InterfaceType, SemIR::UnboundElementType>())
SemIR::InterfaceType, SemIR::UnboundElementType, SemIR::WhereExpr>())
static auto BuildTypeForInst(FileContext& context, InstT /*inst*/)
-> llvm::Type* {
// Return an empty struct as a placeholder.
Expand Down
Loading
Loading