diff --git a/core/prelude/destroy.carbon b/core/prelude/destroy.carbon index 7205bf2f7a8c..7592cdea83b3 100644 --- a/core/prelude/destroy.carbon +++ b/core/prelude/destroy.carbon @@ -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*](); } diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 57f847545634..a40903d10b26 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -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 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()) { - 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, diff --git a/toolchain/check/handle_name.cpp b/toolchain/check/handle_name.cpp index 4570bf3cf863..dda49800a941 100644 --- a/toolchain/check/handle_name.cpp +++ b/toolchain/check/handle_name.cpp @@ -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 - 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(); diff --git a/toolchain/check/node_stack.h b/toolchain/check/node_stack.h index a4cd5dad8210..9480c2e56a62 100644 --- a/toolchain/check/node_stack.h +++ b/toolchain/check/node_stack.h @@ -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: diff --git a/toolchain/check/scope_stack.h b/toolchain/check/scope_stack.h index 5cd63cf2a709..52c9cfc5e551 100644 --- a/toolchain/check/scope_stack.h +++ b/toolchain/check/scope_stack.h @@ -295,8 +295,8 @@ class ScopeStack { // A stack for scope context. llvm::SmallVector 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 destroy_id_stack_; // Information about non-lexical scopes. This is a subset of the entries and diff --git a/toolchain/check/testdata/class/destroy_calls.carbon b/toolchain/check/testdata/class/destroy_calls.carbon index 65c80f4caf58..b67cc5d28581 100644 --- a/toolchain/check/testdata/class/destroy_calls.carbon +++ b/toolchain/check/testdata/class/destroy_calls.carbon @@ -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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %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 %.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 %.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 %.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 %.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 %.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 %.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: diff --git a/toolchain/check/testdata/class/destroy_decl.carbon b/toolchain/check/testdata/class/destroy_decl.carbon deleted file mode 100644 index ddd71298a8e2..000000000000 --- a/toolchain/check/testdata/class/destroy_decl.carbon +++ /dev/null @@ -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 -> (); -} diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 9cc709bdb6c3..924b870ba8d4 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -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) diff --git a/toolchain/lex/token_kind.def b/toolchain/lex/token_kind.def index 6a37779388df..bc124d51b083 100644 --- a/toolchain/lex/token_kind.def +++ b/toolchain/lex/token_kind.def @@ -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") diff --git a/toolchain/lower/testdata/function/definition/destroy.carbon b/toolchain/lower/testdata/function/definition/destroy.carbon index e4a953d087e0..de0c4dfaa912 100644 --- a/toolchain/lower/testdata/function/definition/destroy.carbon +++ b/toolchain/lower/testdata/function/definition/destroy.carbon @@ -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](); } diff --git a/toolchain/parse/handle_decl_name_and_params.cpp b/toolchain/parse/handle_decl_name_and_params.cpp index 6547d6a0c60e..092c5cc7b829 100644 --- a/toolchain/parse/handle_decl_name_and_params.cpp +++ b/toolchain/parse/handle_decl_name_and_params.cpp @@ -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); } } diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index 68520bab022a..2f117bd3652d 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -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) diff --git a/toolchain/parse/testdata/function/declaration.carbon b/toolchain/parse/testdata/function/declaration.carbon index b6f4a41b7276..b49e48d1e8ee 100644 --- a/toolchain/parse/testdata/function/declaration.carbon +++ b/toolchain/parse/testdata/function/declaration.carbon @@ -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: ''}, diff --git a/toolchain/parse/typed_nodes.h b/toolchain/parse/typed_nodes.h index 13273eb4b22f..d7790bdb707f 100644 --- a/toolchain/parse/typed_nodes.h +++ b/toolchain/parse/typed_nodes.h @@ -132,18 +132,12 @@ using EmptyDecl = using IdentifierNameBeforeParams = LeafNode; -using KeywordNameBeforeParams = - LeafNode; // A name in a non-expression context, such as a declaration, that is known // to not be followed by parameters. using IdentifierNameNotBeforeParams = LeafNode; -using KeywordNameNotBeforeParams = - LeafNode; // A name in an expression context. using IdentifierNameExpr = @@ -184,15 +178,6 @@ struct IdentifierNameQualifierWithParams { std::optional params; Lex::PeriodTokenIndex token; }; -struct KeywordNameQualifierWithParams { - static constexpr auto Kind = NodeKind::KeywordNameQualifierWithParams.Define( - {.bracketed_by = KeywordNameBeforeParams::Kind}); - - KeywordNameBeforeParamsId name; - std::optional implicit_params; - std::optional 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> + llvm::SmallVector> qualifiers; AnyNonExprNameId name; std::optional implicit_params; diff --git a/toolchain/parse/typed_nodes_test.cpp b/toolchain/parse/typed_nodes_test.cpp index 96dc4634b903..fcfe2820c7c2 100644 --- a/toolchain/parse/typed_nodes_test.cpp +++ b/toolchain/parse/typed_nodes_test.cpp @@ -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 diff --git a/toolchain/sem_ir/ids.h b/toolchain/sem_ir/ids.h index 70b9130fb036..99bdb5ceac24 100644 --- a/toolchain/sem_ir/ids.h +++ b/toolchain/sem_ir/ids.h @@ -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`. */ \ diff --git a/toolchain/sem_ir/name.cpp b/toolchain/sem_ir/name.cpp index 1c58cbf78664..37bb66fd96b4 100644 --- a/toolchain/sem_ir/name.cpp +++ b/toolchain/sem_ir/name.cpp @@ -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: diff --git a/toolchain/testing/testdata/min_prelude/parts/destroy.carbon b/toolchain/testing/testdata/min_prelude/parts/destroy.carbon index 2c9cced5ccc1..fb2804cf78f6 100644 --- a/toolchain/testing/testdata/min_prelude/parts/destroy.carbon +++ b/toolchain/testing/testdata/min_prelude/parts/destroy.carbon @@ -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*](); }