Convert the scrutinee of a binding pattern to the right category. (#5662)

When the binding pattern appears within a `var` pattern, convert to a
reference. Otherwise, convert to a value.

This gets the advent of code examples to produce the right answers again
:)

---------

Co-authored-by: Geoff Romer <gromer@google.com>
This commit is contained in:
Richard Smith
2025-06-17 16:45:19 +00:00
committed by GitHub
co-authored by Geoff Romer
parent 1c09de9b87
commit 80529aaef9
29 changed files with 317 additions and 260 deletions
+21
View File
@@ -696,6 +696,8 @@ static auto IsValidExprCategoryForConversionTarget(
category == SemIR::ExprCategory::DurableRef ||
category == SemIR::ExprCategory::EphemeralRef ||
category == SemIR::ExprCategory::Initializing;
case ConversionTarget::DurableRef:
return category == SemIR::ExprCategory::DurableRef;
case ConversionTarget::ExplicitAs:
return true;
case ConversionTarget::Initializer:
@@ -1340,12 +1342,19 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
// Commit to using a temporary for this initializing expression.
// TODO: Don't create a temporary if the initializing representation
// is already a value representation.
// TODO: If the target is DurableRef, materialize a VarStorage instead of
// a TemporaryStorage to lifetime-extend.
expr_id = FinalizeTemporary(context, expr_id,
target.kind == ConversionTarget::Discarded);
// We now have an ephemeral reference.
[[fallthrough]];
case SemIR::ExprCategory::DurableRef:
if (target.kind == ConversionTarget::DurableRef) {
break;
}
[[fallthrough]];
case SemIR::ExprCategory::EphemeralRef:
// If a reference expression is an acceptable result, we're done.
if (target.kind == ConversionTarget::ValueOrRef ||
@@ -1362,6 +1371,18 @@ auto Convert(Context& context, SemIR::LocId loc_id, SemIR::InstId expr_id,
[[fallthrough]];
case SemIR::ExprCategory::Value:
if (target.kind == ConversionTarget::DurableRef) {
if (target.diagnose) {
CARBON_DIAGNOSTIC(ConversionFailureNonRefToRef, Error,
"cannot bind durable reference to non-reference "
"value of type {0}",
SemIR::TypeId);
context.emitter().Emit(loc_id, ConversionFailureNonRefToRef,
target.type_id);
}
return SemIR::ErrorInst::InstId;
}
// When initializing from a value, perform a copy.
if (target.is_initializer()) {
expr_id = PerformCopy(context, expr_id, target.diagnose);
+2
View File
@@ -19,6 +19,8 @@ struct ConversionTarget {
Value,
// Convert to either a value or a reference of type `type_id`.
ValueOrRef,
// Convert to a durable reference of type `type_id`.
DurableRef,
// Convert for an explicit `as` cast. This allows any expression category
// as the result, and uses the `As` interface instead of the `ImplicitAs`
// interface.
+55 -22
View File
@@ -48,10 +48,13 @@ class MatchContext {
SemIR::InstId pattern_id;
// `None` when processing the callee side.
SemIR::InstId scrutinee_id;
// Whether we are in a context where plain bindings are reference bindings.
// This happens in var patterns.
bool ref_binding_context;
auto Print(llvm::raw_ostream& out) const -> void {
out << "{pattern_id: " << pattern_id << ", scrutinee_id: " << scrutinee_id
<< "}";
<< ", ref_binding_context: " << ref_binding_context << "}";
}
};
@@ -224,10 +227,18 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
InsertHere(context, type_expr_region_id);
auto value_id = SemIR::InstId::None;
if (kind_ == MatchKind::Local) {
auto conversion_kind = entry.ref_binding_context
? ConversionTarget::DurableRef
: ConversionTarget::Value;
if (!bind_name_id.has_value()) {
// TODO: Is this appropriate, or should we perform a conversion based on
// whether the `_` binding is a value or ref binding first, and then
// separately discard the initializer for a `_` binding?
conversion_kind = ConversionTarget::Discarded;
}
value_id =
Convert(context, SemIR::LocId(entry.scrutinee_id), entry.scrutinee_id,
{.kind = bind_name_id.has_value() ? ConversionTarget::ValueOrRef
: ConversionTarget::Discarded,
{.kind = conversion_kind,
.type_id = context.insts().Get(bind_name_id).type_id()});
} else {
// In a function call, conversion is handled while matching the enclosing
@@ -253,7 +264,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
// the caller side of the pattern, so we traverse without emitting any
// insts.
AddWork({.pattern_id = addr_pattern.inner_id,
.scrutinee_id = SemIR::InstId::None});
.scrutinee_id = SemIR::InstId::None,
.ref_binding_context = false});
return;
}
CARBON_CHECK(entry.scrutinee_id.has_value());
@@ -279,13 +291,16 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
context, SemIR::LocId(scrutinee_ref_id),
{.type_id = GetPointerType(context, scrutinee_ref_type_inst_id),
.lvalue_id = scrutinee_ref_id});
AddWork({.pattern_id = addr_pattern.inner_id, .scrutinee_id = new_scrutinee});
AddWork({.pattern_id = addr_pattern.inner_id,
.scrutinee_id = new_scrutinee,
.ref_binding_context = false});
}
auto MatchContext::DoEmitPatternMatch(Context& context,
SemIR::ValueParamPattern param_pattern,
SemIR::InstId pattern_inst_id,
WorkItem entry) -> void {
CARBON_CHECK(!entry.ref_binding_context);
switch (kind_) {
case MatchKind::Caller: {
CARBON_CHECK(
@@ -320,7 +335,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
.pretty_name_id = SemIR::GetPrettyNameFromPatternId(
context.sem_ir(), entry.pattern_id)});
AddWork({.pattern_id = param_pattern.subpattern_id,
.scrutinee_id = param_id});
.scrutinee_id = param_id,
.ref_binding_context = entry.ref_binding_context});
results_.push_back(param_id);
break;
}
@@ -334,6 +350,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
SemIR::RefParamPattern param_pattern,
SemIR::InstId pattern_inst_id,
WorkItem entry) -> void {
CARBON_CHECK(entry.ref_binding_context);
switch (kind_) {
case MatchKind::Caller: {
CARBON_CHECK(
@@ -362,7 +379,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
.pretty_name_id = SemIR::GetPrettyNameFromPatternId(
context.sem_ir(), entry.pattern_id)});
AddWork({.pattern_id = param_pattern.subpattern_id,
.scrutinee_id = param_id});
.scrutinee_id = param_id,
.ref_binding_context = entry.ref_binding_context});
results_.push_back(param_id);
break;
}
@@ -376,6 +394,7 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
SemIR::OutParamPattern param_pattern,
SemIR::InstId pattern_inst_id,
WorkItem entry) -> void {
CARBON_CHECK(!entry.ref_binding_context);
switch (kind_) {
case MatchKind::Caller: {
CARBON_CHECK(
@@ -408,7 +427,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
.pretty_name_id = SemIR::GetPrettyNameFromPatternId(
context.sem_ir(), entry.pattern_id)});
AddWork({.pattern_id = param_pattern.subpattern_id,
.scrutinee_id = param_id});
.scrutinee_id = param_id,
.ref_binding_context = entry.ref_binding_context});
results_.push_back(param_id);
break;
}
@@ -447,7 +467,8 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
// the caller side of the pattern, so we traverse without emitting any
// insts.
AddWork({.pattern_id = var_pattern.subpattern_id,
.scrutinee_id = SemIR::InstId::None});
.scrutinee_id = SemIR::InstId::None,
.ref_binding_context = true});
return;
}
case MatchKind::Local: {
@@ -481,8 +502,9 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
AddInst<SemIR::Assign>(context, SemIR::LocId(pattern_inst_id),
{.lhs_id = storage_id, .rhs_id = init_id});
}
AddWork(
{.pattern_id = var_pattern.subpattern_id, .scrutinee_id = storage_id});
AddWork({.pattern_id = var_pattern.subpattern_id,
.scrutinee_id = storage_id,
.ref_binding_context = true});
if (context.scope_stack().PeekIndex() == ScopeIndex::Package) {
context.global_init().Suspend();
}
@@ -500,8 +522,9 @@ auto MatchContext::DoEmitPatternMatch(Context& context,
[&](llvm::ArrayRef<SemIR::InstId> subscrutinee_ids) {
for (auto [subpattern_id, subscrutinee_id] :
llvm::reverse(llvm::zip(subpattern_ids, subscrutinee_ids))) {
AddWork(
{.pattern_id = subpattern_id, .scrutinee_id = subscrutinee_id});
AddWork({.pattern_id = subpattern_id,
.scrutinee_id = subscrutinee_id,
.ref_binding_context = entry.ref_binding_context});
}
};
if (!entry.scrutinee_id.has_value()) {
@@ -627,22 +650,25 @@ auto CalleePatternMatch(Context& context,
// in the original order.
if (return_slot_pattern_id.has_value()) {
match.AddWork({.pattern_id = return_slot_pattern_id,
.scrutinee_id = SemIR::InstId::None});
.scrutinee_id = SemIR::InstId::None,
.ref_binding_context = false});
}
if (param_patterns_id.has_value()) {
for (SemIR::InstId inst_id :
llvm::reverse(context.inst_blocks().Get(param_patterns_id))) {
match.AddWork(
{.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::None});
match.AddWork({.pattern_id = inst_id,
.scrutinee_id = SemIR::InstId::None,
.ref_binding_context = false});
}
}
if (implicit_param_patterns_id.has_value()) {
for (SemIR::InstId inst_id :
llvm::reverse(context.inst_blocks().Get(implicit_param_patterns_id))) {
match.AddWork(
{.pattern_id = inst_id, .scrutinee_id = SemIR::InstId::None});
match.AddWork({.pattern_id = inst_id,
.scrutinee_id = SemIR::InstId::None,
.ref_binding_context = false});
}
}
@@ -663,17 +689,22 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
if (return_slot_arg_id.has_value()) {
CARBON_CHECK(return_slot_pattern_id.has_value());
match.AddWork({.pattern_id = return_slot_pattern_id,
.scrutinee_id = return_slot_arg_id});
.scrutinee_id = return_slot_arg_id,
.ref_binding_context = false});
}
// Check type conversions per-element.
for (auto [arg_id, param_pattern_id] : llvm::reverse(llvm::zip_equal(
arg_refs, context.inst_blocks().GetOrEmpty(param_patterns_id)))) {
match.AddWork({.pattern_id = param_pattern_id, .scrutinee_id = arg_id});
match.AddWork({.pattern_id = param_pattern_id,
.scrutinee_id = arg_id,
.ref_binding_context = false});
}
if (self_pattern_id.has_value()) {
match.AddWork({.pattern_id = self_pattern_id, .scrutinee_id = self_arg_id});
match.AddWork({.pattern_id = self_pattern_id,
.scrutinee_id = self_arg_id,
.ref_binding_context = false});
}
return match.DoWork(context);
@@ -682,7 +713,9 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
auto LocalPatternMatch(Context& context, SemIR::InstId pattern_id,
SemIR::InstId scrutinee_id) -> void {
MatchContext match(MatchKind::Local);
match.AddWork({.pattern_id = pattern_id, .scrutinee_id = scrutinee_id});
match.AddWork({.pattern_id = pattern_id,
.scrutinee_id = scrutinee_id,
.ref_binding_context = false});
match.DoWork(context);
}
+2 -1
View File
@@ -187,7 +187,8 @@ extern alias C = Class;
// CHECK:STDOUT: %.loc10_13.2: init %C = class_init (), %.loc10_13.1 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc10_13.3: ref %C = temporary %.loc10_13.1, %.loc10_13.2
// CHECK:STDOUT: %.loc10_13.4: ref %C = converted @__global_init.%.loc10, %.loc10_13.3
// CHECK:STDOUT: %d: ref %C = bind_name d, %.loc10_13.4
// CHECK:STDOUT: %.loc10_13.5: %C = bind_value %.loc10_13.4
// CHECK:STDOUT: %d: %C = bind_name d, %.loc10_13.5
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
+7 -6
View File
@@ -182,9 +182,9 @@ var b: B = {.x = ()} as B;
// CHECK:STDOUT: %Make: %Make.type = struct_value () [concrete]
// CHECK:STDOUT: %B: type = class_type @B [concrete]
// CHECK:STDOUT: %pattern_type.049: type = pattern_type %B [concrete]
// CHECK:STDOUT: %a_ref.var: ref %B = var file.%a_ref.var_patt [concrete]
// CHECK:STDOUT: %ptr.e79: type = ptr_type %B [concrete]
// CHECK:STDOUT: %pattern_type.960: type = pattern_type %ptr.e79 [concrete]
// CHECK:STDOUT: %a_ref.var: ref %B = var file.%a_ref.var_patt [concrete]
// CHECK:STDOUT: %addr: %ptr.e79 = addr_of %a_ref.var [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -196,7 +196,7 @@ var b: B = {.x = ()} as B;
// CHECK:STDOUT: %b_val.patt: %pattern_type.049 = binding_pattern b_val [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %B.ref.loc22: type = name_ref B, %B.decl [concrete = constants.%B]
// CHECK:STDOUT: %b_val: ref %B = bind_name b_val, @__global_init.%.loc22_22.2 [concrete = constants.%a_ref.var]
// CHECK:STDOUT: %b_val: %B = bind_name b_val, @__global_init.%.loc22_22.2
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %b_ptr.patt: %pattern_type.960 = binding_pattern b_ptr [concrete]
// CHECK:STDOUT: }
@@ -217,10 +217,10 @@ var b: B = {.x = ()} as B;
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: %a_val.ref: ref %A = name_ref a_val, file.%a_val [concrete = file.%a_ref.var]
// CHECK:STDOUT: %a_val.ref: %A = name_ref a_val, file.%a_val
// CHECK:STDOUT: %B.ref.loc22: type = name_ref B, file.%B.decl [concrete = constants.%B]
// CHECK:STDOUT: %.loc22_22.1: ref %B = as_compatible %a_val.ref [concrete = constants.%a_ref.var]
// CHECK:STDOUT: %.loc22_22.2: ref %B = converted %a_val.ref, %.loc22_22.1 [concrete = constants.%a_ref.var]
// CHECK:STDOUT: %.loc22_22.1: %B = as_compatible %a_val.ref
// CHECK:STDOUT: %.loc22_22.2: %B = converted %a_val.ref, %.loc22_22.1
// CHECK:STDOUT: %a_ref.ref.loc23: ref %A = name_ref a_ref, file.%a_ref [concrete = file.%a_ref.var]
// CHECK:STDOUT: %B.ref.loc23: type = name_ref B, file.%B.decl [concrete = constants.%B]
// CHECK:STDOUT: %.loc23_25.1: ref %B = as_compatible %a_ref.ref.loc23 [concrete = constants.%a_ref.var]
@@ -379,7 +379,8 @@ var b: B = {.x = ()} as B;
// CHECK:STDOUT: %b_value.patt: %pattern_type.049 = binding_pattern b_value [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %B.ref: type = name_ref B, %B.decl [concrete = constants.%B]
// CHECK:STDOUT: %b_value: ref %B = bind_name b_value, @__global_init.%.loc14_42.2
// CHECK:STDOUT: %.loc14: %B = bind_value @__global_init.%.loc14_42.2
// CHECK:STDOUT: %b_value: %B = bind_name b_value, %.loc14
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
+3 -2
View File
@@ -362,8 +362,9 @@ let n: {.x: ()} = {.x = ()} as {.x = ()};
// CHECK:STDOUT: %n.patt: %pattern_type.c27 = binding_pattern n [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %Y.ref: type = name_ref Y, %Y.decl [concrete = constants.%Y]
// CHECK:STDOUT: %.loc19: ref %Y = temporary @__global_init.%.loc19_29.1, @__global_init.%.loc19_29.2
// CHECK:STDOUT: %n: ref %Y = bind_name n, %.loc19
// CHECK:STDOUT: %.loc19_29.1: ref %Y = temporary @__global_init.%.loc19_29.1, @__global_init.%.loc19_29.2
// CHECK:STDOUT: %.loc19_29.2: %Y = bind_value %.loc19_29.1
// CHECK:STDOUT: %n: %Y = bind_name n, %.loc19_29.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
@@ -315,9 +315,9 @@ let convert_not_constant_widen: i64 = Int32ToInt64(not_constant);
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %u32: type = class_type @UInt, @UInt(constants.%int_32) [concrete = constants.%u32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc6_42.1: ref %u32 = temporary_storage
// CHECK:STDOUT: %.loc6_42.2: ref %u32 = temporary %.loc6_42.1, @__global_init.%int.convert_checked.loc6_42
// CHECK:STDOUT: %SizePreserving: ref %u32 = bind_name SizePreserving, %.loc6_42.2
// CHECK:STDOUT: %.loc6_42.1: %u32 = value_of_initializer @__global_init.%int.convert_checked.loc6_42 [concrete = constants.%int_1.c1d]
// CHECK:STDOUT: %.loc6_42.2: %u32 = converted @__global_init.%int.convert_checked.loc6_42, %.loc6_42.1 [concrete = constants.%int_1.c1d]
// CHECK:STDOUT: %SizePreserving: %u32 = bind_name SizePreserving, %.loc6_42.2
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %Narrowing.patt: %pattern_type.88f = binding_pattern Narrowing [concrete]
// CHECK:STDOUT: }
@@ -325,9 +325,9 @@ let convert_not_constant_widen: i64 = Int32ToInt64(not_constant);
// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete = constants.%int_16]
// CHECK:STDOUT: %i16: type = class_type @Int, @Int(constants.%int_16) [concrete = constants.%i16]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc7_36.1: ref %i16 = temporary_storage
// CHECK:STDOUT: %.loc7_36.2: ref %i16 = temporary %.loc7_36.1, @__global_init.%int.convert_checked.loc7_36
// CHECK:STDOUT: %Narrowing: ref %i16 = bind_name Narrowing, %.loc7_36.2
// CHECK:STDOUT: %.loc7_36.1: %i16 = value_of_initializer @__global_init.%int.convert_checked.loc7_36 [concrete = constants.%int_1.c22]
// CHECK:STDOUT: %.loc7_36.2: %i16 = converted @__global_init.%int.convert_checked.loc7_36, %.loc7_36.1 [concrete = constants.%int_1.c22]
// CHECK:STDOUT: %Narrowing: %i16 = bind_name Narrowing, %.loc7_36.2
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %Widening.patt: %pattern_type.a10 = binding_pattern Widening [concrete]
// CHECK:STDOUT: }
@@ -335,9 +335,9 @@ let convert_not_constant_widen: i64 = Int32ToInt64(not_constant);
// CHECK:STDOUT: %int_64: Core.IntLiteral = int_value 64 [concrete = constants.%int_64]
// CHECK:STDOUT: %i64: type = class_type @Int, @Int(constants.%int_64) [concrete = constants.%i64]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc8_35.1: ref %i64 = temporary_storage
// CHECK:STDOUT: %.loc8_35.2: ref %i64 = temporary %.loc8_35.1, @__global_init.%int.convert_checked.loc8_35
// CHECK:STDOUT: %Widening: ref %i64 = bind_name Widening, %.loc8_35.2
// CHECK:STDOUT: %.loc8_35.1: %i64 = value_of_initializer @__global_init.%int.convert_checked.loc8_35 [concrete = constants.%int_1.a95]
// CHECK:STDOUT: %.loc8_35.2: %i64 = converted @__global_init.%int.convert_checked.loc8_35, %.loc8_35.1 [concrete = constants.%int_1.a95]
// CHECK:STDOUT: %Widening: %i64 = bind_name Widening, %.loc8_35.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @__global_init() {
+6 -6
View File
@@ -58,9 +58,9 @@ fn Main() {
// CHECK:STDOUT: %int_32.loc8: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc8: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc8_25.1: ref %i32 = temporary_storage
// CHECK:STDOUT: %.loc8_25.2: ref %i32 = temporary %.loc8_25.1, %read.char.loc8
// CHECK:STDOUT: %n: ref %i32 = bind_name n, %.loc8_25.2
// CHECK:STDOUT: %.loc8_25.1: %i32 = value_of_initializer %read.char.loc8
// CHECK:STDOUT: %.loc8_25.2: %i32 = converted %read.char.loc8, %.loc8_25.1
// CHECK:STDOUT: %n: %i32 = bind_name n, %.loc8_25.2
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %m.patt: %pattern_type.7ce = binding_pattern m [concrete]
// CHECK:STDOUT: }
@@ -71,9 +71,9 @@ fn Main() {
// CHECK:STDOUT: %int_32.loc9: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc9: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc9_30.1: ref %i32 = temporary_storage
// CHECK:STDOUT: %.loc9_30.2: ref %i32 = temporary %.loc9_30.1, %read.char.loc9
// CHECK:STDOUT: %m: ref %i32 = bind_name m, %.loc9_30.2
// CHECK:STDOUT: %.loc9_30.1: %i32 = value_of_initializer %read.char.loc9
// CHECK:STDOUT: %.loc9_30.2: %i32 = converted %read.char.loc9, %.loc9_30.1
// CHECK:STDOUT: %m: %i32 = bind_name m, %.loc9_30.2
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+6 -5
View File
@@ -307,24 +307,25 @@ class A {
// CHECK:STDOUT: %Make.call: init %Circle = call %Make.ref() to %.loc18_36.1
// CHECK:STDOUT: %Circle.ref.loc18_15: type = name_ref Circle, file.%Circle.decl [concrete = constants.%Circle]
// CHECK:STDOUT: %.loc18_36.2: ref %Circle = temporary %.loc18_36.1, %Make.call
// CHECK:STDOUT: %circle: ref %Circle = bind_name circle, %.loc18_36.2
// CHECK:STDOUT: %.loc18_36.3: %Circle = bind_value %.loc18_36.2
// CHECK:STDOUT: %circle: %Circle = bind_name circle, %.loc18_36.3
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %radius.patt: %pattern_type.7ce = binding_pattern radius [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %circle.ref.loc26: ref %Circle = name_ref circle, %circle
// CHECK:STDOUT: %circle.ref.loc26: %Circle = name_ref circle, %circle
// CHECK:STDOUT: %radius.ref.loc26: <error> = name_ref radius, <error> [concrete = <error>]
// CHECK:STDOUT: %.loc26: type = splice_block %i32 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %radius: %i32 = bind_name radius, <error> [concrete = <error>]
// CHECK:STDOUT: %circle.ref.loc34: ref %Circle = name_ref circle, %circle
// CHECK:STDOUT: %circle.ref.loc34: %Circle = name_ref circle, %circle
// CHECK:STDOUT: %radius.ref.loc34: <error> = name_ref radius, <error> [concrete = <error>]
// CHECK:STDOUT: %int_5: Core.IntLiteral = int_value 5 [concrete = constants.%int_5.64b]
// CHECK:STDOUT: assign %radius.ref.loc34, <error>
// CHECK:STDOUT: %circle.ref.loc42: ref %Circle = name_ref circle, %circle
// CHECK:STDOUT: %circle.ref.loc42: %Circle = name_ref circle, %circle
// CHECK:STDOUT: %SOME_INTERNAL_CONSTANT.ref: <error> = name_ref SOME_INTERNAL_CONSTANT, <error> [concrete = <error>]
// CHECK:STDOUT: %circle.ref.loc51: ref %Circle = name_ref circle, %circle
// CHECK:STDOUT: %circle.ref.loc51: %Circle = name_ref circle, %circle
// CHECK:STDOUT: %SomeInternalFunction.ref: <error> = name_ref SomeInternalFunction, <error> [concrete = <error>]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
+13 -11
View File
@@ -191,17 +191,18 @@ var e: C = MakeAdaptC();
// CHECK:STDOUT: %.loc13_27.8: init %C = class_init (%.loc13_27.4, %.loc13_27.7), %.loc13_27.2 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc13_27.9: ref %C = temporary %.loc13_27.2, %.loc13_27.8
// CHECK:STDOUT: %.loc13_27.10: ref %C = converted @__global_init.%.loc13, %.loc13_27.9
// CHECK:STDOUT: %a: ref %C = bind_name a, %.loc13_27.10
// CHECK:STDOUT: %.loc13_27.11: %C = bind_value %.loc13_27.10
// CHECK:STDOUT: %a: %C = bind_name a, %.loc13_27.11
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %b.patt: %pattern_type.a1a = binding_pattern b [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %AdaptC.ref.loc15: type = name_ref AdaptC, %AdaptC.decl [concrete = constants.%AdaptC]
// CHECK:STDOUT: %b: ref %AdaptC = bind_name b, @__global_init.%.loc15_19.2
// CHECK:STDOUT: %b: %AdaptC = bind_name b, @__global_init.%.loc15_19.2
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %c.patt: %pattern_type.c48 = binding_pattern c [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %C.ref.loc17: type = name_ref C, %C.decl [concrete = constants.%C]
// CHECK:STDOUT: %c: ref %C = bind_name c, @__global_init.%.loc17_14.2
// CHECK:STDOUT: %c: %C = bind_name c, @__global_init.%.loc17_14.2
// CHECK:STDOUT: %MakeC.decl: %MakeC.type = fn_decl @MakeC [concrete = constants.%MakeC] {
// CHECK:STDOUT: %return.patt: %pattern_type.c48 = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.c48 = out_param_pattern %return.patt, call_param0 [concrete]
@@ -271,14 +272,14 @@ var e: C = MakeAdaptC();
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
// CHECK:STDOUT: %.loc13: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2)
// CHECK:STDOUT: %a.ref: ref %C = name_ref a, file.%a
// CHECK:STDOUT: %a.ref: %C = name_ref a, file.%a
// CHECK:STDOUT: %AdaptC.ref.loc15: type = name_ref AdaptC, file.%AdaptC.decl [concrete = constants.%AdaptC]
// CHECK:STDOUT: %.loc15_19.1: ref %AdaptC = as_compatible %a.ref
// CHECK:STDOUT: %.loc15_19.2: ref %AdaptC = converted %a.ref, %.loc15_19.1
// CHECK:STDOUT: %b.ref: ref %AdaptC = name_ref b, file.%b
// CHECK:STDOUT: %.loc15_19.1: %AdaptC = as_compatible %a.ref
// CHECK:STDOUT: %.loc15_19.2: %AdaptC = converted %a.ref, %.loc15_19.1
// CHECK:STDOUT: %b.ref: %AdaptC = name_ref b, file.%b
// CHECK:STDOUT: %C.ref.loc17: type = name_ref C, file.%C.decl [concrete = constants.%C]
// CHECK:STDOUT: %.loc17_14.1: ref %C = as_compatible %b.ref
// CHECK:STDOUT: %.loc17_14.2: ref %C = converted %b.ref, %.loc17_14.1
// CHECK:STDOUT: %.loc17_14.1: %C = as_compatible %b.ref
// CHECK:STDOUT: %.loc17_14.2: %C = converted %b.ref, %.loc17_14.1
// CHECK:STDOUT: %MakeC.ref: %MakeC.type = name_ref MakeC, file.%MakeC.decl [concrete = constants.%MakeC]
// CHECK:STDOUT: %.loc23_1: ref %AdaptC = splice_block file.%d.var [concrete = file.%d.var] {}
// CHECK:STDOUT: %MakeC.call: init %C = call %MakeC.ref() to %.loc23_1
@@ -392,7 +393,8 @@ var e: C = MakeAdaptC();
// CHECK:STDOUT: %.loc13_27.8: init %C = class_init (%.loc13_27.4, %.loc13_27.7), %.loc13_27.2 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc13_27.9: ref %C = temporary %.loc13_27.2, %.loc13_27.8
// CHECK:STDOUT: %.loc13_27.10: ref %C = converted @__global_init.%.loc13, %.loc13_27.9
// CHECK:STDOUT: %a: ref %C = bind_name a, %.loc13_27.10
// CHECK:STDOUT: %.loc13_27.11: %C = bind_value %.loc13_27.10
// CHECK:STDOUT: %a: %C = bind_name a, %.loc13_27.11
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %b.patt: %pattern_type.a1a = binding_pattern b [concrete]
// CHECK:STDOUT: }
@@ -474,7 +476,7 @@ var e: C = MakeAdaptC();
// CHECK:STDOUT: %int_1: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
// CHECK:STDOUT: %.loc13: %struct_type.a.b.cfd = struct_literal (%int_1, %int_2)
// CHECK:STDOUT: %a.ref: ref %C = name_ref a, file.%a
// CHECK:STDOUT: %a.ref: %C = name_ref a, file.%a
// CHECK:STDOUT: %b.ref: %AdaptC = name_ref b, file.%b [concrete = <error>]
// CHECK:STDOUT: %MakeC.ref: %MakeC.type = name_ref MakeC, file.%MakeC.decl [concrete = constants.%MakeC]
// CHECK:STDOUT: %.loc46_23: ref %C = temporary_storage
+4 -2
View File
@@ -314,7 +314,8 @@ fn ConvertInit() {
// CHECK:STDOUT: %.loc33_14.1: ref %B = class_element_access %c.ref, element0
// CHECK:STDOUT: %.loc33_14.2: ref %A = class_element_access %.loc33_14.1, element0
// CHECK:STDOUT: %.loc33_14.3: ref %A = converted %c.ref, %.loc33_14.2
// CHECK:STDOUT: %a: ref %A = bind_name a, %.loc33_14.3
// CHECK:STDOUT: %.loc33_14.4: %A = bind_value %.loc33_14.3
// CHECK:STDOUT: %a: %A = bind_name a, %.loc33_14.4
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -380,7 +381,8 @@ fn ConvertInit() {
// CHECK:STDOUT: %.loc41_59.2: ref %B = class_element_access %.loc41_59.1, element0
// CHECK:STDOUT: %.loc41_59.3: ref %A = class_element_access %.loc41_59.2, element0
// CHECK:STDOUT: %.loc41_59.4: ref %A = converted %.loc41_59.1, %.loc41_59.3
// CHECK:STDOUT: %a: ref %A = bind_name a, %.loc41_59.4
// CHECK:STDOUT: %.loc41_59.5: %A = bind_value %.loc41_59.4
// CHECK:STDOUT: %a: %A = bind_name a, %.loc41_59.5
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -140,13 +140,14 @@ fn Test() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %cv.ref.loc23: ref %Class = name_ref cv, %cv
// CHECK:STDOUT: %Class.ref.loc23: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]
// CHECK:STDOUT: %c: ref %Class = bind_name c, %cv.ref.loc23
// CHECK:STDOUT: %.loc23: %Class = bind_value %cv.ref.loc23
// CHECK:STDOUT: %c: %Class = bind_name c, %.loc23
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %cj.patt: %pattern_type.7ce = binding_pattern cj [concrete]
// CHECK:STDOUT: %cj.var_patt: %pattern_type.7ce = var_pattern %cj.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %cj.var: ref %i32 = var %cj.var_patt
// CHECK:STDOUT: %c.ref.loc24: ref %Class = name_ref c, %c
// CHECK:STDOUT: %c.ref.loc24: %Class = name_ref c, %c
// CHECK:STDOUT: %j.ref.loc24: %Class.elem = name_ref j, @Class.%.loc15 [concrete = @Class.%.loc15]
// CHECK:STDOUT: %.loc24_18.1: ref %i32 = class_element_access %c.ref.loc24, element0
// CHECK:STDOUT: %.loc24_18.2: %i32 = bind_value %.loc24_18.1
@@ -161,7 +162,7 @@ fn Test() {
// CHECK:STDOUT: %ck.var_patt: %pattern_type.7ce = var_pattern %ck.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %ck.var: ref %i32 = var %ck.var_patt
// CHECK:STDOUT: %c.ref.loc25: ref %Class = name_ref c, %c
// CHECK:STDOUT: %c.ref.loc25: %Class = name_ref c, %c
// CHECK:STDOUT: %k.ref.loc25: %Class.elem = name_ref k, @Class.%.loc16 [concrete = @Class.%.loc16]
// CHECK:STDOUT: %.loc25_18.1: ref %i32 = class_element_access %c.ref.loc25, element1
// CHECK:STDOUT: %.loc25_18.2: %i32 = bind_value %.loc25_18.1
@@ -666,9 +666,9 @@ fn H() {
// CHECK:STDOUT: %int_32.loc13_10: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc13_10: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc13_25.1: ref %i32 = temporary_storage
// CHECK:STDOUT: %.loc13_25.2: ref %i32 = temporary %.loc13_25.1, %G.call
// CHECK:STDOUT: %i: ref %i32 = bind_name i, %.loc13_25.2
// CHECK:STDOUT: %.loc13_25.1: %i32 = value_of_initializer %G.call
// CHECK:STDOUT: %.loc13_25.2: %i32 = converted %G.call, %.loc13_25.1
// CHECK:STDOUT: %i: %i32 = bind_name i, %.loc13_25.2
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -865,9 +865,9 @@ fn H() {
// CHECK:STDOUT: %int_32.loc7_10: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc7_10: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc7_25.1: ref %i32 = temporary_storage
// CHECK:STDOUT: %.loc7_25.2: ref %i32 = temporary %.loc7_25.1, %G.call
// CHECK:STDOUT: %j: ref %i32 = bind_name j, %.loc7_25.2
// CHECK:STDOUT: %.loc7_25.1: %i32 = value_of_initializer %G.call
// CHECK:STDOUT: %.loc7_25.2: %i32 = converted %G.call, %.loc7_25.1
// CHECK:STDOUT: %j: %i32 = bind_name j, %.loc7_25.2
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
+9 -11
View File
@@ -227,13 +227,14 @@ fn F(a: Outer*) {
// CHECK:STDOUT: %a.ref.loc45: %ptr.5df = name_ref a, %a
// CHECK:STDOUT: %.loc45_26: ref %Outer = deref %a.ref.loc45
// CHECK:STDOUT: %pi.ref.loc45: %Outer.elem.fe9 = name_ref pi, @Outer.%.loc41 [concrete = @Outer.%.loc41]
// CHECK:STDOUT: %.loc45_29: ref %ptr.36a = class_element_access %.loc45_26, element2
// CHECK:STDOUT: %.loc45_29.1: ref %ptr.36a = class_element_access %.loc45_26, element2
// CHECK:STDOUT: %.loc45_21: type = splice_block %ptr.loc45 [concrete = constants.%ptr.36a] {
// CHECK:STDOUT: %Outer.ref.loc45: type = name_ref Outer, file.%Outer.decl [concrete = constants.%Outer]
// CHECK:STDOUT: %Inner.ref: type = name_ref Inner, @Outer.%Inner.decl [concrete = constants.%Inner]
// CHECK:STDOUT: %ptr.loc45: type = ptr_type %Inner.ref [concrete = constants.%ptr.36a]
// CHECK:STDOUT: }
// CHECK:STDOUT: %b: ref %ptr.36a = bind_name b, %.loc45_29
// CHECK:STDOUT: %.loc45_29.2: %ptr.36a = bind_value %.loc45_29.1
// CHECK:STDOUT: %b: %ptr.36a = bind_name b, %.loc45_29.2
// CHECK:STDOUT: %a.ref.loc47_3: %ptr.5df = name_ref a, %a
// CHECK:STDOUT: %.loc47_4.1: ref %Outer = deref %a.ref.loc47_3
// CHECK:STDOUT: %po.ref.loc47: %Outer.elem.a16 = name_ref po, @Outer.%.loc39 [concrete = @Outer.%.loc39]
@@ -256,16 +257,14 @@ fn F(a: Outer*) {
// CHECK:STDOUT: %.loc49_12.2: ref %ptr.36a = class_element_access %.loc49_12.1, element2
// CHECK:STDOUT: %.loc49_12.3: %ptr.36a = bind_value %.loc49_12.2
// CHECK:STDOUT: assign %.loc49_4.2, %.loc49_12.3
// CHECK:STDOUT: %b.ref.loc50: ref %ptr.36a = name_ref b, %b
// CHECK:STDOUT: %.loc50_3: %ptr.36a = bind_value %b.ref.loc50
// CHECK:STDOUT: %.loc50_4.1: ref %Inner = deref %.loc50_3
// CHECK:STDOUT: %b.ref.loc50: %ptr.36a = name_ref b, %b
// CHECK:STDOUT: %.loc50_4.1: ref %Inner = deref %b.ref.loc50
// CHECK:STDOUT: %po.ref.loc50: %Inner.elem.c30 = name_ref po, @Inner.%.loc23 [concrete = @Inner.%.loc23]
// CHECK:STDOUT: %.loc50_4.2: ref %ptr.5df = class_element_access %.loc50_4.1, element1
// CHECK:STDOUT: %a.ref.loc50: %ptr.5df = name_ref a, %a
// CHECK:STDOUT: assign %.loc50_4.2, %a.ref.loc50
// CHECK:STDOUT: %b.ref.loc51: ref %ptr.36a = name_ref b, %b
// CHECK:STDOUT: %.loc51_3: %ptr.36a = bind_value %b.ref.loc51
// CHECK:STDOUT: %.loc51_4.1: ref %Inner = deref %.loc51_3
// CHECK:STDOUT: %b.ref.loc51: %ptr.36a = name_ref b, %b
// CHECK:STDOUT: %.loc51_4.1: ref %Inner = deref %b.ref.loc51
// CHECK:STDOUT: %pi.ref.loc51_4: %Inner.elem.640 = name_ref pi, @Inner.%.loc22 [concrete = @Inner.%.loc22]
// CHECK:STDOUT: %.loc51_4.2: ref %ptr.36a = class_element_access %.loc51_4.1, element0
// CHECK:STDOUT: %a.ref.loc51: %ptr.5df = name_ref a, %a
@@ -274,9 +273,8 @@ fn F(a: Outer*) {
// CHECK:STDOUT: %.loc51_12.2: ref %ptr.36a = class_element_access %.loc51_12.1, element2
// CHECK:STDOUT: %.loc51_12.3: %ptr.36a = bind_value %.loc51_12.2
// CHECK:STDOUT: assign %.loc51_4.2, %.loc51_12.3
// CHECK:STDOUT: %b.ref.loc52: ref %ptr.36a = name_ref b, %b
// CHECK:STDOUT: %.loc52_3: %ptr.36a = bind_value %b.ref.loc52
// CHECK:STDOUT: %.loc52_4.1: ref %Inner = deref %.loc52_3
// CHECK:STDOUT: %b.ref.loc52: %ptr.36a = name_ref b, %b
// CHECK:STDOUT: %.loc52_4.1: ref %Inner = deref %b.ref.loc52
// CHECK:STDOUT: %qi.ref: %Inner.elem.640 = name_ref qi, @Inner.%.loc24 [concrete = @Inner.%.loc24]
// CHECK:STDOUT: %.loc52_4.2: ref %ptr.36a = class_element_access %.loc52_4.1, element2
// CHECK:STDOUT: %a.ref.loc52: %ptr.5df = name_ref a, %a
@@ -611,9 +611,10 @@ fn G() {
// CHECK:STDOUT: %.loc26_26.4: init type = initialize_from %C.ref to %.loc26_26.3 [concrete = constants.%C]
// CHECK:STDOUT: %.loc26_26.5: init %Class = class_init (%.loc26_26.4), %.loc26_26.2 [concrete = constants.%Class.val]
// CHECK:STDOUT: %.loc26_26.6: ref %Class = temporary %.loc26_26.2, %.loc26_26.5
// CHECK:STDOUT: %.loc26_28: ref %Class = converted %.loc26_26.1, %.loc26_26.6
// CHECK:STDOUT: %.loc26_28.1: ref %Class = converted %.loc26_26.1, %.loc26_26.6
// CHECK:STDOUT: %Class.ref.loc26_11: type = name_ref Class, file.%Class.decl [concrete = constants.%Class]
// CHECK:STDOUT: %c: %Class = bind_symbolic_name c, 0, %.loc26_28 [symbolic = constants.%c]
// CHECK:STDOUT: %.loc26_28.2: %Class = bind_value %.loc26_28.1
// CHECK:STDOUT: %c: %Class = bind_symbolic_name c, 0, %.loc26_28.2 [symbolic = constants.%c]
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
// CHECK:STDOUT: %.loc27_6.1: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %HoldsType.ref: %HoldsType.type = name_ref HoldsType, file.%HoldsType.decl [concrete = constants.%HoldsType.generic]
@@ -331,7 +331,7 @@ fn F() {
// CHECK:STDOUT: %.loc22_28.2: ref %Goat = temporary_storage
// CHECK:STDOUT: %.loc22_28.3: init %Goat = class_init (), %.loc22_28.2 [concrete = constants.%Goat.val]
// CHECK:STDOUT: %.loc22_28.4: ref %Goat = temporary %.loc22_28.2, %.loc22_28.3
// CHECK:STDOUT: %.loc22_30: ref %Goat = converted %.loc22_28.1, %.loc22_28.4
// CHECK:STDOUT: %.loc22_30.1: ref %Goat = converted %.loc22_28.1, %.loc22_28.4
// CHECK:STDOUT: %.loc22_15.1: type = splice_block %.loc22_15.3 [concrete = constants.%Goat] {
// CHECK:STDOUT: %Goat.ref.loc22_10: type = name_ref Goat, file.%Goat.decl [concrete = constants.%Goat]
// CHECK:STDOUT: %Animal.ref.loc22: type = name_ref Animal, file.%Animal.decl [concrete = constants.%Animal.type]
@@ -340,11 +340,12 @@ fn F() {
// CHECK:STDOUT: %as_type.loc22: type = facet_access_type %.loc22_15.2 [concrete = constants.%Goat]
// CHECK:STDOUT: %.loc22_15.3: type = converted %.loc22_15.2, %as_type.loc22 [concrete = constants.%Goat]
// CHECK:STDOUT: }
// CHECK:STDOUT: %x: ref %Goat = bind_name x, %.loc22_30
// CHECK:STDOUT: %x.ref.loc23: ref %Goat = name_ref x, %x
// CHECK:STDOUT: %.loc22_30.2: %Goat = bind_value %.loc22_30.1
// CHECK:STDOUT: %x: %Goat = bind_name x, %.loc22_30.2
// CHECK:STDOUT: %x.ref.loc23: %Goat = name_ref x, %x
// CHECK:STDOUT: %Bleet.ref.loc23: %Bleet.type = name_ref Bleet, @Goat.%Bleet.decl [concrete = constants.%Bleet]
// CHECK:STDOUT: %Bleet.call.loc23: init %empty_tuple.type = call %Bleet.ref.loc23()
// CHECK:STDOUT: %x.ref.loc24: ref %Goat = name_ref x, %x
// CHECK:STDOUT: %x.ref.loc24: %Goat = name_ref x, %x
// CHECK:STDOUT: %Eat.ref.loc24: %Eats.assoc_type = name_ref Eat, @Eats.%assoc0 [concrete = constants.%assoc0]
// CHECK:STDOUT: %impl.elem0.loc24: %.f6e = impl_witness_access constants.%Eats.impl_witness, element0 [concrete = constants.%Eat.73e]
// CHECK:STDOUT: %Eat.call.loc24: init %empty_tuple.type = call %impl.elem0.loc24()
@@ -255,9 +255,10 @@ fn G(holds_to: HoldsType((RuntimeConvertTo, ))) {
// CHECK:STDOUT: %.loc30_36.2: ref %RuntimeConvertFrom = temporary_storage
// CHECK:STDOUT: %.loc30_36.3: init %RuntimeConvertFrom = class_init (), %.loc30_36.2 [concrete = constants.%RuntimeConvertFrom.val]
// CHECK:STDOUT: %.loc30_36.4: ref %RuntimeConvertFrom = temporary %.loc30_36.2, %.loc30_36.3
// CHECK:STDOUT: %.loc30_38: ref %RuntimeConvertFrom = converted %.loc30_36.1, %.loc30_36.4
// CHECK:STDOUT: %.loc30_38.1: ref %RuntimeConvertFrom = converted %.loc30_36.1, %.loc30_36.4
// CHECK:STDOUT: %RuntimeConvertFrom.ref.loc30_14: type = name_ref RuntimeConvertFrom, file.%RuntimeConvertFrom.decl [concrete = constants.%RuntimeConvertFrom]
// CHECK:STDOUT: %from: %RuntimeConvertFrom = bind_symbolic_name from, 0, %.loc30_38 [symbolic = constants.%from]
// CHECK:STDOUT: %.loc30_38.2: %RuntimeConvertFrom = bind_value %.loc30_38.1
// CHECK:STDOUT: %from: %RuntimeConvertFrom = bind_symbolic_name from, 0, %.loc30_38.2 [symbolic = constants.%from]
// CHECK:STDOUT: %F.ref: %F.type = name_ref F, file.%F.decl [concrete = constants.%F]
// CHECK:STDOUT: %from.ref: %RuntimeConvertFrom = name_ref from, %from [symbolic = constants.%from]
// CHECK:STDOUT: %holds_to.ref: %HoldsType.066 = name_ref holds_to, %holds_to
@@ -77,9 +77,10 @@ fn F(T:! type) {
// CHECK:STDOUT: }
// CHECK:STDOUT: %p.ref: ref @F.%ptr.loc16_11.2 (%ptr) = name_ref p, %p
// CHECK:STDOUT: %.loc17_15: @F.%ptr.loc16_11.2 (%ptr) = bind_value %p.ref
// CHECK:STDOUT: %.loc17_14: ref @F.%T.loc15_6.2 (%T) = deref %.loc17_15
// CHECK:STDOUT: %.loc17_14.1: ref @F.%T.loc15_6.2 (%T) = deref %.loc17_15
// CHECK:STDOUT: %T.ref.loc17: type = name_ref T, %T.loc15_6.1 [symbolic = %T.loc15_6.2 (constants.%T)]
// CHECK:STDOUT: %n: ref @F.%T.loc15_6.2 (%T) = bind_name n, %.loc17_14
// CHECK:STDOUT: %.loc17_14.2: @F.%T.loc15_6.2 (%T) = bind_value %.loc17_14.1
// CHECK:STDOUT: %n: @F.%T.loc15_6.2 (%T) = bind_name n, %.loc17_14.2
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT: }
+3 -2
View File
@@ -270,12 +270,13 @@ class X(U:! type) {
// CHECK:STDOUT: %F.call.loc21: init %Param = call %impl.elem0.loc21() to %.loc21_20.1
// CHECK:STDOUT: %.loc21_20.2: ref %Param = temporary %.loc21_20.1, %F.call.loc21
// CHECK:STDOUT: %x.ref.loc21: %Param.elem = name_ref x, @Param.%.loc9 [concrete = @Param.%.loc9]
// CHECK:STDOUT: %.loc21_21: ref %i32 = class_element_access %.loc21_20.2, element0
// CHECK:STDOUT: %.loc21_21.1: ref %i32 = class_element_access %.loc21_20.2, element0
// CHECK:STDOUT: %.loc21_10: type = splice_block %i32.loc21 [concrete = constants.%i32] {
// CHECK:STDOUT: %int_32.loc21: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc21: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: ref %i32 = bind_name a, %.loc21_21
// CHECK:STDOUT: %.loc21_21.2: %i32 = bind_value %.loc21_21.1
// CHECK:STDOUT: %a: %i32 = bind_name a, %.loc21_21.2
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %b.patt: %pattern_type.7ce = binding_pattern b [concrete]
// CHECK:STDOUT: %b.var_patt: %pattern_type.7ce = var_pattern %b.patt [concrete]
+3 -2
View File
@@ -3871,7 +3871,7 @@ fn F() {
// CHECK:STDOUT: %.loc12_21.2: ref %C.131 = temporary_storage
// CHECK:STDOUT: %.loc12_21.3: init %C.131 = class_init (), %.loc12_21.2 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc12_21.4: ref %C.131 = temporary %.loc12_21.2, %.loc12_21.3
// CHECK:STDOUT: %.loc12_23: ref %C.131 = converted %.loc12_21.1, %.loc12_21.4
// CHECK:STDOUT: %.loc12_23.1: ref %C.131 = converted %.loc12_21.1, %.loc12_21.4
// CHECK:STDOUT: %.loc12_11.1: type = splice_block %impl.elem0 [concrete = constants.%C.131] {
// CHECK:STDOUT: %D.ref.loc12_10: type = name_ref D, file.%D.decl [concrete = constants.%D]
// CHECK:STDOUT: %Z.ref: type = name_ref Z, file.%Z.decl [concrete = constants.%Z.type]
@@ -3880,7 +3880,8 @@ fn F() {
// CHECK:STDOUT: %.loc12_11.2: %Z.type = converted %D.ref.loc12_10, %Z.facet [concrete = constants.%Z.facet.f2a]
// CHECK:STDOUT: %impl.elem0: type = impl_witness_access constants.%Z.impl_witness.19e, element0 [concrete = constants.%C.131]
// CHECK:STDOUT: }
// CHECK:STDOUT: %a: ref %C.131 = bind_name a, %.loc12_23
// CHECK:STDOUT: %.loc12_23.2: %C.131 = bind_value %.loc12_23.1
// CHECK:STDOUT: %a: %C.131 = bind_name a, %.loc12_23.2
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -135,9 +135,9 @@ fn F() {
// CHECK:STDOUT: %int_16: Core.IntLiteral = int_value 16 [concrete = constants.%int_16]
// CHECK:STDOUT: %i16: type = class_type @Int, @Int(constants.%int_16) [concrete = constants.%i16]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc7_30.1: ref %i16 = temporary_storage
// CHECK:STDOUT: %.loc7_30.2: ref %i16 = temporary %.loc7_30.1, %foo_short.call
// CHECK:STDOUT: %x: ref %i16 = bind_name x, %.loc7_30.2
// CHECK:STDOUT: %.loc7_30.1: %i16 = value_of_initializer %foo_short.call
// CHECK:STDOUT: %.loc7_30.2: %i16 = converted %foo_short.call, %.loc7_30.1
// CHECK:STDOUT: %x: %i16 = bind_name x, %.loc7_30.2
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
+40 -124
View File
@@ -2,162 +2,78 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// TODO: Add ranges and switch to "--dump-sem-ir-ranges=only".
// EXTRA-ARGS: --dump-sem-ir-ranges=if-present
//
// AUTOUPDATE
// TIP: To test this file alone, run:
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/let/convert.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/let/convert.carbon
// --- convert.carbon
library "[[@TEST_NAME]]";
fn F() -> i32 {
var v: (i32, i32, i32) = (1, 2, 3);
// Convert from object representation to value representation.
//@dump-sem-ir-begin
let w: (i32, i32, i32) = v;
//@dump-sem-ir-end
return w.1;
}
// --- fail_let_bound_to_ref_not_mutable.carbon
library "[[@TEST_NAME]]";
fn G() {
var a: i32 = 0;
let n: i32 = a;
// CHECK:STDERR: fail_let_bound_to_ref_not_mutable.carbon:[[@LINE+4]]:3: error: expression is not assignable [AssignmentToNonAssignable]
// CHECK:STDERR: n = 1;
// CHECK:STDERR: ^
// CHECK:STDERR:
n = 1;
}
// CHECK:STDOUT: --- convert.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %int_32: Core.IntLiteral = int_value 32 [concrete]
// CHECK:STDOUT: %Int.type: type = generic_class_type @Int [concrete]
// CHECK:STDOUT: %Int.generic: %Int.type = struct_value () [concrete]
// CHECK:STDOUT: %i32: type = class_type @Int, @Int(%int_32) [concrete]
// CHECK:STDOUT: %pattern_type.7ce: type = pattern_type %i32 [concrete]
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
// CHECK:STDOUT: %tuple.type.ff9: type = tuple_type (type, type, type) [concrete]
// CHECK:STDOUT: %tuple.type.189: type = tuple_type (%i32, %i32, %i32) [concrete]
// CHECK:STDOUT: %pattern_type.b5a: type = pattern_type %tuple.type.189 [concrete]
// CHECK:STDOUT: %int_1.5b8: Core.IntLiteral = int_value 1 [concrete]
// CHECK:STDOUT: %int_2.ecc: Core.IntLiteral = int_value 2 [concrete]
// CHECK:STDOUT: %int_3.1ba: Core.IntLiteral = int_value 3 [concrete]
// CHECK:STDOUT: %tuple.type.37f: type = tuple_type (Core.IntLiteral, Core.IntLiteral, Core.IntLiteral) [concrete]
// CHECK:STDOUT: %ImplicitAs.type.cc7: type = generic_interface_type @ImplicitAs [concrete]
// CHECK:STDOUT: %ImplicitAs.generic: %ImplicitAs.type.cc7 = struct_value () [concrete]
// CHECK:STDOUT: %ImplicitAs.type.205: type = facet_type <@ImplicitAs, @ImplicitAs(%i32)> [concrete]
// CHECK:STDOUT: %Convert.type.1b6: type = fn_type @Convert.1, @ImplicitAs(%i32) [concrete]
// CHECK:STDOUT: %To.c80: Core.IntLiteral = bind_symbolic_name To, 0 [symbolic]
// CHECK:STDOUT: %Convert.type.0f9: type = fn_type @Convert.3, @impl.4f9(%To.c80) [symbolic]
// CHECK:STDOUT: %Convert.f06: %Convert.type.0f9 = struct_value () [symbolic]
// CHECK:STDOUT: %ImplicitAs.impl_witness.c75: <witness> = impl_witness imports.%ImplicitAs.impl_witness_table.a2f, @impl.4f9(%int_32) [concrete]
// CHECK:STDOUT: %Convert.type.035: type = fn_type @Convert.3, @impl.4f9(%int_32) [concrete]
// CHECK:STDOUT: %Convert.956: %Convert.type.035 = struct_value () [concrete]
// CHECK:STDOUT: %ImplicitAs.facet.921: %ImplicitAs.type.205 = facet_value Core.IntLiteral, (%ImplicitAs.impl_witness.c75) [concrete]
// CHECK:STDOUT: %.9c3: type = fn_type_with_self_type %Convert.type.1b6, %ImplicitAs.facet.921 [concrete]
// CHECK:STDOUT: %Convert.bound.ab5: <bound method> = bound_method %int_1.5b8, %Convert.956 [concrete]
// CHECK:STDOUT: %Convert.specific_fn: <specific function> = specific_function %Convert.956, @Convert.3(%int_32) [concrete]
// CHECK:STDOUT: %bound_method.9a1: <bound method> = bound_method %int_1.5b8, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_1.5d2: %i32 = int_value 1 [concrete]
// CHECK:STDOUT: %Convert.bound.ef9: <bound method> = bound_method %int_2.ecc, %Convert.956 [concrete]
// CHECK:STDOUT: %bound_method.b92: <bound method> = bound_method %int_2.ecc, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_2.ef8: %i32 = int_value 2 [concrete]
// CHECK:STDOUT: %Convert.bound.b30: <bound method> = bound_method %int_3.1ba, %Convert.956 [concrete]
// CHECK:STDOUT: %bound_method.047: <bound method> = bound_method %int_3.1ba, %Convert.specific_fn [concrete]
// CHECK:STDOUT: %int_3.822: %i32 = int_value 3 [concrete]
// CHECK:STDOUT: %tuple: %tuple.type.189 = tuple_value (%int_1.5d2, %int_2.ef8, %int_3.822) [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
// CHECK:STDOUT: %Core: <namespace> = namespace file.%Core.import, [concrete] {
// CHECK:STDOUT: .Int = %Core.Int
// CHECK:STDOUT: .ImplicitAs = %Core.ImplicitAs
// CHECK:STDOUT: import Core//prelude
// CHECK:STDOUT: import Core//prelude/...
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.Int: %Int.type = import_ref Core//prelude/types/int, Int, loaded [concrete = constants.%Int.generic]
// CHECK:STDOUT: %Core.ImplicitAs: %ImplicitAs.type.cc7 = import_ref Core//prelude/operators/as, ImplicitAs, loaded [concrete = constants.%ImplicitAs.generic]
// CHECK:STDOUT: %Core.import_ref.a5b: @impl.4f9.%Convert.type (%Convert.type.0f9) = import_ref Core//prelude/types/int, loc19_39, loaded [symbolic = @impl.4f9.%Convert (constants.%Convert.f06)]
// CHECK:STDOUT: %ImplicitAs.impl_witness_table.a2f = impl_witness_table (%Core.import_ref.a5b), @impl.4f9 [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace [concrete] {
// CHECK:STDOUT: .Core = imports.%Core
// CHECK:STDOUT: .F = %F.decl
// CHECK:STDOUT: }
// CHECK:STDOUT: %Core.import = import Core
// CHECK:STDOUT: %F.decl: %F.type = fn_decl @F [concrete = constants.%F] {
// CHECK:STDOUT: %return.patt: %pattern_type.7ce = return_slot_pattern [concrete]
// CHECK:STDOUT: %return.param_patt: %pattern_type.7ce = out_param_pattern %return.patt, call_param0 [concrete]
// CHECK:STDOUT: } {
// CHECK:STDOUT: %int_32.loc14: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc14: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %return.param: ref %i32 = out_param call_param0
// CHECK:STDOUT: %return: ref %i32 = return_slot %return.param
// CHECK:STDOUT: }
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() -> %i32 {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %v.patt: %pattern_type.b5a = binding_pattern v [concrete]
// CHECK:STDOUT: %v.var_patt: %pattern_type.b5a = var_pattern %v.patt [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %v.var: ref %tuple.type.189 = var %v.var_patt
// CHECK:STDOUT: %int_1.loc15: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
// CHECK:STDOUT: %int_2: Core.IntLiteral = int_value 2 [concrete = constants.%int_2.ecc]
// CHECK:STDOUT: %int_3: Core.IntLiteral = int_value 3 [concrete = constants.%int_3.1ba]
// CHECK:STDOUT: %.loc15_36.1: %tuple.type.37f = tuple_literal (%int_1.loc15, %int_2, %int_3)
// CHECK:STDOUT: %impl.elem0.loc15_36.1: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
// CHECK:STDOUT: %bound_method.loc15_36.1: <bound method> = bound_method %int_1.loc15, %impl.elem0.loc15_36.1 [concrete = constants.%Convert.bound.ab5]
// CHECK:STDOUT: %specific_fn.loc15_36.1: <specific function> = specific_function %impl.elem0.loc15_36.1, @Convert.3(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc15_36.2: <bound method> = bound_method %int_1.loc15, %specific_fn.loc15_36.1 [concrete = constants.%bound_method.9a1]
// CHECK:STDOUT: %int.convert_checked.loc15_36.1: init %i32 = call %bound_method.loc15_36.2(%int_1.loc15) [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %.loc15_36.2: init %i32 = converted %int_1.loc15, %int.convert_checked.loc15_36.1 [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %tuple.elem0: ref %i32 = tuple_access %v.var, element0
// CHECK:STDOUT: %.loc15_36.3: init %i32 = initialize_from %.loc15_36.2 to %tuple.elem0 [concrete = constants.%int_1.5d2]
// CHECK:STDOUT: %impl.elem0.loc15_36.2: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
// CHECK:STDOUT: %bound_method.loc15_36.3: <bound method> = bound_method %int_2, %impl.elem0.loc15_36.2 [concrete = constants.%Convert.bound.ef9]
// CHECK:STDOUT: %specific_fn.loc15_36.2: <specific function> = specific_function %impl.elem0.loc15_36.2, @Convert.3(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc15_36.4: <bound method> = bound_method %int_2, %specific_fn.loc15_36.2 [concrete = constants.%bound_method.b92]
// CHECK:STDOUT: %int.convert_checked.loc15_36.2: init %i32 = call %bound_method.loc15_36.4(%int_2) [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %.loc15_36.4: init %i32 = converted %int_2, %int.convert_checked.loc15_36.2 [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %tuple.elem1.loc15: ref %i32 = tuple_access %v.var, element1
// CHECK:STDOUT: %.loc15_36.5: init %i32 = initialize_from %.loc15_36.4 to %tuple.elem1.loc15 [concrete = constants.%int_2.ef8]
// CHECK:STDOUT: %impl.elem0.loc15_36.3: %.9c3 = impl_witness_access constants.%ImplicitAs.impl_witness.c75, element0 [concrete = constants.%Convert.956]
// CHECK:STDOUT: %bound_method.loc15_36.5: <bound method> = bound_method %int_3, %impl.elem0.loc15_36.3 [concrete = constants.%Convert.bound.b30]
// CHECK:STDOUT: %specific_fn.loc15_36.3: <specific function> = specific_function %impl.elem0.loc15_36.3, @Convert.3(constants.%int_32) [concrete = constants.%Convert.specific_fn]
// CHECK:STDOUT: %bound_method.loc15_36.6: <bound method> = bound_method %int_3, %specific_fn.loc15_36.3 [concrete = constants.%bound_method.047]
// CHECK:STDOUT: %int.convert_checked.loc15_36.3: init %i32 = call %bound_method.loc15_36.6(%int_3) [concrete = constants.%int_3.822]
// CHECK:STDOUT: %.loc15_36.6: init %i32 = converted %int_3, %int.convert_checked.loc15_36.3 [concrete = constants.%int_3.822]
// CHECK:STDOUT: %tuple.elem2: ref %i32 = tuple_access %v.var, element2
// CHECK:STDOUT: %.loc15_36.7: init %i32 = initialize_from %.loc15_36.6 to %tuple.elem2 [concrete = constants.%int_3.822]
// CHECK:STDOUT: %.loc15_36.8: init %tuple.type.189 = tuple_init (%.loc15_36.3, %.loc15_36.5, %.loc15_36.7) to %v.var [concrete = constants.%tuple]
// CHECK:STDOUT: %.loc15_3: init %tuple.type.189 = converted %.loc15_36.1, %.loc15_36.8 [concrete = constants.%tuple]
// CHECK:STDOUT: assign %v.var, %.loc15_3
// CHECK:STDOUT: %.loc15_24.1: type = splice_block %.loc15_24.3 [concrete = constants.%tuple.type.189] {
// CHECK:STDOUT: %int_32.loc15_11: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc15_11: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc15_16: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc15_16: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc15_21: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc15_21: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc15_24.2: %tuple.type.ff9 = tuple_literal (%i32.loc15_11, %i32.loc15_16, %i32.loc15_21)
// CHECK:STDOUT: %.loc15_24.3: type = converted %.loc15_24.2, constants.%tuple.type.189 [concrete = constants.%tuple.type.189]
// CHECK:STDOUT: }
// CHECK:STDOUT: %v: ref %tuple.type.189 = bind_name v, %v.var
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %w.patt: %pattern_type.b5a = binding_pattern w [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %v.ref: ref %tuple.type.189 = name_ref v, %v
// CHECK:STDOUT: %.loc17_24.1: type = splice_block %.loc17_24.3 [concrete = constants.%tuple.type.189] {
// CHECK:STDOUT: %int_32.loc17_11: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc17_11: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc17_16: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc17_16: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc17_21: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc17_21: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc17_24.2: %tuple.type.ff9 = tuple_literal (%i32.loc17_11, %i32.loc17_16, %i32.loc17_21)
// CHECK:STDOUT: %.loc17_24.3: type = converted %.loc17_24.2, constants.%tuple.type.189 [concrete = constants.%tuple.type.189]
// CHECK:STDOUT: %.loc8_24.1: type = splice_block %.loc8_24.3 [concrete = constants.%tuple.type.189] {
// CHECK:STDOUT: %int_32.loc8_11: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc8_11: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc8_16: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc8_16: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %int_32.loc8_21: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc8_21: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: %.loc8_24.2: %tuple.type.ff9 = tuple_literal (%i32.loc8_11, %i32.loc8_16, %i32.loc8_21)
// CHECK:STDOUT: %.loc8_24.3: type = converted %.loc8_24.2, constants.%tuple.type.189 [concrete = constants.%tuple.type.189]
// CHECK:STDOUT: }
// CHECK:STDOUT: %w: ref %tuple.type.189 = bind_name w, %v.ref
// CHECK:STDOUT: %w.ref: ref %tuple.type.189 = name_ref w, %w
// CHECK:STDOUT: %int_1.loc18: Core.IntLiteral = int_value 1 [concrete = constants.%int_1.5b8]
// CHECK:STDOUT: %tuple.elem1.loc18: ref %i32 = tuple_access %w.ref, element1
// CHECK:STDOUT: %.loc18: %i32 = bind_value %tuple.elem1.loc18
// CHECK:STDOUT: return %.loc18
// CHECK:STDOUT: %tuple.elem0.loc8: ref %i32 = tuple_access %v.ref, element0
// CHECK:STDOUT: %.loc8_28.1: %i32 = bind_value %tuple.elem0.loc8
// CHECK:STDOUT: %tuple.elem1.loc8: ref %i32 = tuple_access %v.ref, element1
// CHECK:STDOUT: %.loc8_28.2: %i32 = bind_value %tuple.elem1.loc8
// CHECK:STDOUT: %tuple.elem2.loc8: ref %i32 = tuple_access %v.ref, element2
// CHECK:STDOUT: %.loc8_28.3: %i32 = bind_value %tuple.elem2.loc8
// CHECK:STDOUT: %tuple: %tuple.type.189 = tuple_value (%.loc8_28.1, %.loc8_28.2, %.loc8_28.3)
// CHECK:STDOUT: %.loc8_28.4: %tuple.type.189 = converted %v.ref, %tuple
// CHECK:STDOUT: %w: %tuple.type.189 = bind_name w, %.loc8_28.4
// CHECK:STDOUT: <elided>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -146,7 +146,8 @@ let x: i32 = c[0];
// CHECK:STDOUT: %.loc14_25.2: init %SubscriptType.8ee = class_init (), %.loc14_25.1 [concrete = constants.%SubscriptType.val]
// CHECK:STDOUT: %.loc14_25.3: ref %SubscriptType.8ee = temporary %.loc14_25.1, %.loc14_25.2
// CHECK:STDOUT: %.loc14_25.4: ref %SubscriptType.8ee = converted @__global_init.%.loc14, %.loc14_25.3
// CHECK:STDOUT: %s: ref %SubscriptType.8ee = bind_name s, %.loc14_25.4
// CHECK:STDOUT: %.loc14_25.5: %SubscriptType.8ee = bind_value %.loc14_25.4
// CHECK:STDOUT: %s: %SubscriptType.8ee = bind_name s, %.loc14_25.5
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %c.patt: %pattern_type.c48 = binding_pattern c [concrete]
// CHECK:STDOUT: }
@@ -155,13 +156,15 @@ let x: i32 = c[0];
// CHECK:STDOUT: %.loc15_13.2: init %C = class_init (), %.loc15_13.1 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc15_13.3: ref %C = temporary %.loc15_13.1, %.loc15_13.2
// CHECK:STDOUT: %.loc15_13.4: ref %C = converted @__global_init.%.loc15, %.loc15_13.3
// CHECK:STDOUT: %c: ref %C = bind_name c, %.loc15_13.4
// CHECK:STDOUT: %.loc15_13.5: %C = bind_value %.loc15_13.4
// CHECK:STDOUT: %c: %C = bind_name c, %.loc15_13.5
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %x.patt: %pattern_type.c39 = binding_pattern x [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %ElementType.ref: type = name_ref ElementType, %ElementType.decl [concrete = constants.%ElementType.e6b]
// CHECK:STDOUT: %.loc16: ref %ElementType.e6b = temporary @__global_init.%.loc16_25, @__global_init.%At.call
// CHECK:STDOUT: %x: ref %ElementType.e6b = bind_name x, %.loc16
// CHECK:STDOUT: %.loc16_25.1: ref %ElementType.e6b = temporary @__global_init.%.loc16, @__global_init.%At.call
// CHECK:STDOUT: %.loc16_25.2: %ElementType.e6b = bind_value %.loc16_25.1
// CHECK:STDOUT: %x: %ElementType.e6b = bind_name x, %.loc16_25.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: impl @impl: %C.ref as %IndexWith.type {
@@ -230,14 +233,12 @@ let x: i32 = c[0];
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc14: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %.loc15: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %c.ref: ref %C = name_ref c, file.%c
// CHECK:STDOUT: %s.ref: ref %SubscriptType.8ee = name_ref s, file.%s
// CHECK:STDOUT: %.loc16_24: %SubscriptType.8ee = bind_value %s.ref
// CHECK:STDOUT: %c.ref: %C = name_ref c, file.%c
// CHECK:STDOUT: %s.ref: %SubscriptType.8ee = name_ref s, file.%s
// CHECK:STDOUT: %impl.elem0: %.d94 = impl_witness_access constants.%IndexWith.impl_witness, element0 [concrete = constants.%At.d43]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %c.ref, %impl.elem0
// CHECK:STDOUT: %.loc16_25: ref %ElementType.e6b = temporary_storage
// CHECK:STDOUT: %.loc16_22: %C = bind_value %c.ref
// CHECK:STDOUT: %At.call: init %ElementType.e6b = call %bound_method(%.loc16_22, %.loc16_24) to %.loc16_25
// CHECK:STDOUT: %.loc16: ref %ElementType.e6b = temporary_storage
// CHECK:STDOUT: %At.call: init %ElementType.e6b = call %bound_method(%c.ref, %s.ref) to %.loc16
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -364,9 +365,9 @@ let x: i32 = c[0];
// CHECK:STDOUT: %int_32.loc11: Core.IntLiteral = int_value 32 [concrete = constants.%int_32]
// CHECK:STDOUT: %i32.loc11: type = class_type @Int, @Int(constants.%int_32) [concrete = constants.%i32]
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc11_17.1: ref %i32 = temporary_storage
// CHECK:STDOUT: %.loc11_17.2: ref %i32 = temporary %.loc11_17.1, @__global_init.%At.call
// CHECK:STDOUT: %e: ref %i32 = bind_name e, %.loc11_17.2
// CHECK:STDOUT: %.loc11_17.1: %i32 = value_of_initializer @__global_init.%At.call
// CHECK:STDOUT: %.loc11_17.2: %i32 = converted @__global_init.%At.call, %.loc11_17.1
// CHECK:STDOUT: %e: %i32 = bind_name e, %.loc11_17.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: impl @impl.18b: %.loc4_15.2 as %IndexWith.type {
@@ -495,13 +496,15 @@ let x: i32 = c[0];
// CHECK:STDOUT: %.loc14_13.2: init %C = class_init (), %.loc14_13.1 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc14_13.3: ref %C = temporary %.loc14_13.1, %.loc14_13.2
// CHECK:STDOUT: %.loc14_13.4: ref %C = converted @__global_init.%.loc14, %.loc14_13.3
// CHECK:STDOUT: %c: ref %C = bind_name c, %.loc14_13.4
// CHECK:STDOUT: %.loc14_13.5: %C = bind_value %.loc14_13.4
// CHECK:STDOUT: %c: %C = bind_name c, %.loc14_13.5
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %x.patt: %pattern_type.c39 = binding_pattern x [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT: %ElementType.ref: type = name_ref ElementType, %ElementType.decl [concrete = constants.%ElementType.e6b]
// CHECK:STDOUT: %.loc22: ref %ElementType.e6b = temporary @__global_init.%.loc22_25.2, @__global_init.%At.call
// CHECK:STDOUT: %x: ref %ElementType.e6b = bind_name x, %.loc22
// CHECK:STDOUT: %.loc22_25.1: ref %ElementType.e6b = temporary @__global_init.%.loc22_25.2, @__global_init.%At.call
// CHECK:STDOUT: %.loc22_25.2: %ElementType.e6b = bind_value %.loc22_25.1
// CHECK:STDOUT: %x: %ElementType.e6b = bind_name x, %.loc22_25.2
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: impl @impl.066: %C.ref as %IndexWith.type {
@@ -569,14 +572,13 @@ let x: i32 = c[0];
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc14: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %c.ref: ref %C = name_ref c, file.%c
// CHECK:STDOUT: %c.ref: %C = name_ref c, file.%c
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]
// CHECK:STDOUT: %.loc22_25.1: %SubscriptType.8ee = converted %int_0, <error> [concrete = <error>]
// CHECK:STDOUT: %impl.elem0: %.d94 = impl_witness_access constants.%IndexWith.impl_witness, element0 [concrete = constants.%At.d43]
// CHECK:STDOUT: %bound_method: <bound method> = bound_method %c.ref, %impl.elem0
// CHECK:STDOUT: %.loc22_25.2: ref %ElementType.e6b = temporary_storage
// CHECK:STDOUT: %.loc22_22: %C = bind_value %c.ref
// CHECK:STDOUT: %At.call: init %ElementType.e6b = call %bound_method(%.loc22_22, <error>) to %.loc22_25.2
// CHECK:STDOUT: %At.call: init %ElementType.e6b = call %bound_method(%c.ref, <error>) to %.loc22_25.2
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -626,7 +628,8 @@ let x: i32 = c[0];
// CHECK:STDOUT: %.loc6_13.2: init %C = class_init (), %.loc6_13.1 [concrete = constants.%C.val]
// CHECK:STDOUT: %.loc6_13.3: ref %C = temporary %.loc6_13.1, %.loc6_13.2
// CHECK:STDOUT: %.loc6_13.4: ref %C = converted @__global_init.%.loc6, %.loc6_13.3
// CHECK:STDOUT: %c: ref %C = bind_name c, %.loc6_13.4
// CHECK:STDOUT: %.loc6_13.5: %C = bind_value %.loc6_13.4
// CHECK:STDOUT: %c: %C = bind_name c, %.loc6_13.5
// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %x.patt: %pattern_type.7ce = binding_pattern x [concrete]
// CHECK:STDOUT: }
@@ -649,7 +652,7 @@ let x: i32 = c[0];
// CHECK:STDOUT: fn @__global_init() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %.loc6: %empty_struct_type = struct_literal ()
// CHECK:STDOUT: %c.ref: ref %C = name_ref c, file.%c
// CHECK:STDOUT: %c.ref: %C = name_ref c, file.%c
// CHECK:STDOUT: %int_0: Core.IntLiteral = int_value 0 [concrete = constants.%int_0]
// CHECK:STDOUT: return
// CHECK:STDOUT: }
+7 -2
View File
@@ -753,6 +753,7 @@ fn G() {
// CHECK:STDOUT: %G: %G.type = struct_value () [concrete]
// CHECK:STDOUT: %tuple.type: type = tuple_type (%empty_tuple.type, %empty_tuple.type, %empty_tuple.type) [concrete]
// CHECK:STDOUT: %pattern_type.8c1: type = pattern_type %tuple.type [concrete]
// CHECK:STDOUT: %empty_tuple: %empty_tuple.type = tuple_value () [concrete]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: imports {
@@ -805,7 +806,9 @@ fn G() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc8_38.1: ref %empty_tuple.type = temporary_storage
// CHECK:STDOUT: %.loc8_38.2: ref %empty_tuple.type = temporary %.loc8_38.1, %F.call.loc8_38
// CHECK:STDOUT: %x: ref %empty_tuple.type = bind_name x, %.loc8_38.2
// CHECK:STDOUT: %tuple.loc8_38: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]
// CHECK:STDOUT: %.loc8_38.3: %empty_tuple.type = converted %F.call.loc8_38, %tuple.loc8_38 [concrete = constants.%empty_tuple]
// CHECK:STDOUT: %x: %empty_tuple.type = bind_name x, %.loc8_38.3
// CHECK:STDOUT: assign %y.var, %F.call.loc8_43
// CHECK:STDOUT: %.loc8_23.1: type = splice_block %.loc8_23.3 [concrete = constants.%empty_tuple.type] {
// CHECK:STDOUT: %.loc8_23.2: %empty_tuple.type = tuple_literal ()
@@ -818,7 +821,9 @@ fn G() {
// CHECK:STDOUT: }
// CHECK:STDOUT: %.loc8_48.1: ref %empty_tuple.type = temporary_storage
// CHECK:STDOUT: %.loc8_48.2: ref %empty_tuple.type = temporary %.loc8_48.1, %F.call.loc8_48
// CHECK:STDOUT: %z: ref %empty_tuple.type = bind_name z, %.loc8_48.2
// CHECK:STDOUT: %tuple.loc8_48: %empty_tuple.type = tuple_value () [concrete = constants.%empty_tuple]
// CHECK:STDOUT: %.loc8_48.3: %empty_tuple.type = converted %F.call.loc8_48, %tuple.loc8_48 [concrete = constants.%empty_tuple]
// CHECK:STDOUT: %z: %empty_tuple.type = bind_name z, %.loc8_48.3
// CHECK:STDOUT: return
// CHECK:STDOUT: }
// CHECK:STDOUT:
+7
View File
@@ -51,6 +51,13 @@ constexpr Kind UntestedKinds[] = {
// - Require all diagnostics produced by compiling have their first location
// be in the file being compiled, never an import.
Kind::LanguageServerDiagnosticInWrongFile,
// TODO: This can only fire if we attempt to convert a non-reference
// expression to a durable reference binding. At the moment, the only time
// we attempt reference binding is within a `var` pattern, where the
// conversion cannot fail. This should be covered once we support `ref`
// binding syntax.
Kind::ConversionFailureNonRefToRef,
};
// Looks for diagnostic kinds that aren't covered by a file_test.
@@ -440,6 +440,7 @@ CARBON_DIAGNOSTIC_KIND(ConversionFailure)
CARBON_DIAGNOSTIC_KIND(ConversionFailureNonTypeToFacet)
CARBON_DIAGNOSTIC_KIND(ConversionFailureFacetToFacet)
CARBON_DIAGNOSTIC_KIND(ConversionFailureTypeToFacet)
CARBON_DIAGNOSTIC_KIND(ConversionFailureNonRefToRef)
CARBON_DIAGNOSTIC_KIND(TypeExprEvaluationFailure)
CARBON_DIAGNOSTIC_KIND(UnexpectedDeclNameParams)
CARBON_DIAGNOSTIC_KIND(QualifiedNameInNonScope)
+4 -8
View File
@@ -30,11 +30,8 @@ fn F(p: C*) {
// CHECK:STDOUT: define void @_CF.Main(ptr %p) !dbg !4 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %Get.call = call i32 @_CGet.C.Main(ptr %p), !dbg !7
// CHECK:STDOUT: %.loc19_25.1.temp = alloca i32, align 4, !dbg !7
// CHECK:STDOUT: store i32 %Get.call, ptr %.loc19_25.1.temp, align 4, !dbg !7
// CHECK:STDOUT: %.loc20_12 = load i32, ptr %.loc19_25.1.temp, align 4, !dbg !8
// CHECK:STDOUT: call void @_CSet.C.Main(ptr %p, i32 %.loc20_12), !dbg !9
// CHECK:STDOUT: ret void, !dbg !10
// CHECK:STDOUT: call void @_CSet.C.Main(ptr %p, i32 %Get.call), !dbg !8
// CHECK:STDOUT: ret void, !dbg !9
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
@@ -48,6 +45,5 @@ fn F(p: C*) {
// CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
// CHECK:STDOUT: !6 = !{}
// CHECK:STDOUT: !7 = !DILocation(line: 19, column: 16, scope: !4)
// CHECK:STDOUT: !8 = !DILocation(line: 20, column: 12, scope: !4)
// CHECK:STDOUT: !9 = !DILocation(line: 20, column: 3, scope: !4)
// CHECK:STDOUT: !10 = !DILocation(line: 18, column: 1, scope: !4)
// CHECK:STDOUT: !8 = !DILocation(line: 20, column: 3, scope: !4)
// CHECK:STDOUT: !9 = !DILocation(line: 18, column: 1, scope: !4)
@@ -69,16 +69,12 @@ fn Run() {
// CHECK:STDOUT: define linkonce_odr void @_CG.Main.ae78220c5e9d4af5() !dbg !16 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc35_20.1 = call i1 @"_CF.X.Main:I.Main"(), !dbg !17
// CHECK:STDOUT: %.loc35_20.2.temp = alloca i1, align 1, !dbg !17
// CHECK:STDOUT: store i1 %.loc35_20.1, ptr %.loc35_20.2.temp, align 1, !dbg !17
// CHECK:STDOUT: ret void, !dbg !18
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: define linkonce_odr void @_CG.Main.6b293b16be321a45() !dbg !19 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %.loc35_20.1 = call i32 @"_CF.Y.Main:I.Main"(), !dbg !20
// CHECK:STDOUT: %.loc35_20.2.temp = alloca i32, align 4, !dbg !20
// CHECK:STDOUT: store i32 %.loc35_20.1, ptr %.loc35_20.2.temp, align 4, !dbg !20
// CHECK:STDOUT: ret void, !dbg !21
// CHECK:STDOUT: }
// CHECK:STDOUT:
+64
View File
@@ -0,0 +1,64 @@
// 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/lower/testdata/let/copy_value_rep.carbon
// TIP: To dump output, run:
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/lower/testdata/let/copy_value_rep.carbon
class X {
var a: i32;
}
fn Run() -> i32 {
var x: X = {.a = 1};
let n: i32 = x.a;
x.a = 2;
// Should return 1, not 2.
return n;
}
// CHECK:STDOUT: ; ModuleID = 'copy_value_rep.carbon'
// CHECK:STDOUT: source_filename = "copy_value_rep.carbon"
// CHECK:STDOUT:
// CHECK:STDOUT: @X.val.loc16_3 = internal constant { i32 } { i32 1 }
// CHECK:STDOUT:
// CHECK:STDOUT: define i32 @main() !dbg !4 {
// CHECK:STDOUT: entry:
// CHECK:STDOUT: %x.var = alloca { i32 }, align 8, !dbg !7
// CHECK:STDOUT: call void @llvm.lifetime.start.p0(i64 4, ptr %x.var), !dbg !7
// CHECK:STDOUT: %.loc16_21.3.a = getelementptr inbounds nuw { i32 }, ptr %x.var, i32 0, i32 0, !dbg !8
// CHECK:STDOUT: call void @llvm.memcpy.p0.p0.i64(ptr align 4 %x.var, ptr align 4 @X.val.loc16_3, i64 4, i1 false), !dbg !7
// CHECK:STDOUT: %.loc17_17.1.a = getelementptr inbounds nuw { i32 }, ptr %x.var, i32 0, i32 0, !dbg !9
// CHECK:STDOUT: %.loc17_17.2 = load i32, ptr %.loc17_17.1.a, align 4, !dbg !9
// CHECK:STDOUT: %.loc18_4.a = getelementptr inbounds nuw { i32 }, ptr %x.var, i32 0, i32 0, !dbg !10
// CHECK:STDOUT: store i32 2, ptr %.loc18_4.a, align 4, !dbg !10
// CHECK:STDOUT: ret i32 %.loc17_17.2, !dbg !11
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
// CHECK:STDOUT: declare void @llvm.lifetime.start.p0(i64 immarg, ptr captures(none)) #0
// CHECK:STDOUT:
// CHECK:STDOUT: ; Function Attrs: nocallback nofree nounwind willreturn memory(argmem: readwrite)
// CHECK:STDOUT: declare void @llvm.memcpy.p0.p0.i64(ptr noalias writeonly captures(none), ptr noalias readonly captures(none), i64, i1 immarg) #1
// CHECK:STDOUT:
// CHECK:STDOUT: attributes #0 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
// CHECK:STDOUT: attributes #1 = { nocallback nofree nounwind willreturn memory(argmem: readwrite) }
// CHECK:STDOUT:
// CHECK:STDOUT: !llvm.module.flags = !{!0, !1}
// CHECK:STDOUT: !llvm.dbg.cu = !{!2}
// CHECK:STDOUT:
// CHECK:STDOUT: !0 = !{i32 7, !"Dwarf Version", i32 5}
// CHECK:STDOUT: !1 = !{i32 2, !"Debug Info Version", i32 3}
// CHECK:STDOUT: !2 = distinct !DICompileUnit(language: DW_LANG_C, file: !3, producer: "carbon", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug)
// CHECK:STDOUT: !3 = !DIFile(filename: "copy_value_rep.carbon", directory: "")
// CHECK:STDOUT: !4 = distinct !DISubprogram(name: "Run", linkageName: "main", scope: null, file: !3, line: 15, type: !5, spFlags: DISPFlagDefinition, unit: !2)
// CHECK:STDOUT: !5 = !DISubroutineType(types: !6)
// CHECK:STDOUT: !6 = !{}
// CHECK:STDOUT: !7 = !DILocation(line: 16, column: 3, scope: !4)
// CHECK:STDOUT: !8 = !DILocation(line: 16, column: 14, scope: !4)
// CHECK:STDOUT: !9 = !DILocation(line: 17, column: 16, scope: !4)
// CHECK:STDOUT: !10 = !DILocation(line: 18, column: 3, scope: !4)
// CHECK:STDOUT: !11 = !DILocation(line: 20, column: 3, scope: !4)