mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 19:10:14 +01:00
Drop fn destroy support (#6136)
`fn destroy` is being removed per decision on #6124. It seems like the relevant decision will result in no more keyword-based function names, so this is removing all related support.
This commit is contained in:
@@ -7,8 +7,8 @@ package Core library "prelude/destroy";
|
||||
import library "prelude/types/bool";
|
||||
import library "prelude/types/int_literal";
|
||||
|
||||
// Object destruction, including running `fn destroy()`. Note this is distinct
|
||||
// from memory deallocation.
|
||||
// Destroys objects. Note this is distinct from memory deallocation.
|
||||
// TODO: Switch to `Destructor`+`Destroy` model.
|
||||
interface Destroy {
|
||||
fn Op[addr self: Self*]();
|
||||
}
|
||||
|
||||
@@ -64,9 +64,7 @@ auto HandleParseNode(Context& context, Parse::ReturnTypeId node_id) -> bool {
|
||||
// not on the pattern stacks yet. They are only needed in that case if we have
|
||||
// a return type, which we now know that we do.
|
||||
if (context.node_stack().PeekNodeKind() ==
|
||||
Parse::NodeKind::IdentifierNameNotBeforeParams ||
|
||||
context.node_stack().PeekNodeKind() ==
|
||||
Parse::NodeKind::KeywordNameNotBeforeParams) {
|
||||
Parse::NodeKind::IdentifierNameNotBeforeParams) {
|
||||
context.pattern_block_stack().Push();
|
||||
context.full_pattern_stack().PushFullPattern(
|
||||
FullPatternStack::Kind::ExplicitParamList);
|
||||
@@ -365,81 +363,6 @@ static auto RequestVtableIfVirtual(
|
||||
context.vtable_stack().AddInstId(decl_id);
|
||||
}
|
||||
|
||||
// Validates the `destroy` function's signature. May replace invalid values for
|
||||
// recovery.
|
||||
static auto ValidateIfDestroy(Context& context, bool is_redecl,
|
||||
std::optional<SemIR::Inst> parent_scope_inst,
|
||||
SemIR::Function& function_info) -> void {
|
||||
if (function_info.name_id != SemIR::NameId::Destroy) {
|
||||
return;
|
||||
}
|
||||
|
||||
// For recovery, always force explicit parameters to be empty. We do this
|
||||
// before any of the returns for simplicity.
|
||||
auto orig_param_patterns_id = function_info.param_patterns_id;
|
||||
function_info.param_patterns_id = SemIR::InstBlockId::Empty;
|
||||
|
||||
// Use differences on merge to diagnose remaining issues.
|
||||
if (is_redecl) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!parent_scope_inst || !parent_scope_inst->Is<SemIR::ClassDecl>()) {
|
||||
CARBON_DIAGNOSTIC(DestroyFunctionOutsideClass, Error,
|
||||
"declaring `fn destroy` in non-class scope");
|
||||
context.emitter().Emit(function_info.latest_decl_id(),
|
||||
DestroyFunctionOutsideClass);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!function_info.self_param_id.has_value()) {
|
||||
CARBON_DIAGNOSTIC(DestroyFunctionMissingSelf, Error,
|
||||
"missing implicit `self` parameter");
|
||||
context.emitter().Emit(function_info.latest_decl_id(),
|
||||
DestroyFunctionMissingSelf);
|
||||
return;
|
||||
}
|
||||
|
||||
// `self` must be the only implicit parameter.
|
||||
if (auto block =
|
||||
context.inst_blocks().Get(function_info.implicit_param_patterns_id);
|
||||
block.size() > 1) {
|
||||
// Point at the first non-`self` parameter.
|
||||
auto param_id = block[function_info.self_param_id == block[0] ? 1 : 0];
|
||||
CARBON_DIAGNOSTIC(DestroyFunctionUnexpectedImplicitParam, Error,
|
||||
"unexpected implicit parameter");
|
||||
context.emitter().Emit(param_id, DestroyFunctionUnexpectedImplicitParam);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!orig_param_patterns_id.has_value()) {
|
||||
CARBON_DIAGNOSTIC(DestroyFunctionPositionalParams, Error,
|
||||
"missing empty explicit parameter list");
|
||||
context.emitter().Emit(function_info.latest_decl_id(),
|
||||
DestroyFunctionPositionalParams);
|
||||
return;
|
||||
}
|
||||
|
||||
if (orig_param_patterns_id != SemIR::InstBlockId::Empty) {
|
||||
CARBON_DIAGNOSTIC(DestroyFunctionNonEmptyExplicitParams, Error,
|
||||
"unexpected parameter");
|
||||
context.emitter().Emit(context.inst_blocks().Get(orig_param_patterns_id)[0],
|
||||
DestroyFunctionNonEmptyExplicitParams);
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto return_type_id =
|
||||
function_info.GetDeclaredReturnType(context.sem_ir());
|
||||
return_type_id.has_value() &&
|
||||
return_type_id != GetTupleType(context, {})) {
|
||||
CARBON_DIAGNOSTIC(DestroyFunctionIncorrectReturnType, Error,
|
||||
"incorrect return type; must be unspecified or `()`");
|
||||
context.emitter().Emit(function_info.return_slot_pattern_id,
|
||||
DestroyFunctionIncorrectReturnType);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Diagnoses when positional params aren't supported. Reassigns the pattern
|
||||
// block if needed.
|
||||
static auto DiagnosePositionalParams(Context& context,
|
||||
@@ -505,12 +428,6 @@ static auto BuildFunctionDecl(Context& context,
|
||||
function_info.definition_id = decl_id;
|
||||
}
|
||||
|
||||
// Analyze standard function signatures before positional parameters, so that
|
||||
// we can have more specific diagnostics and recovery.
|
||||
bool is_redecl =
|
||||
name_context.state == DeclNameStack::NameContext::State::Resolved;
|
||||
ValidateIfDestroy(context, is_redecl, parent_scope_inst, function_info);
|
||||
|
||||
DiagnosePositionalParams(context, function_info);
|
||||
|
||||
TryMergeRedecl(context, node_id, name_context, function_decl, function_info,
|
||||
|
||||
@@ -140,38 +140,6 @@ auto HandleParseNode(Context& context, Parse::IdentifierNameExprId node_id)
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the `NameId` for a keyword node.
|
||||
static auto GetKeywordAsNameId(
|
||||
Context& context, Parse::NodeIdOneOf<Parse::KeywordNameNotBeforeParamsId,
|
||||
Parse::KeywordNameBeforeParamsId>
|
||||
node_id) -> SemIR::NameId {
|
||||
auto token = context.parse_tree().node_token(node_id);
|
||||
switch (auto token_kind = context.tokens().GetKind(token)) {
|
||||
case Lex::TokenKind::Destroy:
|
||||
return SemIR::NameId::Destroy;
|
||||
default:
|
||||
CARBON_FATAL("Unexpected token kind: {0}", token_kind);
|
||||
}
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context,
|
||||
Parse::KeywordNameNotBeforeParamsId node_id) -> bool {
|
||||
// The parent is responsible for binding the name.
|
||||
context.node_stack().Push(node_id, GetKeywordAsNameId(context, node_id));
|
||||
return true;
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::KeywordNameBeforeParamsId node_id)
|
||||
-> bool {
|
||||
// Push a pattern block stack entry to handle the parameter pattern.
|
||||
context.pattern_block_stack().Push();
|
||||
context.full_pattern_stack().PushFullPattern(
|
||||
FullPatternStack::Kind::ImplicitParamList);
|
||||
// The parent is responsible for binding the name.
|
||||
context.node_stack().Push(node_id, GetKeywordAsNameId(context, node_id));
|
||||
return true;
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::BaseNameId node_id) -> bool {
|
||||
context.node_stack().Push(node_id, SemIR::NameId::Base);
|
||||
return true;
|
||||
@@ -219,18 +187,6 @@ auto HandleParseNode(Context& context,
|
||||
return ApplyNameQualifier(context);
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context,
|
||||
Parse::KeywordNameQualifierWithParamsId /*node_id*/)
|
||||
-> bool {
|
||||
return ApplyNameQualifier(context);
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context,
|
||||
Parse::KeywordNameQualifierWithoutParamsId /*node_id*/)
|
||||
-> bool {
|
||||
return ApplyNameQualifier(context);
|
||||
}
|
||||
|
||||
auto HandleParseNode(Context& context, Parse::DesignatorExprId node_id)
|
||||
-> bool {
|
||||
SemIR::NameId name_id = context.node_stack().PopName();
|
||||
|
||||
@@ -496,8 +496,6 @@ class NodeStack {
|
||||
case Parse::NodeKind::ImportIntroducer:
|
||||
case Parse::NodeKind::IndexExprStart:
|
||||
case Parse::NodeKind::InvalidParseStart:
|
||||
case Parse::NodeKind::KeywordNameQualifierWithParams:
|
||||
case Parse::NodeKind::KeywordNameQualifierWithoutParams:
|
||||
case Parse::NodeKind::LibraryIntroducer:
|
||||
case Parse::NodeKind::LibrarySpecifier:
|
||||
case Parse::NodeKind::InlineImportSpecifier:
|
||||
|
||||
@@ -295,8 +295,8 @@ class ScopeStack {
|
||||
// A stack for scope context.
|
||||
llvm::SmallVector<ScopeStackEntry> scope_stack_;
|
||||
|
||||
// A stack of `destroy` functions to call. This only has entries inside of
|
||||
// function bodies, where destruction on scope exit is required.
|
||||
// A stack of instances to destroy. This only has entries inside of function
|
||||
// bodies, where destruction on scope exit is required.
|
||||
ArrayStack<SemIR::InstId> destroy_id_stack_;
|
||||
|
||||
// Information about non-lexical scopes. This is a subset of the entries and
|
||||
|
||||
+144
-202
@@ -10,50 +10,36 @@
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/destroy_calls.carbon
|
||||
|
||||
// --- types.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class NoAddr {
|
||||
fn Make() -> NoAddr;
|
||||
fn destroy[self: Self]();
|
||||
}
|
||||
|
||||
class ExplicitReturn {
|
||||
fn Make() -> ExplicitReturn;
|
||||
fn destroy[self: Self]() -> ();
|
||||
}
|
||||
|
||||
class WithAddr {
|
||||
fn Make() -> WithAddr;
|
||||
fn destroy[addr self: Self*]();
|
||||
}
|
||||
|
||||
// --- implicit_return.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
import library "types";
|
||||
|
||||
class A {}
|
||||
class B {}
|
||||
class C {}
|
||||
|
||||
//@dump-sem-ir-begin
|
||||
fn F() {
|
||||
var no_addr: NoAddr;
|
||||
var explicit_return: ExplicitReturn;
|
||||
var with_addr: WithAddr;
|
||||
var a: A;
|
||||
var b: B;
|
||||
var c: C;
|
||||
}
|
||||
//@dump-sem-ir-end
|
||||
|
||||
// --- nested_scope.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
import library "types";
|
||||
|
||||
class A {}
|
||||
class B {}
|
||||
class C {}
|
||||
|
||||
//@dump-sem-ir-begin
|
||||
fn F() {
|
||||
var no_addr: NoAddr;
|
||||
var explicit_return: ExplicitReturn;
|
||||
var with_addr: WithAddr;
|
||||
var a: A;
|
||||
var b: B;
|
||||
if (true) {
|
||||
var in_scope: NoAddr;
|
||||
var c: C;
|
||||
}
|
||||
}
|
||||
//@dump-sem-ir-end
|
||||
@@ -61,43 +47,21 @@ fn F() {
|
||||
// --- temp.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
import library "types";
|
||||
|
||||
class A { fn Make() -> A; }
|
||||
class B { fn Make() -> B; }
|
||||
class C { fn Make() -> C; }
|
||||
|
||||
//@dump-sem-ir-begin
|
||||
fn F() {
|
||||
// TODO: The scoping of these destroy calls is incorrect. Maybe we need to
|
||||
// establish statement scopes?
|
||||
NoAddr.Make();
|
||||
ExplicitReturn.Make();
|
||||
WithAddr.Make();
|
||||
A.Make();
|
||||
B.Make();
|
||||
C.Make();
|
||||
}
|
||||
//@dump-sem-ir-end
|
||||
|
||||
// --- fail_recovery.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class NoSelf {
|
||||
// CHECK:STDERR: fail_recovery.carbon:[[@LINE+4]]:3: error: missing implicit `self` parameter [DestroyFunctionMissingSelf]
|
||||
// CHECK:STDERR: fn destroy();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy();
|
||||
}
|
||||
|
||||
class Args {
|
||||
// CHECK:STDERR: fail_recovery.carbon:[[@LINE+4]]:26: error: unexpected parameter [DestroyFunctionNonEmptyExplicitParams]
|
||||
// CHECK:STDERR: fn destroy[self: Self](x: ());
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy[self: Self](x: ());
|
||||
}
|
||||
|
||||
fn F() {
|
||||
var a: NoSelf;
|
||||
var b: Args;
|
||||
}
|
||||
|
||||
// --- generic_class.carbon
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
@@ -127,30 +91,27 @@ fn G() { F({}); }
|
||||
// CHECK:STDOUT: --- implicit_return.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %A: type = class_type @A [concrete]
|
||||
// CHECK:STDOUT: %ptr.6db: type = ptr_type %A [concrete]
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.type: type = fn_type @A.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op: %A.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %B: type = class_type @B [concrete]
|
||||
// CHECK:STDOUT: %ptr.e79: type = ptr_type %B [concrete]
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.type: type = fn_type @B.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op: %B.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: %ptr.019: type = ptr_type %C [concrete]
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.type: type = fn_type @C.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op: %C.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %NoAddr: type = class_type @NoAddr [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.88f: type = pattern_type %NoAddr [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn: type = class_type @ExplicitReturn [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.611: type = pattern_type %ExplicitReturn [concrete]
|
||||
// CHECK:STDOUT: %WithAddr: type = class_type @WithAddr [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.f93: type = pattern_type %WithAddr [concrete]
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.type: type = fn_type @WithAddr.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op: %WithAddr.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.b4e: type = ptr_type %WithAddr [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.type: type = fn_type @ExplicitReturn.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op: %ExplicitReturn.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.b0a: type = ptr_type %ExplicitReturn [concrete]
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.type: type = fn_type @NoAddr.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op: %NoAddr.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.4b8: type = ptr_type %NoAddr [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.c10: type = pattern_type %A [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.049: type = pattern_type %B [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.c48: type = pattern_type %C [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Main.NoAddr: type = import_ref Main//types, NoAddr, loaded [concrete = constants.%NoAddr]
|
||||
// CHECK:STDOUT: %Main.ExplicitReturn: type = import_ref Main//types, ExplicitReturn, loaded [concrete = constants.%ExplicitReturn]
|
||||
// CHECK:STDOUT: %Main.WithAddr: type = import_ref Main//types, WithAddr, loaded [concrete = constants.%WithAddr]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -160,66 +121,63 @@ fn G() { F({}); }
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %no_addr.patt: %pattern_type.88f = binding_pattern no_addr [concrete]
|
||||
// CHECK:STDOUT: %no_addr.var_patt: %pattern_type.88f = var_pattern %no_addr.patt [concrete]
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.c10 = binding_pattern a [concrete]
|
||||
// CHECK:STDOUT: %a.var_patt: %pattern_type.c10 = var_pattern %a.patt [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %no_addr.var: ref %NoAddr = var %no_addr.var_patt
|
||||
// CHECK:STDOUT: %NoAddr.ref: type = name_ref NoAddr, imports.%Main.NoAddr [concrete = constants.%NoAddr]
|
||||
// CHECK:STDOUT: %no_addr: ref %NoAddr = bind_name no_addr, %no_addr.var
|
||||
// CHECK:STDOUT: %a.var: ref %A = var %a.var_patt
|
||||
// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]
|
||||
// CHECK:STDOUT: %a: ref %A = bind_name a, %a.var
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %explicit_return.patt: %pattern_type.611 = binding_pattern explicit_return [concrete]
|
||||
// CHECK:STDOUT: %explicit_return.var_patt: %pattern_type.611 = var_pattern %explicit_return.patt [concrete]
|
||||
// CHECK:STDOUT: %b.patt: %pattern_type.049 = binding_pattern b [concrete]
|
||||
// CHECK:STDOUT: %b.var_patt: %pattern_type.049 = var_pattern %b.patt [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %explicit_return.var: ref %ExplicitReturn = var %explicit_return.var_patt
|
||||
// CHECK:STDOUT: %ExplicitReturn.ref: type = name_ref ExplicitReturn, imports.%Main.ExplicitReturn [concrete = constants.%ExplicitReturn]
|
||||
// CHECK:STDOUT: %explicit_return: ref %ExplicitReturn = bind_name explicit_return, %explicit_return.var
|
||||
// CHECK:STDOUT: %b.var: ref %B = var %b.var_patt
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]
|
||||
// CHECK:STDOUT: %b: ref %B = bind_name b, %b.var
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %with_addr.patt: %pattern_type.f93 = binding_pattern with_addr [concrete]
|
||||
// CHECK:STDOUT: %with_addr.var_patt: %pattern_type.f93 = var_pattern %with_addr.patt [concrete]
|
||||
// CHECK:STDOUT: %c.patt: %pattern_type.c48 = binding_pattern c [concrete]
|
||||
// CHECK:STDOUT: %c.var_patt: %pattern_type.c48 = var_pattern %c.patt [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %with_addr.var: ref %WithAddr = var %with_addr.var_patt
|
||||
// CHECK:STDOUT: %WithAddr.ref: type = name_ref WithAddr, imports.%Main.WithAddr [concrete = constants.%WithAddr]
|
||||
// CHECK:STDOUT: %with_addr: ref %WithAddr = bind_name with_addr, %with_addr.var
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.bound: <bound method> = bound_method %with_addr.var, constants.%WithAddr.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc9: %ptr.b4e = addr_of %with_addr.var
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.call: init %empty_tuple.type = call %WithAddr.as.Destroy.impl.Op.bound(%addr.loc9)
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.bound: <bound method> = bound_method %explicit_return.var, constants.%ExplicitReturn.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc8: %ptr.b0a = addr_of %explicit_return.var
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.call: init %empty_tuple.type = call %ExplicitReturn.as.Destroy.impl.Op.bound(%addr.loc8)
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.bound: <bound method> = bound_method %no_addr.var, constants.%NoAddr.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc7: %ptr.4b8 = addr_of %no_addr.var
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.call: init %empty_tuple.type = call %NoAddr.as.Destroy.impl.Op.bound(%addr.loc7)
|
||||
// CHECK:STDOUT: %c.var: ref %C = var %c.var_patt
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
|
||||
// CHECK:STDOUT: %c: ref %C = bind_name c, %c.var
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.bound: <bound method> = bound_method %c.var, constants.%C.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc12: %ptr.019 = addr_of %c.var
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.call: init %empty_tuple.type = call %C.as.Destroy.impl.Op.bound(%addr.loc12)
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.bound: <bound method> = bound_method %b.var, constants.%B.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc11: %ptr.e79 = addr_of %b.var
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.call: init %empty_tuple.type = call %B.as.Destroy.impl.Op.bound(%addr.loc11)
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.bound: <bound method> = bound_method %a.var, constants.%A.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc10: %ptr.6db = addr_of %a.var
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.call: init %empty_tuple.type = call %A.as.Destroy.impl.Op.bound(%addr.loc10)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- nested_scope.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %A: type = class_type @A [concrete]
|
||||
// CHECK:STDOUT: %ptr.6db: type = ptr_type %A [concrete]
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.type: type = fn_type @A.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op: %A.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %B: type = class_type @B [concrete]
|
||||
// CHECK:STDOUT: %ptr.e79: type = ptr_type %B [concrete]
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.type: type = fn_type @B.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op: %B.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: %ptr.019: type = ptr_type %C [concrete]
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.type: type = fn_type @C.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op: %C.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %NoAddr: type = class_type @NoAddr [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.88f: type = pattern_type %NoAddr [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn: type = class_type @ExplicitReturn [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.611: type = pattern_type %ExplicitReturn [concrete]
|
||||
// CHECK:STDOUT: %WithAddr: type = class_type @WithAddr [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.f93: type = pattern_type %WithAddr [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.c10: type = pattern_type %A [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.049: type = pattern_type %B [concrete]
|
||||
// CHECK:STDOUT: %true: bool = bool_literal true [concrete]
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.type: type = fn_type @NoAddr.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op: %NoAddr.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.4b8: type = ptr_type %NoAddr [concrete]
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.type: type = fn_type @WithAddr.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op: %WithAddr.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.b4e: type = ptr_type %WithAddr [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.type: type = fn_type @ExplicitReturn.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op: %ExplicitReturn.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.b0a: type = ptr_type %ExplicitReturn [concrete]
|
||||
// CHECK:STDOUT: %pattern_type.c48: type = pattern_type %C [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Main.NoAddr: type = import_ref Main//types, NoAddr, loaded [concrete = constants.%NoAddr]
|
||||
// CHECK:STDOUT: %Main.ExplicitReturn: type = import_ref Main//types, ExplicitReturn, loaded [concrete = constants.%ExplicitReturn]
|
||||
// CHECK:STDOUT: %Main.WithAddr: type = import_ref Main//types, WithAddr, loaded [concrete = constants.%WithAddr]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -229,88 +187,72 @@ fn G() { F({}); }
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %no_addr.patt: %pattern_type.88f = binding_pattern no_addr [concrete]
|
||||
// CHECK:STDOUT: %no_addr.var_patt: %pattern_type.88f = var_pattern %no_addr.patt [concrete]
|
||||
// CHECK:STDOUT: %a.patt: %pattern_type.c10 = binding_pattern a [concrete]
|
||||
// CHECK:STDOUT: %a.var_patt: %pattern_type.c10 = var_pattern %a.patt [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %no_addr.var: ref %NoAddr = var %no_addr.var_patt
|
||||
// CHECK:STDOUT: %NoAddr.ref.loc7: type = name_ref NoAddr, imports.%Main.NoAddr [concrete = constants.%NoAddr]
|
||||
// CHECK:STDOUT: %no_addr: ref %NoAddr = bind_name no_addr, %no_addr.var
|
||||
// CHECK:STDOUT: %a.var: ref %A = var %a.var_patt
|
||||
// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]
|
||||
// CHECK:STDOUT: %a: ref %A = bind_name a, %a.var
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %explicit_return.patt: %pattern_type.611 = binding_pattern explicit_return [concrete]
|
||||
// CHECK:STDOUT: %explicit_return.var_patt: %pattern_type.611 = var_pattern %explicit_return.patt [concrete]
|
||||
// CHECK:STDOUT: %b.patt: %pattern_type.049 = binding_pattern b [concrete]
|
||||
// CHECK:STDOUT: %b.var_patt: %pattern_type.049 = var_pattern %b.patt [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %explicit_return.var: ref %ExplicitReturn = var %explicit_return.var_patt
|
||||
// CHECK:STDOUT: %ExplicitReturn.ref: type = name_ref ExplicitReturn, imports.%Main.ExplicitReturn [concrete = constants.%ExplicitReturn]
|
||||
// CHECK:STDOUT: %explicit_return: ref %ExplicitReturn = bind_name explicit_return, %explicit_return.var
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %with_addr.patt: %pattern_type.f93 = binding_pattern with_addr [concrete]
|
||||
// CHECK:STDOUT: %with_addr.var_patt: %pattern_type.f93 = var_pattern %with_addr.patt [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %with_addr.var: ref %WithAddr = var %with_addr.var_patt
|
||||
// CHECK:STDOUT: %WithAddr.ref: type = name_ref WithAddr, imports.%Main.WithAddr [concrete = constants.%WithAddr]
|
||||
// CHECK:STDOUT: %with_addr: ref %WithAddr = bind_name with_addr, %with_addr.var
|
||||
// CHECK:STDOUT: %b.var: ref %B = var %b.var_patt
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]
|
||||
// CHECK:STDOUT: %b: ref %B = bind_name b, %b.var
|
||||
// CHECK:STDOUT: %true: bool = bool_literal true [concrete = constants.%true]
|
||||
// CHECK:STDOUT: if %true br !if.then else br !if.else
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !if.then:
|
||||
// CHECK:STDOUT: name_binding_decl {
|
||||
// CHECK:STDOUT: %in_scope.patt: %pattern_type.88f = binding_pattern in_scope [concrete]
|
||||
// CHECK:STDOUT: %in_scope.var_patt: %pattern_type.88f = var_pattern %in_scope.patt [concrete]
|
||||
// CHECK:STDOUT: %c.patt: %pattern_type.c48 = binding_pattern c [concrete]
|
||||
// CHECK:STDOUT: %c.var_patt: %pattern_type.c48 = var_pattern %c.patt [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT: %in_scope.var: ref %NoAddr = var %in_scope.var_patt
|
||||
// CHECK:STDOUT: %NoAddr.ref.loc11: type = name_ref NoAddr, imports.%Main.NoAddr [concrete = constants.%NoAddr]
|
||||
// CHECK:STDOUT: %in_scope: ref %NoAddr = bind_name in_scope, %in_scope.var
|
||||
// CHECK:STDOUT: %c.var: ref %C = var %c.var_patt
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
|
||||
// CHECK:STDOUT: %c: ref %C = bind_name c, %c.var
|
||||
// CHECK:STDOUT: br !if.else
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: !if.else:
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.bound.loc11: <bound method> = bound_method %in_scope.var, constants.%NoAddr.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc11: %ptr.4b8 = addr_of %in_scope.var
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.call.loc11: init %empty_tuple.type = call %NoAddr.as.Destroy.impl.Op.bound.loc11(%addr.loc11)
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.bound: <bound method> = bound_method %with_addr.var, constants.%WithAddr.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc9: %ptr.b4e = addr_of %with_addr.var
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.call: init %empty_tuple.type = call %WithAddr.as.Destroy.impl.Op.bound(%addr.loc9)
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.bound: <bound method> = bound_method %explicit_return.var, constants.%ExplicitReturn.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc8: %ptr.b0a = addr_of %explicit_return.var
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.call: init %empty_tuple.type = call %ExplicitReturn.as.Destroy.impl.Op.bound(%addr.loc8)
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.bound.loc7: <bound method> = bound_method %no_addr.var, constants.%NoAddr.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc7: %ptr.4b8 = addr_of %no_addr.var
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.call.loc7: init %empty_tuple.type = call %NoAddr.as.Destroy.impl.Op.bound.loc7(%addr.loc7)
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.bound: <bound method> = bound_method %c.var, constants.%C.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc13: %ptr.019 = addr_of %c.var
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.call: init %empty_tuple.type = call %C.as.Destroy.impl.Op.bound(%addr.loc13)
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.bound: <bound method> = bound_method %b.var, constants.%B.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc11: %ptr.e79 = addr_of %b.var
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.call: init %empty_tuple.type = call %B.as.Destroy.impl.Op.bound(%addr.loc11)
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.bound: <bound method> = bound_method %a.var, constants.%A.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc10: %ptr.6db = addr_of %a.var
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.call: init %empty_tuple.type = call %A.as.Destroy.impl.Op.bound(%addr.loc10)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: --- temp.carbon
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: constants {
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %A: type = class_type @A [concrete]
|
||||
// CHECK:STDOUT: %A.Make.type: type = fn_type @A.Make [concrete]
|
||||
// CHECK:STDOUT: %empty_tuple.type: type = tuple_type () [concrete]
|
||||
// CHECK:STDOUT: %A.Make: %A.Make.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.6db: type = ptr_type %A [concrete]
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.type: type = fn_type @A.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op: %A.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %B: type = class_type @B [concrete]
|
||||
// CHECK:STDOUT: %B.Make.type: type = fn_type @B.Make [concrete]
|
||||
// CHECK:STDOUT: %B.Make: %B.Make.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.e79: type = ptr_type %B [concrete]
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.type: type = fn_type @B.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op: %B.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %C: type = class_type @C [concrete]
|
||||
// CHECK:STDOUT: %C.Make.type: type = fn_type @C.Make [concrete]
|
||||
// CHECK:STDOUT: %C.Make: %C.Make.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.019: type = ptr_type %C [concrete]
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.type: type = fn_type @C.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op: %C.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %F.type: type = fn_type @F [concrete]
|
||||
// CHECK:STDOUT: %F: %F.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %NoAddr: type = class_type @NoAddr [concrete]
|
||||
// CHECK:STDOUT: %NoAddr.Make.type: type = fn_type @NoAddr.Make [concrete]
|
||||
// CHECK:STDOUT: %NoAddr.Make: %NoAddr.Make.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn: type = class_type @ExplicitReturn [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn.Make.type: type = fn_type @ExplicitReturn.Make [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn.Make: %ExplicitReturn.Make.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %WithAddr: type = class_type @WithAddr [concrete]
|
||||
// CHECK:STDOUT: %WithAddr.Make.type: type = fn_type @WithAddr.Make [concrete]
|
||||
// CHECK:STDOUT: %WithAddr.Make: %WithAddr.Make.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.type: type = fn_type @WithAddr.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op: %WithAddr.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.b4e: type = ptr_type %WithAddr [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.type: type = fn_type @ExplicitReturn.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op: %ExplicitReturn.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.b0a: type = ptr_type %ExplicitReturn [concrete]
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.type: type = fn_type @NoAddr.as.Destroy.impl.Op [concrete]
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op: %NoAddr.as.Destroy.impl.Op.type = struct_value () [concrete]
|
||||
// CHECK:STDOUT: %ptr.4b8: type = ptr_type %NoAddr [concrete]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: imports {
|
||||
// CHECK:STDOUT: %Main.NoAddr: type = import_ref Main//types, NoAddr, loaded [concrete = constants.%NoAddr]
|
||||
// CHECK:STDOUT: %Main.ExplicitReturn: type = import_ref Main//types, ExplicitReturn, loaded [concrete = constants.%ExplicitReturn]
|
||||
// CHECK:STDOUT: %Main.WithAddr: type = import_ref Main//types, WithAddr, loaded [concrete = constants.%WithAddr]
|
||||
// CHECK:STDOUT: %Main.import_ref.784: %NoAddr.Make.type = import_ref Main//types, loc5_22, loaded [concrete = constants.%NoAddr.Make]
|
||||
// CHECK:STDOUT: %Main.import_ref.8e0: %ExplicitReturn.Make.type = import_ref Main//types, loc10_30, loaded [concrete = constants.%ExplicitReturn.Make]
|
||||
// CHECK:STDOUT: %Main.import_ref.974: %WithAddr.Make.type = import_ref Main//types, loc15_24, loaded [concrete = constants.%WithAddr.Make]
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: file {
|
||||
@@ -319,30 +261,30 @@ fn G() { F({}); }
|
||||
// CHECK:STDOUT:
|
||||
// CHECK:STDOUT: fn @F() {
|
||||
// CHECK:STDOUT: !entry:
|
||||
// CHECK:STDOUT: %NoAddr.ref: type = name_ref NoAddr, imports.%Main.NoAddr [concrete = constants.%NoAddr]
|
||||
// CHECK:STDOUT: %Make.ref.loc9: %NoAddr.Make.type = name_ref Make, imports.%Main.import_ref.784 [concrete = constants.%NoAddr.Make]
|
||||
// CHECK:STDOUT: %.loc9_15.1: ref %NoAddr = temporary_storage
|
||||
// CHECK:STDOUT: %NoAddr.Make.call: init %NoAddr = call %Make.ref.loc9() to %.loc9_15.1
|
||||
// CHECK:STDOUT: %.loc9_15.2: ref %NoAddr = temporary %.loc9_15.1, %NoAddr.Make.call
|
||||
// CHECK:STDOUT: %ExplicitReturn.ref: type = name_ref ExplicitReturn, imports.%Main.ExplicitReturn [concrete = constants.%ExplicitReturn]
|
||||
// CHECK:STDOUT: %Make.ref.loc10: %ExplicitReturn.Make.type = name_ref Make, imports.%Main.import_ref.8e0 [concrete = constants.%ExplicitReturn.Make]
|
||||
// CHECK:STDOUT: %.loc10_23.1: ref %ExplicitReturn = temporary_storage
|
||||
// CHECK:STDOUT: %ExplicitReturn.Make.call: init %ExplicitReturn = call %Make.ref.loc10() to %.loc10_23.1
|
||||
// CHECK:STDOUT: %.loc10_23.2: ref %ExplicitReturn = temporary %.loc10_23.1, %ExplicitReturn.Make.call
|
||||
// CHECK:STDOUT: %WithAddr.ref: type = name_ref WithAddr, imports.%Main.WithAddr [concrete = constants.%WithAddr]
|
||||
// CHECK:STDOUT: %Make.ref.loc11: %WithAddr.Make.type = name_ref Make, imports.%Main.import_ref.974 [concrete = constants.%WithAddr.Make]
|
||||
// CHECK:STDOUT: %.loc11_17.1: ref %WithAddr = temporary_storage
|
||||
// CHECK:STDOUT: %WithAddr.Make.call: init %WithAddr = call %Make.ref.loc11() to %.loc11_17.1
|
||||
// CHECK:STDOUT: %.loc11_17.2: ref %WithAddr = temporary %.loc11_17.1, %WithAddr.Make.call
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc11_17.2, constants.%WithAddr.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc11: %ptr.b4e = addr_of %.loc11_17.2
|
||||
// CHECK:STDOUT: %WithAddr.as.Destroy.impl.Op.call: init %empty_tuple.type = call %WithAddr.as.Destroy.impl.Op.bound(%addr.loc11)
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc10_23.2, constants.%ExplicitReturn.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc10: %ptr.b0a = addr_of %.loc10_23.2
|
||||
// CHECK:STDOUT: %ExplicitReturn.as.Destroy.impl.Op.call: init %empty_tuple.type = call %ExplicitReturn.as.Destroy.impl.Op.bound(%addr.loc10)
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc9_15.2, constants.%NoAddr.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc9: %ptr.4b8 = addr_of %.loc9_15.2
|
||||
// CHECK:STDOUT: %NoAddr.as.Destroy.impl.Op.call: init %empty_tuple.type = call %NoAddr.as.Destroy.impl.Op.bound(%addr.loc9)
|
||||
// CHECK:STDOUT: %A.ref: type = name_ref A, file.%A.decl [concrete = constants.%A]
|
||||
// CHECK:STDOUT: %Make.ref.loc12: %A.Make.type = name_ref Make, @A.%A.Make.decl [concrete = constants.%A.Make]
|
||||
// CHECK:STDOUT: %.loc12_10.1: ref %A = temporary_storage
|
||||
// CHECK:STDOUT: %A.Make.call: init %A = call %Make.ref.loc12() to %.loc12_10.1
|
||||
// CHECK:STDOUT: %.loc12_10.2: ref %A = temporary %.loc12_10.1, %A.Make.call
|
||||
// CHECK:STDOUT: %B.ref: type = name_ref B, file.%B.decl [concrete = constants.%B]
|
||||
// CHECK:STDOUT: %Make.ref.loc13: %B.Make.type = name_ref Make, @B.%B.Make.decl [concrete = constants.%B.Make]
|
||||
// CHECK:STDOUT: %.loc13_10.1: ref %B = temporary_storage
|
||||
// CHECK:STDOUT: %B.Make.call: init %B = call %Make.ref.loc13() to %.loc13_10.1
|
||||
// CHECK:STDOUT: %.loc13_10.2: ref %B = temporary %.loc13_10.1, %B.Make.call
|
||||
// CHECK:STDOUT: %C.ref: type = name_ref C, file.%C.decl [concrete = constants.%C]
|
||||
// CHECK:STDOUT: %Make.ref.loc14: %C.Make.type = name_ref Make, @C.%C.Make.decl [concrete = constants.%C.Make]
|
||||
// CHECK:STDOUT: %.loc14_10.1: ref %C = temporary_storage
|
||||
// CHECK:STDOUT: %C.Make.call: init %C = call %Make.ref.loc14() to %.loc14_10.1
|
||||
// CHECK:STDOUT: %.loc14_10.2: ref %C = temporary %.loc14_10.1, %C.Make.call
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc14_10.2, constants.%C.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc14: %ptr.019 = addr_of %.loc14_10.2
|
||||
// CHECK:STDOUT: %C.as.Destroy.impl.Op.call: init %empty_tuple.type = call %C.as.Destroy.impl.Op.bound(%addr.loc14)
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc13_10.2, constants.%B.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc13: %ptr.e79 = addr_of %.loc13_10.2
|
||||
// CHECK:STDOUT: %B.as.Destroy.impl.Op.call: init %empty_tuple.type = call %B.as.Destroy.impl.Op.bound(%addr.loc13)
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.bound: <bound method> = bound_method %.loc12_10.2, constants.%A.as.Destroy.impl.Op
|
||||
// CHECK:STDOUT: %addr.loc12: %ptr.6db = addr_of %.loc12_10.2
|
||||
// CHECK:STDOUT: %A.as.Destroy.impl.Op.call: init %empty_tuple.type = call %A.as.Destroy.impl.Op.bound(%addr.loc12)
|
||||
// CHECK:STDOUT: return
|
||||
// CHECK:STDOUT: }
|
||||
// CHECK:STDOUT:
|
||||
|
||||
-219
@@ -1,219 +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
|
||||
//
|
||||
// INCLUDE-FILE: toolchain/testing/testdata/min_prelude/destroy.carbon
|
||||
//
|
||||
// AUTOUPDATE
|
||||
// TIP: To test this file alone, run:
|
||||
// TIP: bazel test //toolchain/testing:file_test --test_arg=--file_tests=toolchain/check/testdata/class/destroy_decl.carbon
|
||||
// TIP: To dump output, run:
|
||||
// TIP: bazel run //toolchain/testing:file_test -- --dump_output --file_tests=toolchain/check/testdata/class/destroy_decl.carbon
|
||||
|
||||
// --- self.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
fn destroy[self: Self]();
|
||||
}
|
||||
|
||||
// --- declare_impl.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
impl as Core.Destroy;
|
||||
}
|
||||
|
||||
// --- fail_define_impl.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
// CHECK:STDERR: fail_define_impl.carbon:[[@LINE+3]]:1: error: redefinition of `impl Self as Core.Destroy` [ImplRedefinition]
|
||||
// CHECK:STDERR: class C {
|
||||
// CHECK:STDERR: ^~~~~~~~~
|
||||
class C {
|
||||
// CHECK:STDERR: fail_define_impl.carbon:[[@LINE+4]]:3: note: previous definition was here [ImplPreviousDefinition]
|
||||
// CHECK:STDERR: impl as Core.Destroy {
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
impl as Core.Destroy {
|
||||
fn Op[addr self: Self*]() {}
|
||||
}
|
||||
}
|
||||
|
||||
// --- addr_self.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
fn destroy[addr self: Self*]();
|
||||
}
|
||||
|
||||
// --- explicit_return.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
fn destroy[self: Self]() -> ();
|
||||
}
|
||||
|
||||
// --- fail_class_function.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_class_function.carbon:[[@LINE+4]]:3: error: missing implicit `self` parameter [DestroyFunctionMissingSelf]
|
||||
// CHECK:STDERR: fn destroy();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy();
|
||||
}
|
||||
|
||||
// --- fail_extra_implicit_params_second.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_extra_implicit_params_second.carbon:[[@LINE+4]]:26: error: unexpected implicit parameter [DestroyFunctionUnexpectedImplicitParam]
|
||||
// CHECK:STDERR: fn destroy[self: Self, T:! type]();
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
fn destroy[self: Self, T:! type]();
|
||||
}
|
||||
|
||||
// --- fail_extra_implicit_params_first.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_extra_implicit_params_first.carbon:[[@LINE+4]]:14: error: unexpected implicit parameter [DestroyFunctionUnexpectedImplicitParam]
|
||||
// CHECK:STDERR: fn destroy[T:! type, self: Self]();
|
||||
// CHECK:STDERR: ^
|
||||
// CHECK:STDERR:
|
||||
fn destroy[T:! type, self: Self]();
|
||||
}
|
||||
|
||||
// --- fail_positional_params.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_positional_params.carbon:[[@LINE+4]]:3: error: missing empty explicit parameter list [DestroyFunctionPositionalParams]
|
||||
// CHECK:STDERR: fn destroy[self: Self];
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy[self: Self];
|
||||
}
|
||||
|
||||
// --- fail_explicit_params.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_explicit_params.carbon:[[@LINE+4]]:26: error: unexpected parameter [DestroyFunctionNonEmptyExplicitParams]
|
||||
// CHECK:STDERR: fn destroy[self: Self](x: ());
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy[self: Self](x: ());
|
||||
}
|
||||
|
||||
// --- fail_return_type.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
// CHECK:STDERR: fail_return_type.carbon:[[@LINE+4]]:28: error: incorrect return type; must be unspecified or `()` [DestroyFunctionIncorrectReturnType]
|
||||
// CHECK:STDERR: fn destroy[self: Self]() -> {};
|
||||
// CHECK:STDERR: ^~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy[self: Self]() -> {};
|
||||
}
|
||||
|
||||
// --- fail_out_of_line_missing_params.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
|
||||
class C {
|
||||
fn destroy[self: Self]();
|
||||
}
|
||||
|
||||
// CHECK:STDERR: fail_out_of_line_missing_params.carbon:[[@LINE+7]]:1: error: redeclaration differs because of missing implicit parameter list [RedeclParamListDiffers]
|
||||
// CHECK:STDERR: fn C.destroy {}
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~
|
||||
// CHECK:STDERR: fail_out_of_line_missing_params.carbon:[[@LINE-6]]:3: note: previously declared with implicit parameter list [RedeclParamListPrevious]
|
||||
// CHECK:STDERR: fn destroy[self: Self]();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn C.destroy {}
|
||||
|
||||
// --- fail_destroy_in_file_scope.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
// CHECK:STDERR: fail_destroy_in_file_scope.carbon:[[@LINE+4]]:1: error: declaring `fn destroy` in non-class scope [DestroyFunctionOutsideClass]
|
||||
// CHECK:STDERR: fn destroy[self: ()]();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy[self: ()]();
|
||||
|
||||
// --- fail_destroy_in_namespace_scope.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
namespace NS;
|
||||
|
||||
// CHECK:STDERR: fail_destroy_in_namespace_scope.carbon:[[@LINE+4]]:1: error: declaring `fn destroy` in non-class scope [DestroyFunctionOutsideClass]
|
||||
// CHECK:STDERR: fn NS.destroy();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn NS.destroy();
|
||||
|
||||
// --- fail_invalid_qualifier_with_params.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
fn destroy[self: Self]();
|
||||
}
|
||||
|
||||
// CHECK:STDERR: fail_invalid_qualifier_with_params.carbon:[[@LINE+7]]:6: error: name qualifiers are only allowed for entities that provide a scope [QualifiedNameInNonScope]
|
||||
// CHECK:STDERR: fn C.destroy[self: Self]().Foo() {}
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_invalid_qualifier_with_params.carbon:[[@LINE-6]]:3: note: referenced non-scope entity declared here [QualifiedNameNonScopeEntity]
|
||||
// CHECK:STDERR: fn destroy[self: Self]();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn C.destroy[self: Self]().Foo() {}
|
||||
|
||||
// --- fail_invalid_qualifier_no_params.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class C {
|
||||
fn destroy[self: Self]();
|
||||
}
|
||||
|
||||
// CHECK:STDERR: fail_invalid_qualifier_no_params.carbon:[[@LINE+7]]:6: error: name qualifiers are only allowed for entities that provide a scope [QualifiedNameInNonScope]
|
||||
// CHECK:STDERR: fn C.destroy.Foo() {}
|
||||
// CHECK:STDERR: ^~~~~~~
|
||||
// CHECK:STDERR: fail_invalid_qualifier_no_params.carbon:[[@LINE-6]]:3: note: referenced non-scope entity declared here [QualifiedNameNonScopeEntity]
|
||||
// CHECK:STDERR: fn destroy[self: Self]();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn C.destroy.Foo() {}
|
||||
|
||||
// --- fail_return_type_after_no_params.carbon
|
||||
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
// Return type handling special-cases the "no params" case.
|
||||
class C {
|
||||
// CHECK:STDERR: fail_return_type_after_no_params.carbon:[[@LINE+4]]:3: error: missing implicit `self` parameter [DestroyFunctionMissingSelf]
|
||||
// CHECK:STDERR: fn destroy -> ();
|
||||
// CHECK:STDERR: ^~~~~~~~~~~~~~~~~
|
||||
// CHECK:STDERR:
|
||||
fn destroy -> ();
|
||||
}
|
||||
@@ -268,13 +268,6 @@ CARBON_DIAGNOSTIC_KIND(InvalidBuiltinSignature)
|
||||
CARBON_DIAGNOSTIC_KIND(ThunkSignature)
|
||||
CARBON_DIAGNOSTIC_KIND(ThunkCallee)
|
||||
|
||||
CARBON_DIAGNOSTIC_KIND(DestroyFunctionOutsideClass)
|
||||
CARBON_DIAGNOSTIC_KIND(DestroyFunctionMissingSelf)
|
||||
CARBON_DIAGNOSTIC_KIND(DestroyFunctionUnexpectedImplicitParam)
|
||||
CARBON_DIAGNOSTIC_KIND(DestroyFunctionPositionalParams)
|
||||
CARBON_DIAGNOSTIC_KIND(DestroyFunctionNonEmptyExplicitParams)
|
||||
CARBON_DIAGNOSTIC_KIND(DestroyFunctionIncorrectReturnType)
|
||||
|
||||
// Class checking.
|
||||
CARBON_DIAGNOSTIC_KIND(AdaptDeclRepeated)
|
||||
CARBON_DIAGNOSTIC_KIND(AdaptWithBase)
|
||||
|
||||
@@ -181,7 +181,6 @@ CARBON_KEYWORD_TOKEN(Const, "const")
|
||||
CARBON_KEYWORD_TOKEN(Continue, "continue")
|
||||
CARBON_KEYWORD_TOKEN(Core, "Core")
|
||||
CARBON_KEYWORD_TOKEN(Default, "default")
|
||||
CARBON_KEYWORD_TOKEN(Destroy, "destroy")
|
||||
CARBON_KEYWORD_TOKEN(Else, "else")
|
||||
CARBON_KEYWORD_TOKEN(Extend, "extend")
|
||||
CARBON_KEYWORD_TOKEN(Extern, "extern")
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
library "[[@TEST_NAME]]";
|
||||
|
||||
class HasDestroy {
|
||||
// TODO: Use `fn destroy` instead once lowering supports it.
|
||||
// TODO: Change for `Destruction`+`Destroy`.
|
||||
impl as Core.Destroy {
|
||||
fn Op[self: Self]();
|
||||
}
|
||||
|
||||
@@ -55,13 +55,6 @@ auto HandleDeclNameAndParams(Context& context) -> void {
|
||||
return;
|
||||
}
|
||||
|
||||
if (auto keyword = context.ConsumeIf(Lex::TokenKind::Destroy)) {
|
||||
HandleName(context, state, *keyword, NodeKind::KeywordNameNotBeforeParams,
|
||||
NodeKind::KeywordNameQualifierWithoutParams,
|
||||
NodeKind::KeywordNameBeforeParams);
|
||||
return;
|
||||
}
|
||||
|
||||
Lex::TokenIndex token = *context.position();
|
||||
if (context.tokens().GetKind(token) == Lex::TokenKind::FileEnd) {
|
||||
// The end of file is an unhelpful diagnostic location. Instead, use the
|
||||
@@ -100,11 +93,10 @@ auto HandleDeclNameAndParamsAfterParams(Context& context) -> void {
|
||||
auto state = context.PopState();
|
||||
|
||||
if (auto period = context.ConsumeIf(Lex::TokenKind::Period)) {
|
||||
auto start_kind = context.tree().node_kind(NodeId(state.subtree_start));
|
||||
auto node_kind = start_kind == NodeKind::IdentifierNameBeforeParams
|
||||
? NodeKind::IdentifierNameQualifierWithParams
|
||||
: NodeKind::KeywordNameQualifierWithParams;
|
||||
context.AddNode(node_kind, *period, state.has_error);
|
||||
CARBON_CHECK(context.tree().node_kind(NodeId(state.subtree_start)) ==
|
||||
NodeKind::IdentifierNameBeforeParams);
|
||||
context.AddNode(NodeKind::IdentifierNameQualifierWithParams, *period,
|
||||
state.has_error);
|
||||
context.PushState(StateKind::DeclNameAndParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,9 +98,6 @@ CARBON_PARSE_NODE_KIND(EmptyDecl)
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameNotBeforeParams)
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameBeforeParams)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(KeywordNameNotBeforeParams)
|
||||
CARBON_PARSE_NODE_KIND(KeywordNameBeforeParams)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameExpr)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(SelfValueName)
|
||||
@@ -133,8 +130,6 @@ CARBON_PARSE_NODE_KIND(InlineImportBody)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameQualifierWithParams)
|
||||
CARBON_PARSE_NODE_KIND(IdentifierNameQualifierWithoutParams)
|
||||
CARBON_PARSE_NODE_KIND(KeywordNameQualifierWithParams)
|
||||
CARBON_PARSE_NODE_KIND(KeywordNameQualifierWithoutParams)
|
||||
|
||||
CARBON_PARSE_NODE_KIND(ExportIntroducer)
|
||||
CARBON_PARSE_NODE_KIND(ExportDecl)
|
||||
|
||||
@@ -36,26 +36,6 @@ fn foo(a: i32, b: i32);
|
||||
|
||||
fn foo() -> u32;
|
||||
|
||||
// --- keyword.carbon
|
||||
|
||||
fn destroy() {}
|
||||
|
||||
// --- keyword_no_params.carbon
|
||||
|
||||
fn destroy {}
|
||||
|
||||
// --- keyword_in_qualified.carbon
|
||||
|
||||
fn MyClass.destroy() {}
|
||||
|
||||
// --- keyword_decl_qualified_no_params.carbon
|
||||
|
||||
fn destroy.Foo() {}
|
||||
|
||||
// --- keyword_decl_qualified_with_params.carbon
|
||||
|
||||
fn destroy[self: Self]().Foo() {}
|
||||
|
||||
// --- impl_fn.carbon
|
||||
|
||||
override fn F();
|
||||
@@ -276,72 +256,6 @@ fn (a tokens c d e f g h i j k l m n o p q r s t u v w x y z);
|
||||
// CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 6},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword_no_params.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameNotBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 4},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword_in_qualified.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameNotBeforeParams', text: 'MyClass'},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 8},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword_decl_qualified_no_params.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameNotBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameQualifierWithoutParams', text: '.', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'Foo'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 7},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 8},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: keyword_decl_qualified_with_params.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameBeforeParams', text: 'destroy'},
|
||||
// CHECK:STDOUT: {kind: 'ImplicitParamListStart', text: '['},
|
||||
// CHECK:STDOUT: {kind: 'SelfValueName', text: 'self'},
|
||||
// CHECK:STDOUT: {kind: 'SelfTypeNameExpr', text: 'Self'},
|
||||
// CHECK:STDOUT: {kind: 'LetBindingPattern', text: ':', subtree_size: 3},
|
||||
// CHECK:STDOUT: {kind: 'ImplicitParamList', text: ']', subtree_size: 5},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'KeywordNameQualifierWithParams', text: '.', subtree_size: 9},
|
||||
// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'Foo'},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('},
|
||||
// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinitionStart', text: '{', subtree_size: 14},
|
||||
// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 15},
|
||||
// CHECK:STDOUT: {kind: 'FileEnd', text: ''},
|
||||
// CHECK:STDOUT: ]
|
||||
// CHECK:STDOUT: - filename: impl_fn.carbon
|
||||
// CHECK:STDOUT: parse_tree: [
|
||||
// CHECK:STDOUT: {kind: 'FileStart', text: ''},
|
||||
|
||||
@@ -132,18 +132,12 @@ using EmptyDecl =
|
||||
using IdentifierNameBeforeParams =
|
||||
LeafNode<NodeKind::IdentifierNameBeforeParams, Lex::IdentifierTokenIndex,
|
||||
NodeCategory::MemberName | NodeCategory::NonExprName>;
|
||||
using KeywordNameBeforeParams =
|
||||
LeafNode<NodeKind::KeywordNameBeforeParams, Lex::TokenIndex,
|
||||
NodeCategory::MemberName | NodeCategory::NonExprName>;
|
||||
|
||||
// A name in a non-expression context, such as a declaration, that is known
|
||||
// to not be followed by parameters.
|
||||
using IdentifierNameNotBeforeParams =
|
||||
LeafNode<NodeKind::IdentifierNameNotBeforeParams, Lex::IdentifierTokenIndex,
|
||||
NodeCategory::MemberName | NodeCategory::NonExprName>;
|
||||
using KeywordNameNotBeforeParams =
|
||||
LeafNode<NodeKind::KeywordNameNotBeforeParams, Lex::TokenIndex,
|
||||
NodeCategory::MemberName | NodeCategory::NonExprName>;
|
||||
|
||||
// A name in an expression context.
|
||||
using IdentifierNameExpr =
|
||||
@@ -184,15 +178,6 @@ struct IdentifierNameQualifierWithParams {
|
||||
std::optional<ExplicitParamListId> params;
|
||||
Lex::PeriodTokenIndex token;
|
||||
};
|
||||
struct KeywordNameQualifierWithParams {
|
||||
static constexpr auto Kind = NodeKind::KeywordNameQualifierWithParams.Define(
|
||||
{.bracketed_by = KeywordNameBeforeParams::Kind});
|
||||
|
||||
KeywordNameBeforeParamsId name;
|
||||
std::optional<ImplicitParamListId> implicit_params;
|
||||
std::optional<ExplicitParamListId> params;
|
||||
Lex::PeriodTokenIndex token;
|
||||
};
|
||||
|
||||
// A name qualifier without parameters, such as `A.`.
|
||||
struct IdentifierNameQualifierWithoutParams {
|
||||
@@ -203,21 +188,12 @@ struct IdentifierNameQualifierWithoutParams {
|
||||
IdentifierNameNotBeforeParamsId name;
|
||||
Lex::PeriodTokenIndex token;
|
||||
};
|
||||
struct KeywordNameQualifierWithoutParams {
|
||||
static constexpr auto Kind =
|
||||
NodeKind::KeywordNameQualifierWithoutParams.Define(
|
||||
{.bracketed_by = KeywordNameNotBeforeParams::Kind});
|
||||
|
||||
KeywordNameNotBeforeParamsId name;
|
||||
Lex::PeriodTokenIndex token;
|
||||
};
|
||||
|
||||
// A complete name in a declaration: `A.C(T:! type).F(n: i32)`.
|
||||
// Note that this includes the parameters of the entity itself.
|
||||
struct DeclName {
|
||||
llvm::SmallVector<NodeIdOneOf<
|
||||
IdentifierNameQualifierWithParams, IdentifierNameQualifierWithoutParams,
|
||||
KeywordNameQualifierWithParams, KeywordNameQualifierWithoutParams>>
|
||||
llvm::SmallVector<NodeIdOneOf<IdentifierNameQualifierWithParams,
|
||||
IdentifierNameQualifierWithoutParams>>
|
||||
qualifiers;
|
||||
AnyNonExprNameId name;
|
||||
std::optional<ImplicitParamListId> implicit_params;
|
||||
|
||||
@@ -293,8 +293,8 @@ NodeIdForKind error: wrong kind IdentifierNameBeforeParams, expected ImplicitPar
|
||||
Optional [^:]*: missing
|
||||
NodeIdInCategory NonExprName: kind IdentifierNameBeforeParams consumed
|
||||
Vector: begin
|
||||
NodeIdOneOf IdentifierNameQualifierWithParams or IdentifierNameQualifierWithoutParams or KeywordNameQualifierWithParams or KeywordNameQualifierWithoutParams: IdentifierNameQualifierWithoutParams consumed
|
||||
NodeIdOneOf error: wrong kind AbstractModifier, expected IdentifierNameQualifierWithParams or IdentifierNameQualifierWithoutParams or KeywordNameQualifierWithParams or KeywordNameQualifierWithoutParams
|
||||
NodeIdOneOf IdentifierNameQualifierWithParams or IdentifierNameQualifierWithoutParams: IdentifierNameQualifierWithoutParams consumed
|
||||
NodeIdOneOf error: wrong kind AbstractModifier, expected IdentifierNameQualifierWithParams or IdentifierNameQualifierWithoutParams
|
||||
Vector: end
|
||||
Aggregate [^:]*: success
|
||||
Vector: begin
|
||||
|
||||
@@ -566,8 +566,6 @@ constexpr FloatKind FloatKind::PPCFloat128 = FloatKind(6);
|
||||
X(ChoiceDiscriminant) \
|
||||
/* The name of the package `Core`. */ \
|
||||
X(Core) \
|
||||
/* The name of `destroy`. */ \
|
||||
X(Destroy) \
|
||||
/* The name of `package`. */ \
|
||||
X(PackageNamespace) \
|
||||
/* The name of `.Self`. */ \
|
||||
|
||||
@@ -23,8 +23,6 @@ static auto GetSpecialName(NameId name_id, bool for_ir) -> llvm::StringRef {
|
||||
return "discriminant";
|
||||
case NameId::SpecialNameId::Core:
|
||||
return "Core";
|
||||
case NameId::SpecialNameId::Destroy:
|
||||
return "destroy";
|
||||
case NameId::SpecialNameId::PackageNamespace:
|
||||
return "package";
|
||||
case NameId::SpecialNameId::PeriodSelf:
|
||||
|
||||
@@ -12,8 +12,8 @@ package Core library "prelude/parts/destroy";
|
||||
import library "prelude/parts/bool";
|
||||
import library "prelude/parts/int_literal";
|
||||
|
||||
// Object destruction, including running `fn destroy()`. Note this is distinct
|
||||
// from memory deallocation.
|
||||
// Destroys objects. Note this is distinct from memory deallocation.
|
||||
// TODO: Switch to `Destructor`+`Destroy` model.
|
||||
interface Destroy {
|
||||
fn Op[addr self: Self*]();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user