Implement constant handling for types of imports. (#3693)

This provides support for Const, Pointer, Struct, and Tuple types. It
does not cover Class, Function, or Interface which have their own Id and
are tracked slightly differently.
This commit is contained in:
Jon Ross-Perkins
2024-02-09 00:11:37 +00:00
committed by GitHub
parent 4d0c3811c9
commit 475ecca339
17 changed files with 909 additions and 252 deletions
+2
View File
@@ -54,6 +54,8 @@ cc_library(
"convert.cpp",
"decl_name_stack.cpp",
"eval.cpp",
"import_ref.cpp",
"import_ref.h",
"inst_block_stack.cpp",
"modifiers.cpp",
"return.cpp",
+5
View File
@@ -16,6 +16,7 @@
#include "toolchain/sem_ir/file.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/typed_insts.h"
#include "toolchain/sem_ir/value_stores.h"
namespace Carbon::Check {
@@ -196,6 +197,10 @@ static auto InitPackageScopeAndImports(Context& context, UnitInfo& unit_info)
context.AddPackageImports(package_imports.node, package_id, sem_irs,
package_imports.has_load_error);
}
context.import_ir_constant_values().resize(
context.import_irs().size(),
SemIR::ConstantValueStore(SemIR::ConstantId::Invalid));
}
// Loops over all nodes in the tree. On some errors, this may return early,
+7 -43
View File
@@ -12,8 +12,10 @@
#include "llvm/ADT/Sequence.h"
#include "toolchain/check/decl_name_stack.h"
#include "toolchain/check/eval.h"
#include "toolchain/check/import_ref.h"
#include "toolchain/check/inst_block_stack.h"
#include "toolchain/lex/tokenized_buffer.h"
#include "toolchain/parse/node_ids.h"
#include "toolchain/parse/node_kind.h"
#include "toolchain/sem_ir/builtin_kind.h"
#include "toolchain/sem_ir/file.h"
@@ -228,45 +230,6 @@ auto Context::AddNameToLookup(SemIR::NameId name_id, SemIR::InstId target_id)
}
}
auto Context::ResolveIfImportRefUnused(SemIR::InstId inst_id) -> void {
auto inst = insts().Get(inst_id);
auto unused_inst = inst.TryAs<SemIR::ImportRefUnused>();
if (!unused_inst) {
return;
}
const SemIR::File& import_ir = *import_irs().Get(unused_inst->ir_id);
auto import_inst = import_ir.insts().Get(unused_inst->inst_id);
// If the type ID isn't a normal value, forward it directly.
if (!import_inst.type_id().is_valid()) {
ReplaceInstBeforeConstantUse(
inst_id,
{SemIR::ImportRefUsed{import_inst.type_id(), unused_inst->ir_id,
unused_inst->inst_id}});
return;
}
auto import_type_inst_id = import_ir.types().GetInstId(import_inst.type_id());
CARBON_CHECK(import_type_inst_id.is_valid());
// If the type of the instruction is a builtin, use it directly.
auto type_id = SemIR::TypeId::Invalid;
if (import_type_inst_id.is_builtin()) {
type_id = GetBuiltinType(import_type_inst_id.builtin_kind());
} else {
// TODO: This section probably needs to TryEvalInst for the type. Similar to
// GetTypeImpl, but in the context of import_ir.
TODO(Parse::NodeId::Invalid,
"TODO: ResolveIfImportRefUnused for non-builtin type");
type_id = SemIR::TypeId::Error;
}
// TODO: Add breadcrumbs for lowering.
ReplaceInstBeforeConstantUse(
inst_id, {SemIR::ImportRefUsed{type_id, unused_inst->ir_id,
unused_inst->inst_id}});
}
auto Context::LookupNameInDecl(Parse::NodeId /*parse_node*/,
SemIR::NameId name_id,
SemIR::NameScopeId scope_id) -> SemIR::InstId {
@@ -296,7 +259,7 @@ auto Context::LookupNameInDecl(Parse::NodeId /*parse_node*/,
// name A from the outer scope.
auto result = scope_stack().LookupInCurrentScope(name_id);
if (result.is_valid()) {
ResolveIfImportRefUnused(result);
TryResolveImportRefUnused(*this, result);
}
return result;
} else {
@@ -333,7 +296,7 @@ auto Context::LookupUnqualifiedName(Parse::NodeId parse_node,
}
if (lexical_result.is_valid()) {
ResolveIfImportRefUnused(lexical_result);
TryResolveImportRefUnused(*this, lexical_result);
return lexical_result;
}
@@ -346,7 +309,7 @@ auto Context::LookupNameInExactScope(SemIR::NameId name_id,
const SemIR::NameScope& scope)
-> SemIR::InstId {
if (auto it = scope.names.find(name_id); it != scope.names.end()) {
ResolveIfImportRefUnused(it->second);
TryResolveImportRefUnused(*this, it->second);
return it->second;
}
return SemIR::InstId::Invalid;
@@ -985,7 +948,8 @@ auto Context::TryToCompleteType(
auto Context::GetTypeIdForTypeConstant(SemIR::ConstantId constant_id)
-> SemIR::TypeId {
CARBON_CHECK(constant_id.is_constant()) << "Canonicalizing non-constant type";
CARBON_CHECK(constant_id.is_constant())
<< "Canonicalizing non-constant type: " << constant_id;
auto [it, added] = type_ids_for_type_constants_.insert(
{constant_id, SemIR::TypeId::Invalid});
+11 -4
View File
@@ -337,6 +337,11 @@ class Context {
return scope_stack().break_continue_stack();
}
auto import_ir_constant_values()
-> llvm::SmallVector<SemIR::ConstantValueStore, 0>& {
return import_ir_constant_values_;
}
// Directly expose SemIR::File data accessors for brevity in calls.
auto identifiers() -> StringStoreWrapper<IdentifierId>& {
@@ -394,10 +399,6 @@ class Context {
SemIR::TypeId type_id_;
};
// If the passed in instruction ID is a ImportRefUnused, resolves it for use.
// Called when name lookup intends to return an inst_id.
auto ResolveIfImportRefUnused(SemIR::InstId inst_id) -> void;
// Tokens for getting data on literals.
const Lex::TokenizedBuffer* tokens_;
@@ -452,6 +453,12 @@ class Context {
// The list which will form NodeBlockId::Exports.
llvm::SmallVector<SemIR::InstId> exports_;
// Per-import constant values. These refer to the main IR and mainly serve as
// a lookup table for quick access.
//
// Inline 0 elements because it's expected to require heap allocation.
llvm::SmallVector<SemIR::ConstantValueStore, 0> import_ir_constant_values_;
};
} // namespace Carbon::Check
+275
View File
@@ -0,0 +1,275 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#include "toolchain/check/import_ref.h"
#include "common/check.h"
#include "toolchain/check/context.h"
#include "toolchain/check/eval.h"
#include "toolchain/parse/node_ids.h"
#include "toolchain/sem_ir/file.h"
#include "toolchain/sem_ir/ids.h"
#include "toolchain/sem_ir/inst.h"
#include "toolchain/sem_ir/inst_kind.h"
#include "toolchain/sem_ir/typed_insts.h"
#include "toolchain/sem_ir/value_stores.h"
namespace Carbon::Check {
// Resolves an instruction from an imported IR into a constant referring to the
// current IR.
class ImportRefResolver {
public:
explicit ImportRefResolver(
Context& context, const SemIR::File& import_ir,
SemIR::ConstantValueStore& import_ir_constant_values)
: context_(context),
import_ir_(import_ir),
import_ir_constant_values_(import_ir_constant_values) {}
// Iteratively resolves an imported instruction's inner references until a
// constant ID referencing the current IR is produced. When an outer
// instruction has unresolved inner references, it will add them to the stack
// for inner evaluation and reattempt outer evaluation after.
auto Resolve(SemIR::InstId inst_id) -> SemIR::ConstantId {
work_stack_.push_back(inst_id);
while (!work_stack_.empty()) {
auto inst_id = work_stack_.back();
CARBON_CHECK(inst_id.is_valid());
// Double-check that the constant still doesn't have a calculated value.
// This should typically be checked before adding it, but a given constant
// may be added multiple times before its constant is evaluated.
if (auto current_const_id = import_ir_constant_values_.Get(inst_id);
current_const_id.is_valid()) {
work_stack_.pop_back();
} else if (auto new_const_id = TryResolveInst(inst_id);
new_const_id.is_valid()) {
import_ir_constant_values_.Set(inst_id, new_const_id);
work_stack_.pop_back();
}
}
auto constant_id = import_ir_constant_values_.Get(inst_id);
CARBON_CHECK(constant_id.is_valid());
return constant_id;
}
private:
// Returns the ConstantId for an instruction, or adds it to the stack and
// returns Invalid if the ConstantId is not ready.
auto GetConstantId(SemIR::TypeId type_id) -> SemIR::ConstantId {
auto inst_id = import_ir_.types().GetInstId(type_id);
auto const_id = import_ir_constant_values_.Get(inst_id);
if (!const_id.is_valid()) {
work_stack_.push_back(inst_id);
}
return const_id;
}
// Tries to resolve the InstId, returning a constant when ready, or Invalid if
// more has been added to the stack. A similar API is followed for all
// following TryResolveTypedInst helper functions.
//
// Logic for each TryResolveTypedInst will be in two phases:
// 1. Gather all input constants.
// 2. Produce an output constant.
//
// Although it's possible TryResolveTypedInst could complete in a single call
// when all input constants are ready, a common scenario is that some inputs
// will still be unresolved, and it'll return Invalid between phases. On the
// second call, all previously unready constants will have been resolved, so
// it should run to completion. As a consequence, it's important to reserve
// all expensive logic for the second phase; this in particular includes
// GetTypeIdForTypeConstant calls which do a hash table lookup.
//
// TODO: Error is returned when support is missing, but that should go away.
auto TryResolveInst(SemIR::InstId inst_id) -> SemIR::ConstantId {
if (inst_id.is_builtin()) {
// Constants for builtins can be directly copied.
return context_.constant_values().Get(inst_id);
}
auto inst = import_ir_.insts().Get(inst_id);
switch (inst.kind()) {
case SemIR::InstKind::ConstType:
return TryResolveTypedInst(inst.As<SemIR::ConstType>());
case SemIR::InstKind::PointerType:
return TryResolveTypedInst(inst.As<SemIR::PointerType>());
case SemIR::InstKind::StructType:
return TryResolveTypedInst(inst.As<SemIR::StructType>());
case SemIR::InstKind::TupleType:
return TryResolveTypedInst(inst.As<SemIR::TupleType>());
default:
context_.TODO(
Parse::NodeId::Invalid,
llvm::formatv("TryResolveInst on {0}", inst.kind()).str());
return SemIR::ConstantId::Error;
}
}
auto TryResolveTypedInst(SemIR::ConstType inst) -> SemIR::ConstantId {
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
auto inner_const_id = GetConstantId(inst.inner_id);
if (!inner_const_id.is_valid()) {
return SemIR::ConstantId::Invalid;
}
auto inner_type_id = context_.GetTypeIdForTypeConstant(inner_const_id);
// TODO: Should ConstType have a wrapper for this similar to the others?
return TryEvalInst(
context_, SemIR::InstId::Invalid,
SemIR::ConstType{SemIR::TypeId::TypeType, inner_type_id});
}
auto TryResolveTypedInst(SemIR::PointerType inst) -> SemIR::ConstantId {
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
auto pointee_const_id = GetConstantId(inst.pointee_id);
if (!pointee_const_id.is_valid()) {
return SemIR::ConstantId::Invalid;
}
auto pointee_type_id = context_.GetTypeIdForTypeConstant(pointee_const_id);
return context_.types().GetConstantId(
context_.GetPointerType(pointee_type_id));
}
auto TryResolveTypedInst(SemIR::StructType inst) -> SemIR::ConstantId {
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
// Collect all constants first, locating unresolved ones in a single pass.
bool has_unresolved = false;
auto orig_fields = import_ir_.inst_blocks().Get(inst.fields_id);
llvm::SmallVector<SemIR::ConstantId> field_const_ids;
field_const_ids.reserve(orig_fields.size());
for (auto field_id : orig_fields) {
auto field = import_ir_.insts().GetAs<SemIR::StructTypeField>(field_id);
auto field_const_id = GetConstantId(field.field_type_id);
if (field_const_id.is_valid()) {
field_const_ids.push_back(field_const_id);
} else {
has_unresolved = true;
}
}
if (has_unresolved) {
return SemIR::ConstantId::Invalid;
}
// Prepare a vector of fields for GetStructType.
// TODO: Should we have field constants so that we can deduplicate fields
// without creating instructions here?
llvm::SmallVector<SemIR::InstId> fields;
fields.reserve(orig_fields.size());
for (auto [field_id, field_const_id] :
llvm::zip(orig_fields, field_const_ids)) {
auto field = import_ir_.insts().GetAs<SemIR::StructTypeField>(field_id);
auto name_str = import_ir_.names().GetAsStringIfIdentifier(field.name_id);
auto name_id = name_str ? SemIR::NameId::ForIdentifier(
context_.identifiers().Add(*name_str))
: field.name_id;
auto field_type_id = context_.GetTypeIdForTypeConstant(field_const_id);
fields.push_back(context_.AddInstInNoBlock(
{Parse::NodeId::Invalid,
SemIR::StructTypeField{.name_id = name_id,
.field_type_id = field_type_id}}));
}
return context_.types().GetConstantId(
context_.GetStructType(context_.inst_blocks().Add(fields)));
}
auto TryResolveTypedInst(SemIR::TupleType inst) -> SemIR::ConstantId {
CARBON_CHECK(inst.type_id == SemIR::TypeId::TypeType);
// Collect all constants first, locating unresolved ones in a single pass.
bool has_unresolved = false;
auto orig_elem_type_ids = import_ir_.type_blocks().Get(inst.elements_id);
llvm::SmallVector<SemIR::ConstantId> elem_const_ids;
elem_const_ids.reserve(orig_elem_type_ids.size());
for (auto elem_type_id : orig_elem_type_ids) {
auto elem_const_id = GetConstantId(elem_type_id);
if (elem_const_id.is_valid()) {
elem_const_ids.push_back(elem_const_id);
} else {
has_unresolved = true;
}
}
if (has_unresolved) {
return SemIR::ConstantId::Invalid;
}
// Prepare a vector of the tuple types for GetTupleType.
llvm::SmallVector<SemIR::TypeId> elem_type_ids;
elem_type_ids.reserve(orig_elem_type_ids.size());
for (auto elem_const_id : elem_const_ids) {
elem_type_ids.push_back(context_.GetTypeIdForTypeConstant(elem_const_id));
}
return context_.types().GetConstantId(context_.GetTupleType(elem_type_ids));
}
Context& context_;
const SemIR::File& import_ir_;
SemIR::ConstantValueStore& import_ir_constant_values_;
llvm::SmallVector<SemIR::InstId> work_stack_;
};
auto TryResolveImportRefUnused(Context& context, SemIR::InstId inst_id)
-> void {
auto inst = context.insts().Get(inst_id);
auto unused_inst = inst.TryAs<SemIR::ImportRefUnused>();
if (!unused_inst) {
return;
}
const SemIR::File& import_ir = *context.import_irs().Get(unused_inst->ir_id);
auto import_inst = import_ir.insts().Get(unused_inst->inst_id);
// TODO: Types need to be specifically addressed here to prevent crashes in
// constant evaluation while support is incomplete. Functions are also
// incomplete, but are allowed to fail differently because they aren't a type.
// The partial function support is useful for some namespace validation.
if (import_inst.Is<SemIR::ClassDecl>() ||
import_inst.Is<SemIR::InterfaceDecl>()) {
context.TODO(
Parse::NodeId::Invalid,
llvm::formatv("TryResolveImportRefUnused on {0}", import_inst.kind())
.str());
context.ReplaceInstBeforeConstantUse(
inst_id, {SemIR::ImportRefUsed{SemIR::TypeId::Error, unused_inst->ir_id,
unused_inst->inst_id}});
return;
}
// If the type ID isn't a normal value, forward it directly.
if (!import_inst.type_id().is_valid()) {
context.ReplaceInstBeforeConstantUse(
inst_id,
{SemIR::ImportRefUsed{import_inst.type_id(), unused_inst->ir_id,
unused_inst->inst_id}});
return;
}
auto import_type_inst_id = import_ir.types().GetInstId(import_inst.type_id());
CARBON_CHECK(import_type_inst_id.is_valid());
auto type_id = SemIR::TypeId::Invalid;
if (import_type_inst_id.is_builtin()) {
// Builtins don't require constant resolution; we can use them directly.
type_id = context.GetBuiltinType(import_type_inst_id.builtin_kind());
} else {
ImportRefResolver resolver(
context, import_ir,
context.import_ir_constant_values()[unused_inst->ir_id.index]);
type_id =
context.GetTypeIdForTypeConstant(resolver.Resolve(import_type_inst_id));
}
// TODO: Add breadcrumbs for lowering.
context.ReplaceInstBeforeConstantUse(
inst_id, {SemIR::ImportRefUsed{type_id, unused_inst->ir_id,
unused_inst->inst_id}});
}
} // namespace Carbon::Check
+19
View File
@@ -0,0 +1,19 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
#ifndef CARBON_TOOLCHAIN_CHECK_IMPORT_REF_H_
#define CARBON_TOOLCHAIN_CHECK_IMPORT_REF_H_
#include "toolchain/check/context.h"
#include "toolchain/sem_ir/file.h"
namespace Carbon::Check {
// If the passed in instruction ID is a ImportRefUnused, resolves it for use.
// Otherwise, errors.
auto TryResolveImportRefUnused(Context& context, SemIR::InstId inst_id) -> void;
} // namespace Carbon::Check
#endif // CARBON_TOOLCHAIN_CHECK_IMPORT_REF_H_
+76 -14
View File
@@ -3,6 +3,10 @@
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// AUTOUPDATE
// CHECK:STDERR: b.carbon: ERROR: Semantics TODO: `TryResolveImportRefUnused on ClassDecl`.
// CHECK:STDERR: b.carbon: ERROR: Semantics TODO: `TryResolveImportRefUnused on ClassDecl`.
// CHECK:STDERR: b.carbon: ERROR: Semantics TODO: `TryResolveInst on ClassType`.
// CHECK:STDERR: b.carbon: ERROR: Semantics TODO: `TryResolveInst on ClassType`.
// --- a.carbon
@@ -17,6 +21,11 @@ class ForwardDeclared {
fn F();
}
var a_ref: Empty = {};
var b_ref: ForwardDeclared = {};
var c_ref: ForwardDeclared* = &b_ref;
// var d_ref: (ForwardDeclared,) = ({},);
// --- b.carbon
library "b" api;
@@ -24,30 +33,58 @@ library "b" api;
import library "a";
fn Run() {
// CHECK:STDERR: b.carbon:[[@LINE+3]]:10: ERROR: Expression cannot be used as a value.
// CHECK:STDERR: var x: Empty = {};
// CHECK:STDERR: ^~~~~
var x: Empty = {};
// CHECK:STDERR: b.carbon:[[@LINE+3]]:10: ERROR: Expression cannot be used as a value.
// CHECK:STDERR: var y: ForwardDeclared = {};
// CHECK:STDERR: ^~~~~~~~~~~~~~~
var y: ForwardDeclared = {};
y.F();
}
var a: Empty = a_ref;
var b: ForwardDeclared = b_ref;
var c: ForwardDeclared* = c_ref;
// CHECK:STDERR: b.carbon:[[@LINE+3]]:29: ERROR: Name `d_ref` not found.
// CHECK:STDERR: var d: (ForwardDeclared,) = d_ref;
// CHECK:STDERR: ^~~~~
var d: (ForwardDeclared,) = d_ref;
// CHECK:STDOUT: --- a.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %Empty: type = class_type @Empty [template]
// CHECK:STDOUT: %.1: type = struct_type {} [template]
// CHECK:STDOUT: %ForwardDeclared: type = class_type @ForwardDeclared [template]
// CHECK:STDOUT: %.2: type = tuple_type () [template]
// CHECK:STDOUT: %.3: type = ptr_type {} [template]
// CHECK:STDOUT: %.4: Empty = struct_value () [template]
// CHECK:STDOUT: %.5: ForwardDeclared = struct_value () [template]
// CHECK:STDOUT: %.6: type = ptr_type ForwardDeclared [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.Empty = %Empty.decl, .ForwardDeclared = %ForwardDeclared.decl.loc7} [template]
// CHECK:STDOUT: package: <namespace> = namespace {.Empty = %Empty.decl, .ForwardDeclared = %ForwardDeclared.decl.loc7, .a_ref = %a_ref, .b_ref = %b_ref, .c_ref = %c_ref} [template]
// CHECK:STDOUT: %Empty.decl = class_decl @Empty, ()
// CHECK:STDOUT: %ForwardDeclared.decl.loc7 = class_decl @ForwardDeclared, ()
// CHECK:STDOUT: %ForwardDeclared.decl.loc9 = class_decl @ForwardDeclared, ()
// CHECK:STDOUT: %Empty.ref: type = name_ref Empty, constants.%Empty [template = constants.%Empty]
// CHECK:STDOUT: %a_ref.var: ref Empty = var a_ref
// CHECK:STDOUT: %a_ref: ref Empty = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %.loc13_21.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc13_21.2: init Empty = class_init (), %a_ref.var [template = constants.%.4]
// CHECK:STDOUT: %.loc13_21.3: init Empty = converted %.loc13_21.1, %.loc13_21.2 [template = constants.%.4]
// CHECK:STDOUT: assign %a_ref.var, %.loc13_21.3
// CHECK:STDOUT: %ForwardDeclared.ref.loc14: type = name_ref ForwardDeclared, constants.%ForwardDeclared [template = constants.%ForwardDeclared]
// CHECK:STDOUT: %b_ref.var: ref ForwardDeclared = var b_ref
// CHECK:STDOUT: %b_ref: ref ForwardDeclared = bind_name b_ref, %b_ref.var
// CHECK:STDOUT: %.loc14_31.1: {} = struct_literal ()
// CHECK:STDOUT: %.loc14_31.2: init ForwardDeclared = class_init (), %b_ref.var [template = constants.%.5]
// CHECK:STDOUT: %.loc14_31.3: init ForwardDeclared = converted %.loc14_31.1, %.loc14_31.2 [template = constants.%.5]
// CHECK:STDOUT: assign %b_ref.var, %.loc14_31.3
// CHECK:STDOUT: %ForwardDeclared.ref.loc15: type = name_ref ForwardDeclared, constants.%ForwardDeclared [template = constants.%ForwardDeclared]
// CHECK:STDOUT: %.loc15_27: type = ptr_type ForwardDeclared [template = constants.%.6]
// CHECK:STDOUT: %c_ref.var: ref ForwardDeclared* = var c_ref
// CHECK:STDOUT: %c_ref: ref ForwardDeclared* = bind_name c_ref, %c_ref.var
// CHECK:STDOUT: %b_ref.ref: ref ForwardDeclared = name_ref b_ref, %b_ref
// CHECK:STDOUT: %.loc15_31: ForwardDeclared* = addr_of %b_ref.ref
// CHECK:STDOUT: assign %c_ref.var, %.loc15_31
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: class @Empty {
@@ -71,23 +108,48 @@ fn Run() {
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.Empty = %import_ref.1, .ForwardDeclared = %import_ref.2, .Run = %Run} [template]
// CHECK:STDOUT: %import_ref.1: invalid = import_ref ir1, inst+1, used
// CHECK:STDOUT: %import_ref.2: invalid = import_ref ir1, inst+4, used
// CHECK:STDOUT: package: <namespace> = namespace {.Empty = %import_ref.1, .ForwardDeclared = %import_ref.2, .a_ref = %import_ref.3, .b_ref = %import_ref.4, .c_ref = %import_ref.5, .Run = %Run, .a = %a, .b = %b, .c = %c, .d = %d} [template]
// CHECK:STDOUT: %import_ref.1: <error> = import_ref ir1, inst+1, used
// CHECK:STDOUT: %import_ref.2: <error> = import_ref ir1, inst+4, used
// CHECK:STDOUT: %import_ref.3: ref <error> = import_ref ir1, inst+12, used
// CHECK:STDOUT: %import_ref.4: ref <error> = import_ref ir1, inst+20, used
// CHECK:STDOUT: %import_ref.5: ref <error> = import_ref ir1, inst+30, used
// CHECK:STDOUT: %Run: <function> = fn_decl @Run [template]
// CHECK:STDOUT: %Empty.ref: <error> = name_ref Empty, %import_ref.1
// CHECK:STDOUT: %a.var: ref <error> = var a
// CHECK:STDOUT: %a: ref <error> = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref.3
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: %ForwardDeclared.ref.loc13: <error> = name_ref ForwardDeclared, %import_ref.2
// CHECK:STDOUT: %b.var: ref <error> = var b
// CHECK:STDOUT: %b: ref <error> = bind_name b, %b.var
// CHECK:STDOUT: %b_ref.ref: ref <error> = name_ref b_ref, %import_ref.4
// CHECK:STDOUT: assign %b.var, <error>
// CHECK:STDOUT: %ForwardDeclared.ref.loc14: <error> = name_ref ForwardDeclared, %import_ref.2
// CHECK:STDOUT: %.loc14: type = ptr_type <error> [template = <error>]
// CHECK:STDOUT: %c.var: ref <error> = var c
// CHECK:STDOUT: %c: ref <error> = bind_name c, %c.var
// CHECK:STDOUT: %c_ref.ref: ref <error> = name_ref c_ref, %import_ref.5
// CHECK:STDOUT: assign %c.var, <error>
// CHECK:STDOUT: %ForwardDeclared.ref.loc18: <error> = name_ref ForwardDeclared, %import_ref.2
// CHECK:STDOUT: %.loc18: <error> = tuple_literal (%ForwardDeclared.ref.loc18)
// CHECK:STDOUT: %d.var: ref <error> = var d
// CHECK:STDOUT: %d: ref <error> = bind_name d, %d.var
// CHECK:STDOUT: %d_ref.ref: <error> = name_ref d_ref, <error> [template = <error>]
// CHECK:STDOUT: assign %d.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @Run() {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %Empty.ref: invalid = name_ref Empty, file.%import_ref.1
// CHECK:STDOUT: %Empty.ref: <error> = name_ref Empty, file.%import_ref.1
// CHECK:STDOUT: %x.var: ref <error> = var x
// CHECK:STDOUT: %x: ref <error> = bind_name x, %x.var
// CHECK:STDOUT: %.loc10: {} = struct_literal ()
// CHECK:STDOUT: %.loc7: {} = struct_literal ()
// CHECK:STDOUT: assign %x.var, <error>
// CHECK:STDOUT: %ForwardDeclared.ref: invalid = name_ref ForwardDeclared, file.%import_ref.2
// CHECK:STDOUT: %ForwardDeclared.ref: <error> = name_ref ForwardDeclared, file.%import_ref.2
// CHECK:STDOUT: %y.var: ref <error> = var y
// CHECK:STDOUT: %y: ref <error> = bind_name y, %y.var
// CHECK:STDOUT: %.loc14: {} = struct_literal ()
// CHECK:STDOUT: %.loc8: {} = struct_literal ()
// CHECK:STDOUT: assign %y.var, <error>
// CHECK:STDOUT: %y.ref: ref <error> = name_ref y, %y
// CHECK:STDOUT: return
+42
View File
@@ -0,0 +1,42 @@
// 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
fn A(p: const i32**) -> const i32** {
return p;
}
fn B(p: const (i32*)) -> const (i32*) {
return p;
}
// CHECK:STDOUT: --- basic.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = const_type i32 [template]
// CHECK:STDOUT: %.2: type = ptr_type const i32 [template]
// CHECK:STDOUT: %.3: type = ptr_type const i32* [template]
// CHECK:STDOUT: %.4: type = ptr_type i32 [template]
// CHECK:STDOUT: %.5: type = const_type i32* [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.A = %A, .B = %B} [template]
// CHECK:STDOUT: %A: <function> = fn_decl @A [template]
// CHECK:STDOUT: %B: <function> = fn_decl @B [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @A(%p: const i32**) -> const i32** {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %p.ref: const i32** = name_ref p, %p
// CHECK:STDOUT: return %p.ref
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @B(%p: const (i32*)) -> const (i32*) {
// CHECK:STDOUT: !entry:
// CHECK:STDOUT: %p.ref: const (i32*) = name_ref p, %p
// CHECK:STDOUT: return %p.ref
// CHECK:STDOUT: }
// CHECK:STDOUT:
-60
View File
@@ -1,60 +0,0 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for non-builtin type`.
// --- implicit.carbon
package Implicit api;
fn F() -> const i32;
var a_ref: const i32 = F();
// --- implicit.impl.carbon
package Implicit impl;
var a: const i32 = a_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = const_type i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.F = %F, .a_ref = %a_ref} [template]
// CHECK:STDOUT: %F: <function> = fn_decl @F [template]
// CHECK:STDOUT: %.loc6_12: type = const_type i32 [template = constants.%.1]
// CHECK:STDOUT: %a_ref.var: ref const i32 = var a_ref
// CHECK:STDOUT: %a_ref: ref const i32 = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %F.ref: <function> = name_ref F, %F [template = %F]
// CHECK:STDOUT: %.loc6_25: init const i32 = call %F.ref()
// CHECK:STDOUT: assign %a_ref.var, %.loc6_25
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() -> const i32;
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = const_type i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.F = %import_ref.1, .a_ref = %import_ref.2, .a = %a} [template]
// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+4, unused
// CHECK:STDOUT: %import_ref.2: ref <error> = import_ref ir1, inst+7, used
// CHECK:STDOUT: %.loc4: type = const_type i32 [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref const i32 = var a
// CHECK:STDOUT: %a: ref const i32 = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref.2
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+79
View File
@@ -0,0 +1,79 @@
// 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
// --- implicit.carbon
package Implicit api;
fn F() -> const i32;
var a_ref: const i32 = F();
var a_ptr_ref: const i32* = &a_ref;
// --- implicit.impl.carbon
package Implicit impl;
// Take a reference to avoid unsupported copy logic. This still validates the
// `const` is handled.
var a: const i32* = &a_ref;
var a_ptr: const i32* = a_ptr_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = const_type i32 [template]
// CHECK:STDOUT: %.2: type = ptr_type const i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.F = %F, .a_ref = %a_ref, .a_ptr_ref = %a_ptr_ref} [template]
// CHECK:STDOUT: %F: <function> = fn_decl @F [template]
// CHECK:STDOUT: %.loc6_12: type = const_type i32 [template = constants.%.1]
// CHECK:STDOUT: %a_ref.var: ref const i32 = var a_ref
// CHECK:STDOUT: %a_ref: ref const i32 = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %F.ref: <function> = name_ref F, %F [template = %F]
// CHECK:STDOUT: %.loc6_25: init const i32 = call %F.ref()
// CHECK:STDOUT: assign %a_ref.var, %.loc6_25
// CHECK:STDOUT: %.loc7_16: type = const_type i32 [template = constants.%.1]
// CHECK:STDOUT: %.loc7_25: type = ptr_type const i32 [template = constants.%.2]
// CHECK:STDOUT: %a_ptr_ref.var: ref const i32* = var a_ptr_ref
// CHECK:STDOUT: %a_ptr_ref: ref const i32* = bind_name a_ptr_ref, %a_ptr_ref.var
// CHECK:STDOUT: %a_ref.ref: ref const i32 = name_ref a_ref, %a_ref
// CHECK:STDOUT: %.loc7_29: const i32* = addr_of %a_ref.ref
// CHECK:STDOUT: assign %a_ptr_ref.var, %.loc7_29
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: fn @F() -> const i32;
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = const_type i32 [template]
// CHECK:STDOUT: %.2: type = ptr_type const i32 [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.F = %import_ref.1, .a_ref = %import_ref.2, .a_ptr_ref = %import_ref.3, .a = %a, .a_ptr = %a_ptr} [template]
// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+4, unused
// CHECK:STDOUT: %import_ref.2: ref const i32 = import_ref ir1, inst+7, used
// CHECK:STDOUT: %import_ref.3: ref const i32* = import_ref ir1, inst+15, used
// CHECK:STDOUT: %.loc6_8: type = const_type i32 [template = constants.%.1]
// CHECK:STDOUT: %.loc6_17: type = ptr_type const i32 [template = constants.%.2]
// CHECK:STDOUT: %a.var: ref const i32* = var a
// CHECK:STDOUT: %a: ref const i32* = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref const i32 = name_ref a_ref, %import_ref.2
// CHECK:STDOUT: %.loc6_21: const i32* = addr_of %a_ref.ref
// CHECK:STDOUT: assign %a.var, %.loc6_21
// CHECK:STDOUT: %.loc7_12: type = const_type i32 [template = constants.%.1]
// CHECK:STDOUT: %.loc7_21: type = ptr_type const i32 [template = constants.%.2]
// CHECK:STDOUT: %a_ptr.var: ref const i32* = var a_ptr
// CHECK:STDOUT: %a_ptr: ref const i32* = bind_name a_ptr, %a_ptr.var
// CHECK:STDOUT: %a_ptr_ref.ref: ref const i32* = name_ref a_ptr_ref, %import_ref.3
// CHECK:STDOUT: %.loc7_25: const i32* = bind_value %a_ptr_ref.ref
// CHECK:STDOUT: assign %a_ptr.var, %.loc7_25
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -0,0 +1,85 @@
// 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
// --- implicit.carbon
package Implicit api;
// CHECK:STDERR: implicit.carbon:[[@LINE+3]]:12: ERROR: Name `x` not found.
// CHECK:STDERR: var a_ref: x;
// CHECK:STDERR: ^
var a_ref: x;
// CHECK:STDERR: implicit.carbon:[[@LINE+3]]:18: ERROR: Name `x` not found.
// CHECK:STDERR: var b_ref: {.a = x};
// CHECK:STDERR: ^
var b_ref: {.a = x};
// CHECK:STDERR: implicit.carbon:[[@LINE+3]]:13: ERROR: Name `x` not found.
// CHECK:STDERR: var c_ref: (x,);
// CHECK:STDERR: ^
var c_ref: (x,);
// CHECK:STDERR: implicit.carbon:[[@LINE+3]]:12: ERROR: Name `x` not found.
// CHECK:STDERR: var d_ref: x*;
// CHECK:STDERR: ^
var d_ref: x*;
// --- implicit.impl.carbon
package Implicit impl;
// In each of these cases, name lookup should succeed, but they should all have
// an error type.
var a: i32 = a_ref;
var b: i32 = b_ref;
var c: i32 = c_ref;
var d: i32 = d_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %a_ref, .b_ref = %b_ref, .c_ref = %c_ref, .d_ref = %d_ref} [template]
// CHECK:STDOUT: %x.ref.loc7: <error> = name_ref x, <error> [template = <error>]
// CHECK:STDOUT: %a_ref.var: ref <error> = var a_ref
// CHECK:STDOUT: %a_ref: ref <error> = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %x.ref.loc11: <error> = name_ref x, <error> [template = <error>]
// CHECK:STDOUT: %.loc11: <error> = struct_literal (%x.ref.loc11)
// CHECK:STDOUT: %b_ref.var: ref <error> = var b_ref
// CHECK:STDOUT: %b_ref: ref <error> = bind_name b_ref, %b_ref.var
// CHECK:STDOUT: %x.ref.loc15: <error> = name_ref x, <error> [template = <error>]
// CHECK:STDOUT: %.loc15: <error> = tuple_literal (%x.ref.loc15)
// CHECK:STDOUT: %c_ref.var: ref <error> = var c_ref
// CHECK:STDOUT: %c_ref: ref <error> = bind_name c_ref, %c_ref.var
// CHECK:STDOUT: %x.ref.loc19: <error> = name_ref x, <error> [template = <error>]
// CHECK:STDOUT: %.loc19: type = ptr_type <error> [template = <error>]
// CHECK:STDOUT: %d_ref.var: ref <error> = var d_ref
// CHECK:STDOUT: %d_ref: ref <error> = bind_name d_ref, %d_ref.var
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %import_ref.1, .b_ref = %import_ref.2, .c_ref = %import_ref.3, .d_ref = %import_ref.4, .a = %a, .b = %b, .c = %c, .d = %d} [template]
// CHECK:STDOUT: %import_ref.1: ref <error> = import_ref ir1, inst+3, used
// CHECK:STDOUT: %import_ref.2: ref <error> = import_ref ir1, inst+8, used
// CHECK:STDOUT: %import_ref.3: ref <error> = import_ref ir1, inst+12, used
// CHECK:STDOUT: %import_ref.4: ref <error> = import_ref ir1, inst+16, used
// CHECK:STDOUT: %a.var: ref i32 = var a
// CHECK:STDOUT: %a: ref i32 = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref.1
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: %b.var: ref i32 = var b
// CHECK:STDOUT: %b: ref i32 = bind_name b, %b.var
// CHECK:STDOUT: %b_ref.ref: ref <error> = name_ref b_ref, %import_ref.2
// CHECK:STDOUT: assign %b.var, <error>
// CHECK:STDOUT: %c.var: ref i32 = var c
// CHECK:STDOUT: %c: ref i32 = bind_name c, %c.var
// CHECK:STDOUT: %c_ref.ref: ref <error> = name_ref c_ref, %import_ref.3
// CHECK:STDOUT: assign %c.var, <error>
// CHECK:STDOUT: %d.var: ref i32 = var d
// CHECK:STDOUT: %d: ref i32 = bind_name d, %d.var
// CHECK:STDOUT: %d_ref.ref: ref <error> = name_ref d_ref, %import_ref.4
// CHECK:STDOUT: assign %d.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
@@ -2,11 +2,7 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for non-builtin type`.
// --- implicit.carbon
@@ -51,11 +47,12 @@ var a: i32* = a_ref;
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_orig = %import_ref.1, .a_ref = %import_ref.2, .a = %a} [template]
// CHECK:STDOUT: %import_ref.1 = import_ref ir1, inst+2, unused
// CHECK:STDOUT: %import_ref.2: ref <error> = import_ref ir1, inst+9, used
// CHECK:STDOUT: %.loc4: type = ptr_type i32 [template = constants.%.1]
// CHECK:STDOUT: %import_ref.2: ref i32* = import_ref ir1, inst+9, used
// CHECK:STDOUT: %.loc4_11: type = ptr_type i32 [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref i32* = var a
// CHECK:STDOUT: %a: ref i32* = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref.2
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: %a_ref.ref: ref i32* = name_ref a_ref, %import_ref.2
// CHECK:STDOUT: %.loc4_15: i32* = bind_value %a_ref.ref
// CHECK:STDOUT: assign %a.var, %.loc4_15
// CHECK:STDOUT: }
// CHECK:STDOUT:
-58
View File
@@ -1,58 +0,0 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for non-builtin type`.
// --- implicit.carbon
package Implicit api;
var a_ref: {.a: i32} = {.a = 0};
// --- implicit.impl.carbon
package Implicit impl;
var a: {.a: i32} = a_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = struct_type {.a: i32} [template]
// CHECK:STDOUT: %.2: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.3: {.a: i32} = struct_value (%.2) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %a_ref} [template]
// CHECK:STDOUT: %.loc4_20: type = struct_type {.a: i32} [template = constants.%.1]
// CHECK:STDOUT: %a_ref.var: ref {.a: i32} = var a_ref
// CHECK:STDOUT: %a_ref: ref {.a: i32} = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %.loc4_30: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_31.1: {.a: i32} = struct_literal (%.loc4_30)
// CHECK:STDOUT: %.loc4_31.2: init {.a: i32} = struct_init (%.loc4_30) to %a_ref.var [template = constants.%.3]
// CHECK:STDOUT: %.loc4_31.3: init {.a: i32} = converted %.loc4_31.1, %.loc4_31.2 [template = constants.%.3]
// CHECK:STDOUT: assign %a_ref.var, %.loc4_31.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = struct_type {.a: i32} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %import_ref, .a = %a} [template]
// CHECK:STDOUT: %import_ref: ref <error> = import_ref ir1, inst+6, used
// CHECK:STDOUT: %.loc4: type = struct_type {.a: i32} [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref {.a: i32} = var a
// CHECK:STDOUT: %a: ref {.a: i32} = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+134
View File
@@ -0,0 +1,134 @@
// 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
// --- implicit.carbon
package Implicit api;
var a_ref: {.a: i32} = {.a = 0};
var b_ref: {.a: {.b: i32, .c: (i32,)}, .d: i32} =
{.a = {.b = 0, .c = (0,)}, .d = 0};
// --- implicit.impl.carbon
package Implicit impl;
var a: {.a: i32} = a_ref;
var b: {.a: {.b: i32, .c: (i32,)}, .d: i32} = b_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = struct_type {.a: i32} [template]
// CHECK:STDOUT: %.2: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.3: {.a: i32} = struct_value (%.2) [template]
// CHECK:STDOUT: %.4: type = tuple_type (type) [template]
// CHECK:STDOUT: %.5: type = tuple_type (i32) [template]
// CHECK:STDOUT: %.6: type = struct_type {.b: i32, .c: (i32,)} [template]
// CHECK:STDOUT: %.7: type = struct_type {.a: {.b: i32, .c: (i32,)}, .d: i32} [template]
// CHECK:STDOUT: %.8: type = ptr_type {.b: i32, .c: (i32,)} [template]
// CHECK:STDOUT: %.9: type = struct_type {.a: {.b: i32, .c: (i32,)}*, .d: i32} [template]
// CHECK:STDOUT: %.10: type = ptr_type {.a: {.b: i32, .c: (i32,)}*, .d: i32} [template]
// CHECK:STDOUT: %.11: (i32,) = tuple_value (%.2) [template]
// CHECK:STDOUT: %.12: {.b: i32, .c: (i32,)} = struct_value (%.2, %.11) [template]
// CHECK:STDOUT: %.13: {.a: {.b: i32, .c: (i32,)}, .d: i32} = struct_value (%.12, %.2) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %a_ref, .b_ref = %b_ref} [template]
// CHECK:STDOUT: %.loc4_20: type = struct_type {.a: i32} [template = constants.%.1]
// CHECK:STDOUT: %a_ref.var: ref {.a: i32} = var a_ref
// CHECK:STDOUT: %a_ref: ref {.a: i32} = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %.loc4_30: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc4_31.1: {.a: i32} = struct_literal (%.loc4_30)
// CHECK:STDOUT: %.loc4_31.2: init {.a: i32} = struct_init (%.loc4_30) to %a_ref.var [template = constants.%.3]
// CHECK:STDOUT: %.loc4_31.3: init {.a: i32} = converted %.loc4_31.1, %.loc4_31.2 [template = constants.%.3]
// CHECK:STDOUT: assign %a_ref.var, %.loc4_31.3
// CHECK:STDOUT: %.loc5_36.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc5_36.2: type = converted %.loc5_36.1, constants.%.5 [template = constants.%.5]
// CHECK:STDOUT: %.loc5_37: type = struct_type {.b: i32, .c: (i32,)} [template = constants.%.6]
// CHECK:STDOUT: %.loc5_47: type = struct_type {.a: {.b: i32, .c: (i32,)}, .d: i32} [template = constants.%.7]
// CHECK:STDOUT: %b_ref.var: ref {.a: {.b: i32, .c: (i32,)}, .d: i32} = var b_ref
// CHECK:STDOUT: %b_ref: ref {.a: {.b: i32, .c: (i32,)}, .d: i32} = bind_name b_ref, %b_ref.var
// CHECK:STDOUT: %.loc6_17: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc6_26: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc6_28.1: (i32,) = tuple_literal (%.loc6_26)
// CHECK:STDOUT: %.loc6_29.1: {.b: i32, .c: (i32,)} = struct_literal (%.loc6_17, %.loc6_28.1)
// CHECK:STDOUT: %.loc6_37: i32 = int_literal 0 [template = constants.%.2]
// CHECK:STDOUT: %.loc6_38.1: {.a: {.b: i32, .c: (i32,)}, .d: i32} = struct_literal (%.loc6_29.1, %.loc6_37)
// CHECK:STDOUT: %.loc6_38.2: ref {.b: i32, .c: (i32,)} = struct_access %b_ref.var, element0
// CHECK:STDOUT: %.loc6_29.2: ref i32 = struct_access %.loc6_38.2, element0
// CHECK:STDOUT: %.loc6_29.3: init i32 = initialize_from %.loc6_17 to %.loc6_29.2 [template = constants.%.2]
// CHECK:STDOUT: %.loc6_29.4: ref (i32,) = struct_access %.loc6_38.2, element1
// CHECK:STDOUT: %.loc6_28.2: init (i32,) = tuple_init (%.loc6_26) to %.loc6_29.4 [template = constants.%.11]
// CHECK:STDOUT: %.loc6_28.3: init (i32,) = converted %.loc6_28.1, %.loc6_28.2 [template = constants.%.11]
// CHECK:STDOUT: %.loc6_29.5: init (i32,) = initialize_from %.loc6_28.3 to %.loc6_29.4 [template = constants.%.11]
// CHECK:STDOUT: %.loc6_29.6: init {.b: i32, .c: (i32,)} = struct_init (%.loc6_29.3, %.loc6_29.5) to %.loc6_38.2 [template = constants.%.12]
// CHECK:STDOUT: %.loc6_29.7: init {.b: i32, .c: (i32,)} = converted %.loc6_29.1, %.loc6_29.6 [template = constants.%.12]
// CHECK:STDOUT: %.loc6_38.3: ref i32 = struct_access %b_ref.var, element1
// CHECK:STDOUT: %.loc6_38.4: init i32 = initialize_from %.loc6_37 to %.loc6_38.3 [template = constants.%.2]
// CHECK:STDOUT: %.loc6_38.5: init {.a: {.b: i32, .c: (i32,)}, .d: i32} = struct_init (%.loc6_29.7, %.loc6_38.4) to %b_ref.var [template = constants.%.13]
// CHECK:STDOUT: %.loc6_38.6: init {.a: {.b: i32, .c: (i32,)}, .d: i32} = converted %.loc6_38.1, %.loc6_38.5 [template = constants.%.13]
// CHECK:STDOUT: assign %b_ref.var, %.loc6_38.6
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = struct_type {.a: i32} [template]
// CHECK:STDOUT: %.2: type = tuple_type (type) [template]
// CHECK:STDOUT: %.3: type = tuple_type (i32) [template]
// CHECK:STDOUT: %.4: type = struct_type {.b: i32, .c: (i32,)} [template]
// CHECK:STDOUT: %.5: type = struct_type {.a: {.b: i32, .c: (i32,)}, .d: i32} [template]
// CHECK:STDOUT: %.6: type = ptr_type {.b: i32, .c: (i32,)} [template]
// CHECK:STDOUT: %.7: type = struct_type {.a: {.b: i32, .c: (i32,)}*, .d: i32} [template]
// CHECK:STDOUT: %.8: type = ptr_type {.a: {.b: i32, .c: (i32,)}*, .d: i32} [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %import_ref.1, .b_ref = %import_ref.2, .a = %a, .b = %b} [template]
// CHECK:STDOUT: %import_ref.1: ref {.a: i32} = import_ref ir1, inst+6, used
// CHECK:STDOUT: %import_ref.2: ref {.a: {.b: i32, .c: (i32,)}, .d: i32} = import_ref ir1, inst+37, used
// CHECK:STDOUT: %.loc4_16: type = struct_type {.a: i32} [template = constants.%.1]
// CHECK:STDOUT: %a.var: ref {.a: i32} = var a
// CHECK:STDOUT: %a: ref {.a: i32} = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref {.a: i32} = name_ref a_ref, %import_ref.1
// CHECK:STDOUT: %.loc4_20.1: ref i32 = struct_access %a_ref.ref, element0
// CHECK:STDOUT: %.loc4_20.2: i32 = bind_value %.loc4_20.1
// CHECK:STDOUT: %.loc4_20.3: init {.a: i32} = struct_init (%.loc4_20.2) to %a.var
// CHECK:STDOUT: %.loc4_20.4: init {.a: i32} = converted %a_ref.ref, %.loc4_20.3
// CHECK:STDOUT: assign %a.var, %.loc4_20.4
// CHECK:STDOUT: %.loc5_32.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc5_32.2: type = converted %.loc5_32.1, constants.%.3 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_33: type = struct_type {.b: i32, .c: (i32,)} [template = constants.%.4]
// CHECK:STDOUT: %.loc5_43: type = struct_type {.a: {.b: i32, .c: (i32,)}, .d: i32} [template = constants.%.5]
// CHECK:STDOUT: %b.var: ref {.a: {.b: i32, .c: (i32,)}, .d: i32} = var b
// CHECK:STDOUT: %b: ref {.a: {.b: i32, .c: (i32,)}, .d: i32} = bind_name b, %b.var
// CHECK:STDOUT: %b_ref.ref: ref {.a: {.b: i32, .c: (i32,)}, .d: i32} = name_ref b_ref, %import_ref.2
// CHECK:STDOUT: %.loc5_47.1: ref {.b: i32, .c: (i32,)} = struct_access %b_ref.ref, element0
// CHECK:STDOUT: %.loc5_47.2: ref i32 = struct_access %.loc5_47.1, element0
// CHECK:STDOUT: %.loc5_47.3: i32 = bind_value %.loc5_47.2
// CHECK:STDOUT: %.loc5_47.4: ref {.b: i32, .c: (i32,)} = struct_access %b.var, element0
// CHECK:STDOUT: %.loc5_47.5: ref i32 = struct_access %.loc5_47.4, element0
// CHECK:STDOUT: %.loc5_47.6: init i32 = initialize_from %.loc5_47.3 to %.loc5_47.5
// CHECK:STDOUT: %.loc5_47.7: ref (i32,) = struct_access %.loc5_47.1, element1
// CHECK:STDOUT: %.loc5_47.8: ref i32 = tuple_access %.loc5_47.7, element0
// CHECK:STDOUT: %.loc5_47.9: i32 = bind_value %.loc5_47.8
// CHECK:STDOUT: %.loc5_47.10: ref (i32,) = struct_access %.loc5_47.4, element1
// CHECK:STDOUT: %.loc5_47.11: init (i32,) = tuple_init (%.loc5_47.9) to %.loc5_47.10
// CHECK:STDOUT: %.loc5_47.12: init (i32,) = converted %.loc5_47.7, %.loc5_47.11
// CHECK:STDOUT: %.loc5_47.13: init (i32,) = initialize_from %.loc5_47.12 to %.loc5_47.10
// CHECK:STDOUT: %.loc5_47.14: init {.b: i32, .c: (i32,)} = struct_init (%.loc5_47.6, %.loc5_47.13) to %.loc5_47.4
// CHECK:STDOUT: %.loc5_47.15: init {.b: i32, .c: (i32,)} = converted %.loc5_47.1, %.loc5_47.14
// CHECK:STDOUT: %.loc5_47.16: ref i32 = struct_access %b_ref.ref, element1
// CHECK:STDOUT: %.loc5_47.17: i32 = bind_value %.loc5_47.16
// CHECK:STDOUT: %.loc5_47.18: ref i32 = struct_access %b.var, element1
// CHECK:STDOUT: %.loc5_47.19: init i32 = initialize_from %.loc5_47.17 to %.loc5_47.18
// CHECK:STDOUT: %.loc5_47.20: init {.a: {.b: i32, .c: (i32,)}, .d: i32} = struct_init (%.loc5_47.15, %.loc5_47.19) to %b.var
// CHECK:STDOUT: %.loc5_47.21: init {.a: {.b: i32, .c: (i32,)}, .d: i32} = converted %b_ref.ref, %.loc5_47.20
// CHECK:STDOUT: assign %b.var, %.loc5_47.21
// CHECK:STDOUT: }
// CHECK:STDOUT:
-62
View File
@@ -1,62 +0,0 @@
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// CHECK:STDERR: implicit.impl.carbon: ERROR: Semantics TODO: `TODO: ResolveIfImportRefUnused for non-builtin type`.
// --- implicit.carbon
package Implicit api;
var a_ref: (i32,) = (0,);
// --- implicit.impl.carbon
package Implicit impl;
var a: (i32,) = a_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type (type) [template]
// CHECK:STDOUT: %.2: type = tuple_type (i32) [template]
// CHECK:STDOUT: %.3: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.4: (i32,) = tuple_value (%.3) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %a_ref} [template]
// CHECK:STDOUT: %.loc4_17.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc4_17.2: type = converted %.loc4_17.1, constants.%.2 [template = constants.%.2]
// CHECK:STDOUT: %a_ref.var: ref (i32,) = var a_ref
// CHECK:STDOUT: %a_ref: ref (i32,) = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %.loc4_22: i32 = int_literal 0 [template = constants.%.3]
// CHECK:STDOUT: %.loc4_24.1: (i32,) = tuple_literal (%.loc4_22)
// CHECK:STDOUT: %.loc4_24.2: init (i32,) = tuple_init (%.loc4_22) to %a_ref.var [template = constants.%.4]
// CHECK:STDOUT: %.loc4_24.3: init (i32,) = converted %.loc4_24.1, %.loc4_24.2 [template = constants.%.4]
// CHECK:STDOUT: assign %a_ref.var, %.loc4_24.3
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type (type) [template]
// CHECK:STDOUT: %.2: type = tuple_type (i32) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %import_ref, .a = %a} [template]
// CHECK:STDOUT: %import_ref: ref <error> = import_ref ir1, inst+6, used
// CHECK:STDOUT: %.loc4_13.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc4_13.2: type = converted %.loc4_13.1, constants.%.2 [template = constants.%.2]
// CHECK:STDOUT: %a.var: ref (i32,) = var a
// CHECK:STDOUT: %a: ref (i32,) = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref <error> = name_ref a_ref, %import_ref
// CHECK:STDOUT: assign %a.var, <error>
// CHECK:STDOUT: }
// CHECK:STDOUT:
+169
View File
@@ -0,0 +1,169 @@
// 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
// --- implicit.carbon
package Implicit api;
var a_ref: (i32,) = (0,);
var b_ref: (((i32,), i32), (i32, i32)) = (((0,), 1), (2, 3));
// --- implicit.impl.carbon
package Implicit impl;
var a: (i32,) = a_ref;
var b: (((i32,), i32), (i32, i32)) = b_ref;
// CHECK:STDOUT: --- implicit.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type (type) [template]
// CHECK:STDOUT: %.2: type = tuple_type (i32) [template]
// CHECK:STDOUT: %.3: i32 = int_literal 0 [template]
// CHECK:STDOUT: %.4: (i32,) = tuple_value (%.3) [template]
// CHECK:STDOUT: %.5: type = tuple_type ((type,), type) [template]
// CHECK:STDOUT: %.6: type = tuple_type (type, type) [template]
// CHECK:STDOUT: %.7: type = tuple_type (((type,), type), (type, type)) [template]
// CHECK:STDOUT: %.8: type = tuple_type ((i32,), i32) [template]
// CHECK:STDOUT: %.9: type = tuple_type (i32, i32) [template]
// CHECK:STDOUT: %.10: type = tuple_type (((i32,), i32), (i32, i32)) [template]
// CHECK:STDOUT: %.11: type = ptr_type (i32, i32) [template]
// CHECK:STDOUT: %.12: type = ptr_type ((i32,), i32) [template]
// CHECK:STDOUT: %.13: type = tuple_type (((i32,), i32)*, (i32, i32)*) [template]
// CHECK:STDOUT: %.14: type = ptr_type (((i32,), i32)*, (i32, i32)*) [template]
// CHECK:STDOUT: %.15: i32 = int_literal 1 [template]
// CHECK:STDOUT: %.16: i32 = int_literal 2 [template]
// CHECK:STDOUT: %.17: i32 = int_literal 3 [template]
// CHECK:STDOUT: %.18: ((i32,), i32) = tuple_value (%.4, %.15) [template]
// CHECK:STDOUT: %.19: (i32, i32) = tuple_value (%.16, %.17) [template]
// CHECK:STDOUT: %.20: (((i32,), i32), (i32, i32)) = tuple_value (%.18, %.19) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %a_ref, .b_ref = %b_ref} [template]
// CHECK:STDOUT: %.loc4_17.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc4_17.2: type = converted %.loc4_17.1, constants.%.2 [template = constants.%.2]
// CHECK:STDOUT: %a_ref.var: ref (i32,) = var a_ref
// CHECK:STDOUT: %a_ref: ref (i32,) = bind_name a_ref, %a_ref.var
// CHECK:STDOUT: %.loc4_22: i32 = int_literal 0 [template = constants.%.3]
// CHECK:STDOUT: %.loc4_24.1: (i32,) = tuple_literal (%.loc4_22)
// CHECK:STDOUT: %.loc4_24.2: init (i32,) = tuple_init (%.loc4_22) to %a_ref.var [template = constants.%.4]
// CHECK:STDOUT: %.loc4_24.3: init (i32,) = converted %.loc4_24.1, %.loc4_24.2 [template = constants.%.4]
// CHECK:STDOUT: assign %a_ref.var, %.loc4_24.3
// CHECK:STDOUT: %.loc5_19.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc5_25.1: ((type,), type) = tuple_literal (%.loc5_19.1, i32)
// CHECK:STDOUT: %.loc5_37.1: (type, type) = tuple_literal (i32, i32)
// CHECK:STDOUT: %.loc5_38.1: (((type,), type), (type, type)) = tuple_literal (%.loc5_25.1, %.loc5_37.1)
// CHECK:STDOUT: %.loc5_19.2: type = converted %.loc5_19.1, constants.%.2 [template = constants.%.2]
// CHECK:STDOUT: %.loc5_25.2: type = converted %.loc5_25.1, constants.%.8 [template = constants.%.8]
// CHECK:STDOUT: %.loc5_37.2: type = converted %.loc5_37.1, constants.%.9 [template = constants.%.9]
// CHECK:STDOUT: %.loc5_38.2: type = converted %.loc5_38.1, constants.%.10 [template = constants.%.10]
// CHECK:STDOUT: %b_ref.var: ref (((i32,), i32), (i32, i32)) = var b_ref
// CHECK:STDOUT: %b_ref: ref (((i32,), i32), (i32, i32)) = bind_name b_ref, %b_ref.var
// CHECK:STDOUT: %.loc5_45: i32 = int_literal 0 [template = constants.%.3]
// CHECK:STDOUT: %.loc5_47.1: (i32,) = tuple_literal (%.loc5_45)
// CHECK:STDOUT: %.loc5_50: i32 = int_literal 1 [template = constants.%.15]
// CHECK:STDOUT: %.loc5_51.1: ((i32,), i32) = tuple_literal (%.loc5_47.1, %.loc5_50)
// CHECK:STDOUT: %.loc5_55: i32 = int_literal 2 [template = constants.%.16]
// CHECK:STDOUT: %.loc5_58: i32 = int_literal 3 [template = constants.%.17]
// CHECK:STDOUT: %.loc5_59.1: (i32, i32) = tuple_literal (%.loc5_55, %.loc5_58)
// CHECK:STDOUT: %.loc5_60.1: (((i32,), i32), (i32, i32)) = tuple_literal (%.loc5_51.1, %.loc5_59.1)
// CHECK:STDOUT: %.loc5_60.2: ref ((i32,), i32) = tuple_access %b_ref.var, element0
// CHECK:STDOUT: %.loc5_51.2: ref (i32,) = tuple_access %.loc5_60.2, element0
// CHECK:STDOUT: %.loc5_47.2: init (i32,) = tuple_init (%.loc5_45) to %.loc5_51.2 [template = constants.%.4]
// CHECK:STDOUT: %.loc5_47.3: init (i32,) = converted %.loc5_47.1, %.loc5_47.2 [template = constants.%.4]
// CHECK:STDOUT: %.loc5_51.3: init (i32,) = initialize_from %.loc5_47.3 to %.loc5_51.2 [template = constants.%.4]
// CHECK:STDOUT: %.loc5_51.4: ref i32 = tuple_access %.loc5_60.2, element1
// CHECK:STDOUT: %.loc5_51.5: init i32 = initialize_from %.loc5_50 to %.loc5_51.4 [template = constants.%.15]
// CHECK:STDOUT: %.loc5_51.6: init ((i32,), i32) = tuple_init (%.loc5_51.3, %.loc5_51.5) to %.loc5_60.2 [template = constants.%.18]
// CHECK:STDOUT: %.loc5_51.7: init ((i32,), i32) = converted %.loc5_51.1, %.loc5_51.6 [template = constants.%.18]
// CHECK:STDOUT: %.loc5_60.3: ref (i32, i32) = tuple_access %b_ref.var, element1
// CHECK:STDOUT: %.loc5_59.2: ref i32 = tuple_access %.loc5_60.3, element0
// CHECK:STDOUT: %.loc5_59.3: init i32 = initialize_from %.loc5_55 to %.loc5_59.2 [template = constants.%.16]
// CHECK:STDOUT: %.loc5_59.4: ref i32 = tuple_access %.loc5_60.3, element1
// CHECK:STDOUT: %.loc5_59.5: init i32 = initialize_from %.loc5_58 to %.loc5_59.4 [template = constants.%.17]
// CHECK:STDOUT: %.loc5_59.6: init (i32, i32) = tuple_init (%.loc5_59.3, %.loc5_59.5) to %.loc5_60.3 [template = constants.%.19]
// CHECK:STDOUT: %.loc5_59.7: init (i32, i32) = converted %.loc5_59.1, %.loc5_59.6 [template = constants.%.19]
// CHECK:STDOUT: %.loc5_60.4: init (((i32,), i32), (i32, i32)) = tuple_init (%.loc5_51.7, %.loc5_59.7) to %b_ref.var [template = constants.%.20]
// CHECK:STDOUT: %.loc5_60.5: init (((i32,), i32), (i32, i32)) = converted %.loc5_60.1, %.loc5_60.4 [template = constants.%.20]
// CHECK:STDOUT: assign %b_ref.var, %.loc5_60.5
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: --- implicit.impl.carbon
// CHECK:STDOUT:
// CHECK:STDOUT: constants {
// CHECK:STDOUT: %.1: type = tuple_type (type) [template]
// CHECK:STDOUT: %.2: type = tuple_type (i32) [template]
// CHECK:STDOUT: %.3: type = tuple_type ((type,), type) [template]
// CHECK:STDOUT: %.4: type = tuple_type (type, type) [template]
// CHECK:STDOUT: %.5: type = tuple_type (((type,), type), (type, type)) [template]
// CHECK:STDOUT: %.6: type = tuple_type ((i32,), i32) [template]
// CHECK:STDOUT: %.7: type = tuple_type (i32, i32) [template]
// CHECK:STDOUT: %.8: type = tuple_type (((i32,), i32), (i32, i32)) [template]
// CHECK:STDOUT: %.9: type = ptr_type (i32, i32) [template]
// CHECK:STDOUT: %.10: type = ptr_type ((i32,), i32) [template]
// CHECK:STDOUT: %.11: type = tuple_type (((i32,), i32)*, (i32, i32)*) [template]
// CHECK:STDOUT: %.12: type = ptr_type (((i32,), i32)*, (i32, i32)*) [template]
// CHECK:STDOUT: }
// CHECK:STDOUT:
// CHECK:STDOUT: file {
// CHECK:STDOUT: package: <namespace> = namespace {.a_ref = %import_ref.1, .b_ref = %import_ref.2, .a = %a, .b = %b} [template]
// CHECK:STDOUT: %import_ref.1: ref (i32,) = import_ref ir1, inst+6, used
// CHECK:STDOUT: %import_ref.2: ref (((i32,), i32), (i32, i32)) = import_ref ir1, inst+34, used
// CHECK:STDOUT: %.loc4_13.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc4_13.2: type = converted %.loc4_13.1, constants.%.2 [template = constants.%.2]
// CHECK:STDOUT: %a.var: ref (i32,) = var a
// CHECK:STDOUT: %a: ref (i32,) = bind_name a, %a.var
// CHECK:STDOUT: %a_ref.ref: ref (i32,) = name_ref a_ref, %import_ref.1
// CHECK:STDOUT: %.loc4_17.1: ref i32 = tuple_access %a_ref.ref, element0
// CHECK:STDOUT: %.loc4_17.2: i32 = bind_value %.loc4_17.1
// CHECK:STDOUT: %.loc4_17.3: init (i32,) = tuple_init (%.loc4_17.2) to %a.var
// CHECK:STDOUT: %.loc4_17.4: init (i32,) = converted %a_ref.ref, %.loc4_17.3
// CHECK:STDOUT: assign %a.var, %.loc4_17.4
// CHECK:STDOUT: %.loc5_15.1: (type,) = tuple_literal (i32)
// CHECK:STDOUT: %.loc5_21.1: ((type,), type) = tuple_literal (%.loc5_15.1, i32)
// CHECK:STDOUT: %.loc5_33.1: (type, type) = tuple_literal (i32, i32)
// CHECK:STDOUT: %.loc5_34.1: (((type,), type), (type, type)) = tuple_literal (%.loc5_21.1, %.loc5_33.1)
// CHECK:STDOUT: %.loc5_15.2: type = converted %.loc5_15.1, constants.%.2 [template = constants.%.2]
// CHECK:STDOUT: %.loc5_21.2: type = converted %.loc5_21.1, constants.%.6 [template = constants.%.6]
// CHECK:STDOUT: %.loc5_33.2: type = converted %.loc5_33.1, constants.%.7 [template = constants.%.7]
// CHECK:STDOUT: %.loc5_34.2: type = converted %.loc5_34.1, constants.%.8 [template = constants.%.8]
// CHECK:STDOUT: %b.var: ref (((i32,), i32), (i32, i32)) = var b
// CHECK:STDOUT: %b: ref (((i32,), i32), (i32, i32)) = bind_name b, %b.var
// CHECK:STDOUT: %b_ref.ref: ref (((i32,), i32), (i32, i32)) = name_ref b_ref, %import_ref.2
// CHECK:STDOUT: %.loc5_38.1: ref ((i32,), i32) = tuple_access %b_ref.ref, element0
// CHECK:STDOUT: %.loc5_38.2: ref (i32,) = tuple_access %.loc5_38.1, element0
// CHECK:STDOUT: %.loc5_38.3: ref i32 = tuple_access %.loc5_38.2, element0
// CHECK:STDOUT: %.loc5_38.4: i32 = bind_value %.loc5_38.3
// CHECK:STDOUT: %.loc5_38.5: ref ((i32,), i32) = tuple_access %b.var, element0
// CHECK:STDOUT: %.loc5_38.6: ref (i32,) = tuple_access %.loc5_38.5, element0
// CHECK:STDOUT: %.loc5_38.7: init (i32,) = tuple_init (%.loc5_38.4) to %.loc5_38.6
// CHECK:STDOUT: %.loc5_38.8: init (i32,) = converted %.loc5_38.2, %.loc5_38.7
// CHECK:STDOUT: %.loc5_38.9: init (i32,) = initialize_from %.loc5_38.8 to %.loc5_38.6
// CHECK:STDOUT: %.loc5_38.10: ref i32 = tuple_access %.loc5_38.1, element1
// CHECK:STDOUT: %.loc5_38.11: i32 = bind_value %.loc5_38.10
// CHECK:STDOUT: %.loc5_38.12: ref i32 = tuple_access %.loc5_38.5, element1
// CHECK:STDOUT: %.loc5_38.13: init i32 = initialize_from %.loc5_38.11 to %.loc5_38.12
// CHECK:STDOUT: %.loc5_38.14: init ((i32,), i32) = tuple_init (%.loc5_38.9, %.loc5_38.13) to %.loc5_38.5
// CHECK:STDOUT: %.loc5_38.15: init ((i32,), i32) = converted %.loc5_38.1, %.loc5_38.14
// CHECK:STDOUT: %.loc5_38.16: ref (i32, i32) = tuple_access %b_ref.ref, element1
// CHECK:STDOUT: %.loc5_38.17: ref i32 = tuple_access %.loc5_38.16, element0
// CHECK:STDOUT: %.loc5_38.18: i32 = bind_value %.loc5_38.17
// CHECK:STDOUT: %.loc5_38.19: ref (i32, i32) = tuple_access %b.var, element1
// CHECK:STDOUT: %.loc5_38.20: ref i32 = tuple_access %.loc5_38.19, element0
// CHECK:STDOUT: %.loc5_38.21: init i32 = initialize_from %.loc5_38.18 to %.loc5_38.20
// CHECK:STDOUT: %.loc5_38.22: ref i32 = tuple_access %.loc5_38.16, element1
// CHECK:STDOUT: %.loc5_38.23: i32 = bind_value %.loc5_38.22
// CHECK:STDOUT: %.loc5_38.24: ref i32 = tuple_access %.loc5_38.19, element1
// CHECK:STDOUT: %.loc5_38.25: init i32 = initialize_from %.loc5_38.23 to %.loc5_38.24
// CHECK:STDOUT: %.loc5_38.26: init (i32, i32) = tuple_init (%.loc5_38.21, %.loc5_38.25) to %.loc5_38.19
// CHECK:STDOUT: %.loc5_38.27: init (i32, i32) = converted %.loc5_38.16, %.loc5_38.26
// CHECK:STDOUT: %.loc5_38.28: init (((i32,), i32), (i32, i32)) = tuple_init (%.loc5_38.15, %.loc5_38.27) to %b.var
// CHECK:STDOUT: %.loc5_38.29: init (((i32,), i32), (i32, i32)) = converted %b_ref.ref, %.loc5_38.28
// CHECK:STDOUT: assign %b.var, %.loc5_38.29
// CHECK:STDOUT: }
// CHECK:STDOUT:
-3
View File
@@ -2,9 +2,6 @@
// Exceptions. See /LICENSE for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
// When there are no more cases that can hit a TODO, remove this test. Until
// then, update it whenever its target is implemented.
//
// AUTOUPDATE
// --- implicit.carbon