diff --git a/docs/design/classes.md b/docs/design/classes.md index da0a61e1f49a..736fb961eb39 100644 --- a/docs/design/classes.md +++ b/docs/design/classes.md @@ -1237,21 +1237,20 @@ There are three virtual modifier keywords: virtual" but is called ["pure virtual" in C++](https://en.wikipedia.org/wiki/Virtual_function#Abstract_classes_and_pure_virtual_functions). Only abstract classes may have unimplemented abstract methods. -- `impl` - This marks a method that overrides a method marked `virtual` or +- `override` - This marks a method that overrides a method marked `virtual` or `abstract` in the base class with an implementation specific to -- and defined within -- this class. The method is still virtual and may be overridden again in subsequent derived classes if this is a base class. See [method overriding in Wikipedia](https://en.wikipedia.org/wiki/Method_overriding). Requiring a keyword when overriding allows the compiler to diagnose when the derived class accidentally uses the wrong signature or spelling and so - doesn't match the base class. We intentionally use the same keyword here as - for implementing interfaces, to emphasize that they are similar operations. + doesn't match the base class. -| Keyword on
method in `C` | Allowed in
`abstract class C` | Allowed in
`base class C` | Allowed in
final `class C` | in `B` where
`C` extends `B` | in `D` where
`D` extends `C` | -| ----------------------------- | ---------------------------------- | ------------------------------ | ------------------------------- | -------------------------------------------------------- | -------------------------------------------------------------------------------- | -| `virtual` | ✅ | ✅ | ❌ | _not present_ | `abstract`
`impl`
_not mentioned_ | -| `abstract` | ✅ | ❌ | ❌ | _not present_
`virtual`
`abstract`
`impl` | `abstract`
`impl`
_may not be
mentioned if
`D` is not final_ | -| `impl` | ✅ | ✅ | ✅ | `virtual`
`abstract`
`impl` | `abstract`
`impl` | +| Keyword on
method in `C` | Allowed in
`abstract class C` | Allowed in
`base class C` | Allowed in
final `class C` | in `B` where
`C` extends `B` | in `D` where
`D` extends `C` | +| ----------------------------- | ---------------------------------- | ------------------------------ | ------------------------------- | ------------------------------------------------------------ | ------------------------------------------------------------------------------------ | +| `virtual` | ✅ | ✅ | ❌ | _not present_ | `abstract`
`override`
_not mentioned_ | +| `abstract` | ✅ | ❌ | ❌ | _not present_
`virtual`
`abstract`
`override` | `abstract`
`override`
_may not be
mentioned if
`D` is not final_ | +| `override` | ✅ | ✅ | ✅ | `virtual`
`abstract`
`override` | `abstract`
`override` | Since validating a method with a virtual modifier keyword involves looking for methods with the same name in the base class, virtual methods must be declared @@ -1315,15 +1314,15 @@ base class B1 { class D1 { extend base: B1; // ❌ Illegal: - // impl fn F[self: Self](x: Self) -> Self; + // override fn F[self: Self](x: Self) -> Self; // since that would mean the same thing as: - // impl fn F[self: Self](x: D1) -> D1; + // override fn F[self: Self](x: D1) -> D1; // and `D1` is a different type than `B1`. // ✅ Allowed: Parameter and return types // of `F` match declaration in `B1`. - impl fn F[self: Self](x: B1) -> B1; - // Or: impl fn F[self: D1](x: B1) -> B1; + override fn F[self: Self](x: B1) -> B1; + // Or: override fn F[self: D1](x: B1) -> B1; } ``` @@ -1341,9 +1340,9 @@ base class B2 { class D2 { extend base: B2; // ✅ Allowed - impl fn Clone[self: Self]() -> Self*; + override fn Clone[self: Self]() -> Self*; // Means the same thing as: - // impl fn Clone[self: D2]() -> D2*; + // override fn Clone[self: D2]() -> D2*; // which is allowed since `D2*` is a // subtype of `B2*`. } @@ -1615,7 +1614,7 @@ of its base classes unless it has a [virtual destructor](https://en.wikipedia.org/wiki/Virtual_function#Virtual_destructors). An abstract or base class' destructor may be declared virtual using the `virtual` introducer, in which case any derived class destructor declaration -must be `impl`: +must be `override`: ```carbon base class MyBaseClass { @@ -1624,7 +1623,7 @@ base class MyBaseClass { class MyDerivedClass { extend base: MyBaseClass; - impl fn destroy[addr self: Self*]() { ... } + override fn destroy[addr self: Self*]() { ... } } ``` @@ -2298,6 +2297,8 @@ the type of `U.x`." - [Destructor syntax options](/proposals/p5017.md#destructor-syntax-options) - [Destructor name options](/proposals/p5017.md#destructor-name-options) +- [#6008: Replace `impl fn` with `override fn`](https://github.com/carbon-language/carbon-lang/pull/6008) + ## References - [#257: Initialization of memory and variables](https://github.com/carbon-language/carbon-lang/pull/257) diff --git a/proposals/p6008.md b/proposals/p6008.md new file mode 100644 index 000000000000..575801e1a204 --- /dev/null +++ b/proposals/p6008.md @@ -0,0 +1,57 @@ +# Replace `impl fn` with `override fn` + + + +[Pull request](https://github.com/carbon-language/carbon-lang/pull/6008) + + + +## Table of contents + +- [Abstract](#abstract) +- [Problem](#problem) +- [Background](#background) +- [Proposal](#proposal) +- [Rationale](#rationale) + + + +## Abstract + +This proposal renames the syntax used to mark an overriding definition of a +virtual method from `impl fn` to `override fn` to avoid ambiguity. + +## Problem + +The phrase `impl fn` was introduced to mark overriding virtual functions, +however, it is now ambiguous: besides indicating an overriding virtual function, +it can be parsed as an "impl" declaration when the construct following "impl" +begins with a lambda introduced by "fn". + +## Background + +The original syntax was adopted in +[proposal #777](https://github.com/carbon-language/carbon-lang/pull/777) to +emphasize that implementing interfaces and overriding virtual functions are +similar operations. + +## Proposal + +This proposal is to replace the `impl fn` syntax with `override fn` for method +overriding in class inheritance. + +Note that `impl` is still a modifier keyword for library and package +declarations (`impl library ...` and `impl package ...` respectively). The +former is unambiguous and the latter is easy to disambiguate, so no change is +needed for these two cases. + +## Rationale + +This proposal is focused on the +[That code is easy to read, understand, and write](/docs/project/goals.md#code-that-is-easy-to-read-understand-and-write) +Carbon goal. Changing the keyword from `impl` to `override` makes the intent +clearer, resolves syntax ambiguity, and adheres to existing C++ conventions. diff --git a/toolchain/check/class.cpp b/toolchain/check/class.cpp index 7a03c925e51a..3d07f6c461e2 100644 --- a/toolchain/check/class.cpp +++ b/toolchain/check/class.cpp @@ -199,7 +199,7 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id, .GetAs(override_fn_decl_id) .function_id); return override_fn.virtual_modifier == - SemIR::FunctionFields::VirtualModifier::Impl && + SemIR::FunctionFields::VirtualModifier::Override && override_fn.name_id == fn.name_id; }); if (i != vtable_contents.end()) { @@ -237,13 +237,15 @@ static auto BuildVtable(Context& context, Parse::ClassDefinitionId node_id, for (auto inst_id : vtable_contents) { auto fn_decl = context.insts().GetAs(inst_id); auto& fn = context.functions().Get(fn_decl.function_id); - if (fn.virtual_modifier != SemIR::FunctionFields::VirtualModifier::Impl) { + if (fn.virtual_modifier != + SemIR::FunctionFields::VirtualModifier::Override) { fn.virtual_index = vtable.size(); vtable.push_back(build_specific_function(inst_id)); } else if (!implemented_impls.Lookup(fn_decl.function_id)) { - CARBON_DIAGNOSTIC(ImplWithoutVirtualInBase, Error, - "impl without compatible virtual in base class"); - context.emitter().Emit(SemIR::LocId(inst_id), ImplWithoutVirtualInBase); + CARBON_DIAGNOSTIC(OverrideWithoutVirtualInBase, Error, + "override without compatible virtual in base class"); + context.emitter().Emit(SemIR::LocId(inst_id), + OverrideWithoutVirtualInBase); } } diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index a2b4bd912961..57f847545634 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -128,7 +128,8 @@ static auto GetVirtualModifier(const KeywordModifierSet& modifier_set) SemIR::Function::VirtualModifier::Virtual) .Case(KeywordModifierSet::Abstract, SemIR::Function::VirtualModifier::Abstract) - .Case(KeywordModifierSet::Impl, SemIR::Function::VirtualModifier::Impl) + .Case(KeywordModifierSet::Override, + SemIR::Function::VirtualModifier::Override) .Default(SemIR::Function::VirtualModifier::None); } @@ -342,10 +343,11 @@ static auto RequestVtableIfVirtual( } auto& class_info = context.classes().Get(class_decl->class_id); - if (virtual_modifier == SemIR::Function::VirtualModifier::Impl && + if (virtual_modifier == SemIR::Function::VirtualModifier::Override && !class_info.base_id.has_value()) { - CARBON_DIAGNOSTIC(ImplWithoutBase, Error, "impl without base class"); - context.emitter().Emit(node_id, ImplWithoutBase); + CARBON_DIAGNOSTIC(OverrideWithoutBase, Error, + "override without base class"); + context.emitter().Emit(node_id, OverrideWithoutBase); virtual_modifier = SemIR::Function::VirtualModifier::None; return; } diff --git a/toolchain/check/keyword_modifier_set.h b/toolchain/check/keyword_modifier_set.h index bfabe5625f79..a8c4f39196ae 100644 --- a/toolchain/check/keyword_modifier_set.h +++ b/toolchain/check/keyword_modifier_set.h @@ -38,6 +38,7 @@ enum class ModifierOrder : int8_t { Access, Extern, Extend, Decl, Last = Decl }; X(Export) \ X(Final) \ X(Impl) \ + X(Override) \ X(Returned) \ X(Virtual) @@ -113,11 +114,11 @@ CARBON_KEYWORD_MODIFIER_SET(CARBON_KEYWORD_MODIFIER_SET_WITH_TYPE) constexpr KeywordModifierSet KeywordModifierSet::Access(Private | Protected); constexpr KeywordModifierSet KeywordModifierSet::Class(Abstract | Base); -constexpr KeywordModifierSet KeywordModifierSet::Method(Abstract | Impl | +constexpr KeywordModifierSet KeywordModifierSet::Method(Abstract | Override | Virtual); constexpr KeywordModifierSet KeywordModifierSet::ImplDecl(Extend | Final); constexpr KeywordModifierSet KeywordModifierSet::Interface(Default | Final); -constexpr KeywordModifierSet KeywordModifierSet::Decl(Class | Method | +constexpr KeywordModifierSet KeywordModifierSet::Decl(Class | Method | Impl | Interface | Export | Returned); diff --git a/toolchain/check/testdata/class/virtual_modifiers.carbon b/toolchain/check/testdata/class/virtual_modifiers.carbon index 54cc4b098547..287778cd291b 100644 --- a/toolchain/check/testdata/class/virtual_modifiers.carbon +++ b/toolchain/check/testdata/class/virtual_modifiers.carbon @@ -34,7 +34,7 @@ import Modifiers; class Derived { extend base: Modifiers.Base; - impl fn H[self: Self](); + override fn H[self: Self](); } fn Use() { @@ -72,7 +72,7 @@ abstract class A1 { abstract class A2 { extend base: A1; - impl fn F[self: Self](); + override fn F[self: Self](); } // --- impl_base.carbon @@ -85,12 +85,12 @@ base class B1 { base class B2 { extend base: B1; - impl fn F[self: Self](); + override fn F[self: Self](); } class C { extend base: B2; - impl fn F[self: Self](); + override fn F[self: Self](); } fn Use() { @@ -104,11 +104,11 @@ fn Use() { library "[[@TEST_NAME]]"; class C { - // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:3: error: impl without base class [ImplWithoutBase] - // CHECK:STDERR: impl fn F[self: Self](); - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_modifiers.carbon:[[@LINE+4]]:3: error: override without base class [OverrideWithoutBase] + // CHECK:STDERR: override fn F[self: Self](); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: - impl fn F[self: Self](); + override fn F[self: Self](); } // --- init_members.carbon @@ -139,11 +139,11 @@ base class Base { class Derived { extend base: Base; - // CHECK:STDERR: fail_impl_without_base_declaration.carbon:[[@LINE+4]]:3: error: impl without compatible virtual in base class [ImplWithoutVirtualInBase] - // CHECK:STDERR: impl fn F[self: Self](); - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_impl_without_base_declaration.carbon:[[@LINE+4]]:3: error: override without compatible virtual in base class [OverrideWithoutVirtualInBase] + // CHECK:STDERR: override fn F[self: Self](); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: - impl fn F[self: Self](); + override fn F[self: Self](); } // --- abstract_impl.carbon @@ -160,7 +160,7 @@ abstract class AbstractIntermediate { class Derived { extend base: AbstractIntermediate; - impl fn F[self: Self](); + override fn F[self: Self](); } // --- virtual_impl.carbon @@ -177,7 +177,7 @@ base class VirtualIntermediate { class Derived { extend base: VirtualIntermediate; - impl fn F[self: Self](); + override fn F[self: Self](); } // --- fail_impl_mismatch.carbon @@ -191,13 +191,13 @@ base class Base { class Derived { extend base: Base; // CHECK:STDERR: fail_impl_mismatch.carbon:[[@LINE+7]]:3: error: redeclaration differs because of parameter count of 1 [RedeclParamCountDiffers] - // CHECK:STDERR: impl fn F[self: Self](v: i32); - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: override fn F[self: Self](v: i32); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_impl_mismatch.carbon:[[@LINE-8]]:3: note: previously declared with parameter count of 0 [RedeclParamCountPrevious] // CHECK:STDERR: virtual fn F[self: Self](); // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: - impl fn F[self: Self](v: i32); + override fn F[self: Self](v: i32); } // --- fail_todo_impl_conversion.carbon @@ -223,13 +223,13 @@ base class Base { class Derived { extend base: Base; // CHECK:STDERR: fail_todo_impl_conversion.carbon:[[@LINE+7]]:3: error: function redeclaration differs because return type is `T2` [FunctionRedeclReturnTypeDiffers] - // CHECK:STDERR: impl fn F[self: Self]() -> T2; - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: override fn F[self: Self]() -> T2; + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_todo_impl_conversion.carbon:[[@LINE-8]]:3: note: previously declared with return type `T1` [FunctionRedeclReturnTypePrevious] // CHECK:STDERR: virtual fn F[self: Self]() -> T1; // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: - impl fn F[self: Self]() -> T2; + override fn F[self: Self]() -> T2; } // --- fail_generic_virtual_decl.carbon @@ -261,7 +261,7 @@ base class Base(T:! type) { class Derived { extend base: Base(T1); - impl fn F[self: Self](t: T1) { } + override fn F[self: Self](t: T1) { } } // --- fail_virtual_without_self.carbon @@ -284,10 +284,10 @@ abstract class T1 { class T2 { extend base: T1; // CHECK:STDERR: fail_virtual_without_self.carbon:[[@LINE+4]]:3: error: virtual class function [VirtualWithoutSelf] - // CHECK:STDERR: impl fn F(); - // CHECK:STDERR: ^~~~~~~~~~~~ + // CHECK:STDERR: override fn F(); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~ // CHECK:STDERR: - impl fn F(); + override fn F(); } // --- fail_addr_self_mismatch.carbon @@ -300,14 +300,14 @@ base class T1 { class T2 { extend base: T1; - // CHECK:STDERR: fail_addr_self_mismatch.carbon:[[@LINE+7]]:14: error: redeclaration differs at implicit parameter 1 [RedeclParamDiffers] - // CHECK:STDERR: impl fn F1[addr self: Self*](); - // CHECK:STDERR: ^~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_addr_self_mismatch.carbon:[[@LINE+7]]:18: error: redeclaration differs at implicit parameter 1 [RedeclParamDiffers] + // CHECK:STDERR: override fn F1[addr self: Self*](); + // CHECK:STDERR: ^~~~~~~~~~~~~~~~ // CHECK:STDERR: fail_addr_self_mismatch.carbon:[[@LINE-8]]:17: note: previous declaration's corresponding implicit parameter here [RedeclParamPrevious] // CHECK:STDERR: virtual fn F1[self: Self*](); // CHECK:STDERR: ^~~~~~~~~~~ // CHECK:STDERR: - impl fn F1[addr self: Self*](); + override fn F1[addr self: Self*](); } // --- fail_generic_virtual.carbon @@ -369,7 +369,7 @@ base class NonGenericBase { base class GenericDerived(T:! type) { extend base: NonGenericBase; - impl fn F2[self: Self]() { } + override fn F2[self: Self]() { } virtual fn F3[self: Self]() { } } @@ -386,7 +386,7 @@ class T1; base class NonGenericDerived { extend base: GenericBase(T1); - impl fn F2[self: Self]() { } + override fn F2[self: Self]() { } virtual fn F3[self: Self]() { } } @@ -400,7 +400,7 @@ base class Base(T:! type) { class T1; class D1 { extend base: Base(T1); - impl fn F[self: Self](t: Base(T1)*) { } + override fn F[self: Self](t: Base(T1)*) { } } // --- fail_impl_generic_specifically_mismatch.carbon @@ -416,14 +416,14 @@ base class Base(T:! type) { class D1 { extend base: Base(T1); - // CHECK:STDERR: fail_impl_generic_specifically_mismatch.carbon:[[@LINE+7]]:25: error: type `` of parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] - // CHECK:STDERR: impl fn F[self: Self](t: T2*) { } - // CHECK:STDERR: ^~~~~~ + // CHECK:STDERR: fail_impl_generic_specifically_mismatch.carbon:[[@LINE+7]]:29: error: type `` of parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] + // CHECK:STDERR: override fn F[self: Self](t: T2*) { } + // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: fail_impl_generic_specifically_mismatch.carbon:[[@LINE-8]]:28: note: previous declaration's corresponding parameter here [RedeclParamPrevious] // CHECK:STDERR: virtual fn F[self: Self](t: T1*) { } // CHECK:STDERR: ^~~~~~ // CHECK:STDERR: - impl fn F[self: Self](t: T2*) { } + override fn F[self: Self](t: T2*) { } } // --- fail_impl_generic_generic_mismatch.carbon @@ -435,14 +435,14 @@ abstract class Base(T:! type) { } class Derived(T:! type) { extend base: Base(T); - // CHECK:STDERR: fail_impl_generic_generic_mismatch.carbon:[[@LINE+7]]:25: error: type `` of parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] - // CHECK:STDERR: impl fn F[self: Self](t: T) { } - // CHECK:STDERR: ^~~~ + // CHECK:STDERR: fail_impl_generic_generic_mismatch.carbon:[[@LINE+7]]:29: error: type `` of parameter 1 in redeclaration differs from previous parameter type `` [RedeclParamDiffersType] + // CHECK:STDERR: override fn F[self: Self](t: T) { } + // CHECK:STDERR: ^~~~ // CHECK:STDERR: fail_impl_generic_generic_mismatch.carbon:[[@LINE-7]]:28: note: previous declaration's corresponding parameter here [RedeclParamPrevious] // CHECK:STDERR: virtual fn F[self: Self](t: T*) { } // CHECK:STDERR: ^~~~~ // CHECK:STDERR: - impl fn F[self: Self](t: T) { } + override fn F[self: Self](t: T) { } } // --- impl_generic_generic.carbon @@ -454,7 +454,7 @@ abstract class Base(T:! type) { } class Derived(T:! type) { extend base: Base(T*); - impl fn F[self: Self](t: T*) { } + override fn F[self: Self](t: T*) { } } // --- abstract_generic_undefined.carbon @@ -469,7 +469,7 @@ class T1; class Derived { extend base: Base(T1); - impl fn F[self: Self]() { } + override fn F[self: Self]() { } } // --- generic_lib.carbon @@ -802,7 +802,7 @@ class T2(G2:! type) { // CHECK:STDOUT: @Derived.%Derived.H.decl // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @Derived.H(%self.param: %Derived); +// CHECK:STDOUT: override fn @Derived.H(%self.param: %Derived); // CHECK:STDOUT: // CHECK:STDOUT: fn @Derived.as.Destroy.impl.Op(%self.param: %ptr.404) = "no_op"; // CHECK:STDOUT: @@ -1236,7 +1236,7 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @A1.as.Destroy.impl.Op(%self.param: %ptr.678) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @A2.F(%self.param: %A2); +// CHECK:STDOUT: override fn @A2.F(%self.param: %A2); // CHECK:STDOUT: // CHECK:STDOUT: fn @A2.as.Destroy.impl.Op(%self.param: %ptr.590) = "no_op"; // CHECK:STDOUT: @@ -1468,11 +1468,11 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @B1.as.Destroy.impl.Op(%self.param: %ptr.890) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @B2.F(%self.param: %B2); +// CHECK:STDOUT: override fn @B2.F(%self.param: %B2); // CHECK:STDOUT: // CHECK:STDOUT: fn @B2.as.Destroy.impl.Op(%self.param: %ptr.afe) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @C.F(%self.param: %C); +// CHECK:STDOUT: override fn @C.F(%self.param: %C); // CHECK:STDOUT: // CHECK:STDOUT: fn @C.as.Destroy.impl.Op(%self.param: %ptr.019) = "no_op"; // CHECK:STDOUT: @@ -1617,7 +1617,7 @@ class T2(G2:! type) { // CHECK:STDOUT: .F = %C.F.decl // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @C.F(%self.param: %C); +// CHECK:STDOUT: override fn @C.F(%self.param: %C); // CHECK:STDOUT: // CHECK:STDOUT: fn @C.as.Destroy.impl.Op(%self.param: %ptr.019) = "no_op"; // CHECK:STDOUT: @@ -2013,7 +2013,7 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @Base.as.Destroy.impl.Op(%self.param: %ptr.11f) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @Derived.F(%self.param: %Derived); +// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived); // CHECK:STDOUT: // CHECK:STDOUT: fn @Derived.as.Destroy.impl.Op(%self.param: %ptr.404) = "no_op"; // CHECK:STDOUT: @@ -2218,7 +2218,7 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @AbstractIntermediate.as.Destroy.impl.Op(%self.param: %ptr.fd8) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @Derived.F(%self.param: %Derived); +// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived); // CHECK:STDOUT: // CHECK:STDOUT: fn @Derived.as.Destroy.impl.Op(%self.param: %ptr.404) = "no_op"; // CHECK:STDOUT: @@ -2423,7 +2423,7 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @VirtualIntermediate.as.Destroy.impl.Op(%self.param: %ptr.7dc) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @Derived.F(%self.param: %Derived); +// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived); // CHECK:STDOUT: // CHECK:STDOUT: fn @Derived.as.Destroy.impl.Op(%self.param: %ptr.404) = "no_op"; // CHECK:STDOUT: @@ -2590,7 +2590,7 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @Base.as.Destroy.impl.Op(%self.param: %ptr.11f) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @Derived.F(%self.param: %Derived, %v.param: %i32); +// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived, %v.param: %i32); // CHECK:STDOUT: // CHECK:STDOUT: fn @Derived.as.Destroy.impl.Op(%self.param: %ptr.404) = "no_op"; // CHECK:STDOUT: @@ -2882,7 +2882,7 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @Base.as.Destroy.impl.Op(%self.param: %ptr.11f) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @Derived.F(%self.param: %Derived) -> %return.param: %T2; +// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived) -> %return.param: %T2; // CHECK:STDOUT: // CHECK:STDOUT: fn @Derived.as.Destroy.impl.Op(%self.param: %ptr.404) = "no_op"; // CHECK:STDOUT: @@ -3320,7 +3320,7 @@ class T2(G2:! type) { // CHECK:STDOUT: fn(%self.param: @Base.as.Destroy.impl.Op.%ptr (%ptr.b7c)) = "no_op"; // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @Derived.F(%self.param: %Derived, %t.param: %T1) { +// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived, %t.param: %T1) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -3622,10 +3622,10 @@ class T2(G2:! type) { // CHECK:STDOUT: %T2.F1.decl: %T2.F1.type = fn_decl @T2.F1 [concrete = constants.%T2.F1] { // CHECK:STDOUT: %self.patt: %pattern_type.fb8 = binding_pattern self [concrete] // CHECK:STDOUT: %self.param_patt: %pattern_type.fb8 = value_param_pattern %self.patt, call_param0 [concrete] -// CHECK:STDOUT: %.loc17_14: %pattern_type.f6d = addr_pattern %self.param_patt [concrete] +// CHECK:STDOUT: %.loc17_18: %pattern_type.f6d = addr_pattern %self.param_patt [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: %ptr.63e = value_param call_param0 -// CHECK:STDOUT: %.loc17_29: type = splice_block %ptr [concrete = constants.%ptr.63e] { +// CHECK:STDOUT: %.loc17_33: type = splice_block %ptr [concrete = constants.%ptr.63e] { // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%T2 [concrete = constants.%T2] // CHECK:STDOUT: %ptr: type = ptr_type %Self.ref [concrete = constants.%ptr.63e] // CHECK:STDOUT: } @@ -3660,7 +3660,7 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @T1.as.Destroy.impl.Op(%self.param: %ptr.87b) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @T2.F1(%self.param: %ptr.63e); +// CHECK:STDOUT: override fn @T2.F1(%self.param: %ptr.63e); // CHECK:STDOUT: // CHECK:STDOUT: fn @T2.as.Destroy.impl.Op(%self.param: %ptr.63e) = "no_op"; // CHECK:STDOUT: @@ -4505,9 +4505,9 @@ class T2(G2:! type) { // CHECK:STDOUT: %self.param_patt: @GenericDerived.F2.%pattern_type (%pattern_type.061) = value_param_pattern %self.patt, call_param0 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: @GenericDerived.F2.%GenericDerived (%GenericDerived) = value_param call_param0 -// CHECK:STDOUT: %.loc11_20.1: type = splice_block %Self.ref [symbolic = %GenericDerived (constants.%GenericDerived)] { -// CHECK:STDOUT: %.loc11_20.2: type = specific_constant constants.%GenericDerived, @GenericDerived(constants.%T) [symbolic = %GenericDerived (constants.%GenericDerived)] -// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc11_20.2 [symbolic = %GenericDerived (constants.%GenericDerived)] +// CHECK:STDOUT: %.loc11_24.1: type = splice_block %Self.ref [symbolic = %GenericDerived (constants.%GenericDerived)] { +// CHECK:STDOUT: %.loc11_24.2: type = specific_constant constants.%GenericDerived, @GenericDerived(constants.%T) [symbolic = %GenericDerived (constants.%GenericDerived)] +// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc11_24.2 [symbolic = %GenericDerived (constants.%GenericDerived)] // CHECK:STDOUT: } // CHECK:STDOUT: %self: @GenericDerived.F2.%GenericDerived (%GenericDerived) = bind_name self, %self.param // CHECK:STDOUT: } @@ -4566,7 +4566,7 @@ class T2(G2:! type) { // CHECK:STDOUT: // CHECK:STDOUT: fn @NonGenericBase.as.Destroy.impl.Op(%self.param: %ptr.806) = "no_op"; // CHECK:STDOUT: -// CHECK:STDOUT: generic impl fn @GenericDerived.F2(@GenericDerived.%T.loc9_27.2: type) { +// CHECK:STDOUT: generic override fn @GenericDerived.F2(@GenericDerived.%T.loc9_27.2: type) { // CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %GenericDerived: type = class_type @GenericDerived, @GenericDerived(%T) [symbolic = %GenericDerived (constants.%GenericDerived)] // CHECK:STDOUT: %pattern_type: type = pattern_type %GenericDerived [symbolic = %pattern_type (constants.%pattern_type.061)] @@ -4574,7 +4574,7 @@ class T2(G2:! type) { // CHECK:STDOUT: !definition: // CHECK:STDOUT: %require_complete: = require_complete_type %GenericDerived [symbolic = %require_complete (constants.%require_complete)] // CHECK:STDOUT: -// CHECK:STDOUT: impl fn(%self.param: @GenericDerived.F2.%GenericDerived (%GenericDerived)) { +// CHECK:STDOUT: override fn(%self.param: @GenericDerived.F2.%GenericDerived (%GenericDerived)) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -4921,7 +4921,7 @@ class T2(G2:! type) { // CHECK:STDOUT: fn(%self.param: @GenericBase.as.Destroy.impl.Op.%ptr (%ptr.b68)) = "no_op"; // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @NonGenericDerived.F2(%self.param: %NonGenericDerived) { +// CHECK:STDOUT: override fn @NonGenericDerived.F2(%self.param: %NonGenericDerived) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -5257,7 +5257,7 @@ class T2(G2:! type) { // CHECK:STDOUT: fn(%self.param: @Base.as.Destroy.impl.Op.%ptr (%ptr.b7c)) = "no_op"; // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @D1.F(%self.param: %D1, %t.param: %ptr.184) { +// CHECK:STDOUT: override fn @D1.F(%self.param: %D1, %t.param: %ptr.184) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -5568,7 +5568,7 @@ class T2(G2:! type) { // CHECK:STDOUT: fn(%self.param: @Base.as.Destroy.impl.Op.%ptr (%ptr.b7c)) = "no_op"; // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @D1.F(%self.param: %D1, %t.param: %ptr.63e) { +// CHECK:STDOUT: override fn @D1.F(%self.param: %D1, %t.param: %ptr.63e) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -5827,15 +5827,15 @@ class T2(G2:! type) { // CHECK:STDOUT: %Base.loc8_22.1: type = class_type @Base, @Base(constants.%T) [symbolic = %Base.loc8_22.2 (constants.%Base)] // CHECK:STDOUT: %.loc8: @Derived.%Derived.elem (%Derived.elem) = base_decl %Base.loc8_22.1, element0 [concrete] // CHECK:STDOUT: %Derived.F.decl: @Derived.%Derived.F.type (%Derived.F.type) = fn_decl @Derived.F [symbolic = @Derived.%Derived.F (constants.%Derived.F)] { -// CHECK:STDOUT: %self.patt: @Derived.F.%pattern_type.loc16_13 (%pattern_type.423) = binding_pattern self [concrete] -// CHECK:STDOUT: %self.param_patt: @Derived.F.%pattern_type.loc16_13 (%pattern_type.423) = value_param_pattern %self.patt, call_param0 [concrete] -// CHECK:STDOUT: %t.patt: @Derived.F.%pattern_type.loc16_25 (%pattern_type.7dc) = binding_pattern t [concrete] -// CHECK:STDOUT: %t.param_patt: @Derived.F.%pattern_type.loc16_25 (%pattern_type.7dc) = value_param_pattern %t.patt, call_param1 [concrete] +// CHECK:STDOUT: %self.patt: @Derived.F.%pattern_type.loc16_17 (%pattern_type.423) = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: @Derived.F.%pattern_type.loc16_17 (%pattern_type.423) = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %t.patt: @Derived.F.%pattern_type.loc16_29 (%pattern_type.7dc) = binding_pattern t [concrete] +// CHECK:STDOUT: %t.param_patt: @Derived.F.%pattern_type.loc16_29 (%pattern_type.7dc) = value_param_pattern %t.patt, call_param1 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: @Derived.F.%Derived (%Derived) = value_param call_param0 -// CHECK:STDOUT: %.loc16_19.1: type = splice_block %Self.ref [symbolic = %Derived (constants.%Derived)] { -// CHECK:STDOUT: %.loc16_19.2: type = specific_constant constants.%Derived, @Derived(constants.%T) [symbolic = %Derived (constants.%Derived)] -// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc16_19.2 [symbolic = %Derived (constants.%Derived)] +// CHECK:STDOUT: %.loc16_23.1: type = splice_block %Self.ref [symbolic = %Derived (constants.%Derived)] { +// CHECK:STDOUT: %.loc16_23.2: type = specific_constant constants.%Derived, @Derived(constants.%T) [symbolic = %Derived (constants.%Derived)] +// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc16_23.2 [symbolic = %Derived (constants.%Derived)] // CHECK:STDOUT: } // CHECK:STDOUT: %self: @Derived.F.%Derived (%Derived) = bind_name self, %self.param // CHECK:STDOUT: %t.param: @Derived.F.%T (%T) = value_param call_param1 @@ -5898,19 +5898,19 @@ class T2(G2:! type) { // CHECK:STDOUT: fn(%self.param: @Base.as.Destroy.impl.Op.%ptr (%ptr.b7c)) = "no_op"; // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic impl fn @Derived.F(@Derived.%T.loc7_15.2: type) { +// CHECK:STDOUT: generic override fn @Derived.F(@Derived.%T.loc7_15.2: type) { // CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %Derived: type = class_type @Derived, @Derived(%T) [symbolic = %Derived (constants.%Derived)] -// CHECK:STDOUT: %pattern_type.loc16_13: type = pattern_type %Derived [symbolic = %pattern_type.loc16_13 (constants.%pattern_type.423)] +// CHECK:STDOUT: %pattern_type.loc16_17: type = pattern_type %Derived [symbolic = %pattern_type.loc16_17 (constants.%pattern_type.423)] // CHECK:STDOUT: %Base: type = class_type @Base, @Base(%T) [symbolic = %Base (constants.%Base)] -// CHECK:STDOUT: %require_complete.loc16_28: = require_complete_type %Base [symbolic = %require_complete.loc16_28 (constants.%require_complete.97d)] -// CHECK:STDOUT: %pattern_type.loc16_25: type = pattern_type %T [symbolic = %pattern_type.loc16_25 (constants.%pattern_type.7dc)] +// CHECK:STDOUT: %require_complete.loc16_32: = require_complete_type %Base [symbolic = %require_complete.loc16_32 (constants.%require_complete.97d)] +// CHECK:STDOUT: %pattern_type.loc16_29: type = pattern_type %T [symbolic = %pattern_type.loc16_29 (constants.%pattern_type.7dc)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: -// CHECK:STDOUT: %require_complete.loc16_17: = require_complete_type %Derived [symbolic = %require_complete.loc16_17 (constants.%require_complete.5f4)] -// CHECK:STDOUT: %require_complete.loc16_26: = require_complete_type %T [symbolic = %require_complete.loc16_26 (constants.%require_complete.4ae)] +// CHECK:STDOUT: %require_complete.loc16_21: = require_complete_type %Derived [symbolic = %require_complete.loc16_21 (constants.%require_complete.5f4)] +// CHECK:STDOUT: %require_complete.loc16_30: = require_complete_type %T [symbolic = %require_complete.loc16_30 (constants.%require_complete.4ae)] // CHECK:STDOUT: -// CHECK:STDOUT: impl fn(%self.param: @Derived.F.%Derived (%Derived), %t.param: @Derived.F.%T (%T)) { +// CHECK:STDOUT: override fn(%self.param: @Derived.F.%Derived (%Derived), %t.param: @Derived.F.%T (%T)) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -5979,14 +5979,14 @@ class T2(G2:! type) { // CHECK:STDOUT: specific @Derived.F(constants.%T) { // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: %Derived => constants.%Derived -// CHECK:STDOUT: %pattern_type.loc16_13 => constants.%pattern_type.423 +// CHECK:STDOUT: %pattern_type.loc16_17 => constants.%pattern_type.423 // CHECK:STDOUT: %Base => constants.%Base -// CHECK:STDOUT: %require_complete.loc16_28 => constants.%require_complete.97d -// CHECK:STDOUT: %pattern_type.loc16_25 => constants.%pattern_type.7dc +// CHECK:STDOUT: %require_complete.loc16_32 => constants.%require_complete.97d +// CHECK:STDOUT: %pattern_type.loc16_29 => constants.%pattern_type.7dc // CHECK:STDOUT: // CHECK:STDOUT: !definition: -// CHECK:STDOUT: %require_complete.loc16_17 => constants.%require_complete.5f4 -// CHECK:STDOUT: %require_complete.loc16_26 => constants.%require_complete.4ae +// CHECK:STDOUT: %require_complete.loc16_21 => constants.%require_complete.5f4 +// CHECK:STDOUT: %require_complete.loc16_30 => constants.%require_complete.4ae // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Derived.as.Destroy.impl(constants.%T) { @@ -6210,23 +6210,23 @@ class T2(G2:! type) { // CHECK:STDOUT: %Base.loc8_23.1: type = class_type @Base, @Base(constants.%ptr.79f) [symbolic = %Base.loc8_23.2 (constants.%Base.16b)] // CHECK:STDOUT: %.loc8: @Derived.%Derived.elem (%Derived.elem) = base_decl %Base.loc8_23.1, element0 [concrete] // CHECK:STDOUT: %Derived.F.decl: @Derived.%Derived.F.type (%Derived.F.type) = fn_decl @Derived.F [symbolic = @Derived.%Derived.F (constants.%Derived.F)] { -// CHECK:STDOUT: %self.patt: @Derived.F.%pattern_type.loc9_13 (%pattern_type.423) = binding_pattern self [concrete] -// CHECK:STDOUT: %self.param_patt: @Derived.F.%pattern_type.loc9_13 (%pattern_type.423) = value_param_pattern %self.patt, call_param0 [concrete] -// CHECK:STDOUT: %t.patt: @Derived.F.%pattern_type.loc9_25 (%pattern_type.afe) = binding_pattern t [concrete] -// CHECK:STDOUT: %t.param_patt: @Derived.F.%pattern_type.loc9_25 (%pattern_type.afe) = value_param_pattern %t.patt, call_param1 [concrete] +// CHECK:STDOUT: %self.patt: @Derived.F.%pattern_type.loc9_17 (%pattern_type.423) = binding_pattern self [concrete] +// CHECK:STDOUT: %self.param_patt: @Derived.F.%pattern_type.loc9_17 (%pattern_type.423) = value_param_pattern %self.patt, call_param0 [concrete] +// CHECK:STDOUT: %t.patt: @Derived.F.%pattern_type.loc9_29 (%pattern_type.afe) = binding_pattern t [concrete] +// CHECK:STDOUT: %t.param_patt: @Derived.F.%pattern_type.loc9_29 (%pattern_type.afe) = value_param_pattern %t.patt, call_param1 [concrete] // CHECK:STDOUT: } { // CHECK:STDOUT: %self.param: @Derived.F.%Derived (%Derived) = value_param call_param0 -// CHECK:STDOUT: %.loc9_19.1: type = splice_block %Self.ref [symbolic = %Derived (constants.%Derived)] { -// CHECK:STDOUT: %.loc9_19.2: type = specific_constant constants.%Derived, @Derived(constants.%T) [symbolic = %Derived (constants.%Derived)] -// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc9_19.2 [symbolic = %Derived (constants.%Derived)] +// CHECK:STDOUT: %.loc9_23.1: type = splice_block %Self.ref [symbolic = %Derived (constants.%Derived)] { +// CHECK:STDOUT: %.loc9_23.2: type = specific_constant constants.%Derived, @Derived(constants.%T) [symbolic = %Derived (constants.%Derived)] +// CHECK:STDOUT: %Self.ref: type = name_ref Self, %.loc9_23.2 [symbolic = %Derived (constants.%Derived)] // CHECK:STDOUT: } // CHECK:STDOUT: %self: @Derived.F.%Derived (%Derived) = bind_name self, %self.param -// CHECK:STDOUT: %t.param: @Derived.F.%ptr.loc9_28 (%ptr.79f) = value_param call_param1 -// CHECK:STDOUT: %.loc9_29: type = splice_block %ptr.loc9_29 [symbolic = %ptr.loc9_28 (constants.%ptr.79f)] { +// CHECK:STDOUT: %t.param: @Derived.F.%ptr.loc9_32 (%ptr.79f) = value_param call_param1 +// CHECK:STDOUT: %.loc9_33: type = splice_block %ptr.loc9_33 [symbolic = %ptr.loc9_32 (constants.%ptr.79f)] { // CHECK:STDOUT: %T.ref: type = name_ref T, @Derived.%T.loc7_15.2 [symbolic = %T (constants.%T)] -// CHECK:STDOUT: %ptr.loc9_29: type = ptr_type %T.ref [symbolic = %ptr.loc9_28 (constants.%ptr.79f)] +// CHECK:STDOUT: %ptr.loc9_33: type = ptr_type %T.ref [symbolic = %ptr.loc9_32 (constants.%ptr.79f)] // CHECK:STDOUT: } -// CHECK:STDOUT: %t: @Derived.F.%ptr.loc9_28 (%ptr.79f) = bind_name t, %t.param +// CHECK:STDOUT: %t: @Derived.F.%ptr.loc9_32 (%ptr.79f) = bind_name t, %t.param // CHECK:STDOUT: } // CHECK:STDOUT: %Self.ref: type = name_ref Self, constants.%Derived [symbolic = @Derived.as.Destroy.impl.%Derived (constants.%Derived)] // CHECK:STDOUT: impl_decl @Derived.as.Destroy.impl [concrete] {} {} @@ -6283,20 +6283,20 @@ class T2(G2:! type) { // CHECK:STDOUT: fn(%self.param: @Base.as.Destroy.impl.Op.%ptr (%ptr.b7c)) = "no_op"; // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: generic impl fn @Derived.F(@Derived.%T.loc7_15.2: type) { +// CHECK:STDOUT: generic override fn @Derived.F(@Derived.%T.loc7_15.2: type) { // CHECK:STDOUT: %T: type = bind_symbolic_name T, 0 [symbolic = %T (constants.%T)] // CHECK:STDOUT: %Derived: type = class_type @Derived, @Derived(%T) [symbolic = %Derived (constants.%Derived)] -// CHECK:STDOUT: %pattern_type.loc9_13: type = pattern_type %Derived [symbolic = %pattern_type.loc9_13 (constants.%pattern_type.423)] -// CHECK:STDOUT: %ptr.loc9_28: type = ptr_type %T [symbolic = %ptr.loc9_28 (constants.%ptr.79f)] -// CHECK:STDOUT: %Base: type = class_type @Base, @Base(%ptr.loc9_28) [symbolic = %Base (constants.%Base.16b)] -// CHECK:STDOUT: %require_complete.loc9_28: = require_complete_type %Base [symbolic = %require_complete.loc9_28 (constants.%require_complete.fce)] -// CHECK:STDOUT: %pattern_type.loc9_25: type = pattern_type %ptr.loc9_28 [symbolic = %pattern_type.loc9_25 (constants.%pattern_type.afe)] +// CHECK:STDOUT: %pattern_type.loc9_17: type = pattern_type %Derived [symbolic = %pattern_type.loc9_17 (constants.%pattern_type.423)] +// CHECK:STDOUT: %ptr.loc9_32: type = ptr_type %T [symbolic = %ptr.loc9_32 (constants.%ptr.79f)] +// CHECK:STDOUT: %Base: type = class_type @Base, @Base(%ptr.loc9_32) [symbolic = %Base (constants.%Base.16b)] +// CHECK:STDOUT: %require_complete.loc9_32: = require_complete_type %Base [symbolic = %require_complete.loc9_32 (constants.%require_complete.fce)] +// CHECK:STDOUT: %pattern_type.loc9_29: type = pattern_type %ptr.loc9_32 [symbolic = %pattern_type.loc9_29 (constants.%pattern_type.afe)] // CHECK:STDOUT: // CHECK:STDOUT: !definition: -// CHECK:STDOUT: %require_complete.loc9_17: = require_complete_type %Derived [symbolic = %require_complete.loc9_17 (constants.%require_complete.5f4)] -// CHECK:STDOUT: %require_complete.loc9_26: = require_complete_type %ptr.loc9_28 [symbolic = %require_complete.loc9_26 (constants.%require_complete.6e5)] +// CHECK:STDOUT: %require_complete.loc9_21: = require_complete_type %Derived [symbolic = %require_complete.loc9_21 (constants.%require_complete.5f4)] +// CHECK:STDOUT: %require_complete.loc9_30: = require_complete_type %ptr.loc9_32 [symbolic = %require_complete.loc9_30 (constants.%require_complete.6e5)] // CHECK:STDOUT: -// CHECK:STDOUT: impl fn(%self.param: @Derived.F.%Derived (%Derived), %t.param: @Derived.F.%ptr.loc9_28 (%ptr.79f)) { +// CHECK:STDOUT: override fn(%self.param: @Derived.F.%Derived (%Derived), %t.param: @Derived.F.%ptr.loc9_32 (%ptr.79f)) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } @@ -6385,15 +6385,15 @@ class T2(G2:! type) { // CHECK:STDOUT: specific @Derived.F(constants.%T) { // CHECK:STDOUT: %T => constants.%T // CHECK:STDOUT: %Derived => constants.%Derived -// CHECK:STDOUT: %pattern_type.loc9_13 => constants.%pattern_type.423 -// CHECK:STDOUT: %ptr.loc9_28 => constants.%ptr.79f +// CHECK:STDOUT: %pattern_type.loc9_17 => constants.%pattern_type.423 +// CHECK:STDOUT: %ptr.loc9_32 => constants.%ptr.79f // CHECK:STDOUT: %Base => constants.%Base.16b -// CHECK:STDOUT: %require_complete.loc9_28 => constants.%require_complete.fce -// CHECK:STDOUT: %pattern_type.loc9_25 => constants.%pattern_type.afe +// CHECK:STDOUT: %require_complete.loc9_32 => constants.%require_complete.fce +// CHECK:STDOUT: %pattern_type.loc9_29 => constants.%pattern_type.afe // CHECK:STDOUT: // CHECK:STDOUT: !definition: -// CHECK:STDOUT: %require_complete.loc9_17 => constants.%require_complete.5f4 -// CHECK:STDOUT: %require_complete.loc9_26 => constants.%require_complete.6e5 +// CHECK:STDOUT: %require_complete.loc9_21 => constants.%require_complete.5f4 +// CHECK:STDOUT: %require_complete.loc9_30 => constants.%require_complete.6e5 // CHECK:STDOUT: } // CHECK:STDOUT: // CHECK:STDOUT: specific @Derived.as.Destroy.impl(constants.%T) { @@ -6623,7 +6623,7 @@ class T2(G2:! type) { // CHECK:STDOUT: fn(%self.param: @Base.as.Destroy.impl.Op.%ptr (%ptr.b7c)) = "no_op"; // CHECK:STDOUT: } // CHECK:STDOUT: -// CHECK:STDOUT: impl fn @Derived.F(%self.param: %Derived) { +// CHECK:STDOUT: override fn @Derived.F(%self.param: %Derived) { // CHECK:STDOUT: !entry: // CHECK:STDOUT: return // CHECK:STDOUT: } diff --git a/toolchain/check/testdata/function/definition/fail_local_decl.carbon b/toolchain/check/testdata/function/definition/fail_local_decl.carbon index dffce768ac0e..a10c1d79e46f 100644 --- a/toolchain/check/testdata/function/definition/fail_local_decl.carbon +++ b/toolchain/check/testdata/function/definition/fail_local_decl.carbon @@ -22,11 +22,11 @@ fn F() { // CHECK:STDERR: ^~~~~~~ // CHECK:STDERR: default fn F(); - // CHECK:STDERR: fail_virtual.carbon:[[@LINE+4]]:3: error: `impl` not allowed; requires class scope [ModifierRequiresClass] - // CHECK:STDERR: impl fn G(); - // CHECK:STDERR: ^~~~ + // CHECK:STDERR: fail_virtual.carbon:[[@LINE+4]]:3: error: `override` not allowed; requires class scope [ModifierRequiresClass] + // CHECK:STDERR: override fn G(); + // CHECK:STDERR: ^~~~~~~~ // CHECK:STDERR: - impl fn G(); + override fn G(); // CHECK:STDERR: fail_virtual.carbon:[[@LINE+4]]:3: error: `virtual` not allowed; requires class scope [ModifierRequiresClass] // CHECK:STDERR: virtual fn H(); // CHECK:STDERR: ^~~~~~~ diff --git a/toolchain/check/testdata/interop/cpp/class/abstract.carbon b/toolchain/check/testdata/interop/cpp/class/abstract.carbon index 688f5dd19cde..c676be1a3613 100644 --- a/toolchain/check/testdata/interop/cpp/class/abstract.carbon +++ b/toolchain/check/testdata/interop/cpp/class/abstract.carbon @@ -46,11 +46,11 @@ import Cpp library "abstract.h"; class C { extend base: Cpp.A; - // CHECK:STDERR: fail_todo_impl_abstract_member.carbon:[[@LINE+4]]:3: error: impl without compatible virtual in base class [ImplWithoutVirtualInBase] - // CHECK:STDERR: impl fn f[addr self: Self*]() {} - // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // CHECK:STDERR: fail_todo_impl_abstract_member.carbon:[[@LINE+4]]:3: error: override without compatible virtual in base class [OverrideWithoutVirtualInBase] + // CHECK:STDERR: override fn f[addr self: Self*]() {} + // CHECK:STDERR: ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // CHECK:STDERR: - impl fn f[addr self: Self*]() {} + override fn f[addr self: Self*]() {} } // --- abstract_final.h diff --git a/toolchain/diagnostics/diagnostic_kind.def b/toolchain/diagnostics/diagnostic_kind.def index 3e81a0f6c3b4..f2ad06b77227 100644 --- a/toolchain/diagnostics/diagnostic_kind.def +++ b/toolchain/diagnostics/diagnostic_kind.def @@ -289,8 +289,8 @@ CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclOutsideClass) CARBON_DIAGNOSTIC_KIND(ClassSpecificDeclPrevious) CARBON_DIAGNOSTIC_KIND(ClassIncompleteWithinDefinition) CARBON_DIAGNOSTIC_KIND(GenericVirtual) -CARBON_DIAGNOSTIC_KIND(ImplWithoutBase) -CARBON_DIAGNOSTIC_KIND(ImplWithoutVirtualInBase) +CARBON_DIAGNOSTIC_KIND(OverrideWithoutBase) +CARBON_DIAGNOSTIC_KIND(OverrideWithoutVirtualInBase) CARBON_DIAGNOSTIC_KIND(VirtualWithoutSelf) // Deduction. diff --git a/toolchain/lex/token_kind.def b/toolchain/lex/token_kind.def index 8f99e5d1b3a7..5cd423e39900 100644 --- a/toolchain/lex/token_kind.def +++ b/toolchain/lex/token_kind.def @@ -199,6 +199,7 @@ CARBON_KEYWORD_TOKEN(Not, "not") CARBON_KEYWORD_TOKEN(Observe, "observe") CARBON_TOKEN_WITH_VIRTUAL_NODE( CARBON_KEYWORD_TOKEN(Or, "or")) +CARBON_KEYWORD_TOKEN(Override, "override") CARBON_KEYWORD_TOKEN(Partial, "partial") CARBON_KEYWORD_TOKEN(Private, "private") CARBON_KEYWORD_TOKEN(Protected, "protected") diff --git a/toolchain/lower/testdata/class/virtual.carbon b/toolchain/lower/testdata/class/virtual.carbon index 41495b6d6dd2..c29d841f8f6c 100644 --- a/toolchain/lower/testdata/class/virtual.carbon +++ b/toolchain/lower/testdata/class/virtual.carbon @@ -24,7 +24,7 @@ base class Intermediate { class Derived { extend base: Intermediate; - impl fn Fn[self: Self]() { } + override fn Fn[self: Self]() { } } // --- create.carbon @@ -100,7 +100,7 @@ base class Base { class Derived { extend base: Base; - impl fn F[self: Self](); + override fn F[self: Self](); } fn Use() { diff --git a/toolchain/parse/node_kind.def b/toolchain/parse/node_kind.def index 55dfecbfeec4..de29180ac512 100644 --- a/toolchain/parse/node_kind.def +++ b/toolchain/parse/node_kind.def @@ -344,6 +344,7 @@ CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Export) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Extend) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Final) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Impl) +CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Override) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Private) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Protected) CARBON_PARSE_NODE_KIND_TOKEN_MODIFIER(Virtual) diff --git a/toolchain/parse/state.def b/toolchain/parse/state.def index 283ff96b4441..d39b1d6ebb03 100644 --- a/toolchain/parse/state.def +++ b/toolchain/parse/state.def @@ -285,8 +285,8 @@ CARBON_PARSE_STATE(DeclNameAndParamsAfterParams) // ^~~~~~ // final // ^~~~~ -// impl fn -// ^~~~ +// override fn +// ^~~~~~~~ // private // ^~~~~~~ // protected diff --git a/toolchain/parse/testdata/function/decl_statement.carbon b/toolchain/parse/testdata/function/decl_statement.carbon index f188ae5e2c5e..a623e27b1cd6 100644 --- a/toolchain/parse/testdata/function/decl_statement.carbon +++ b/toolchain/parse/testdata/function/decl_statement.carbon @@ -37,6 +37,7 @@ fn F() { namespace N; default fn F(); impl fn G(); + override fn H(); virtual fn H(); private var v: i32; protected var v: i32; @@ -157,6 +158,12 @@ fn F() { // CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, // CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 6}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, +// CHECK:STDOUT: {kind: 'OverrideModifier', text: 'override'}, +// CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'H'}, +// CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, +// CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, +// CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 6}, +// CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, // CHECK:STDOUT: {kind: 'VirtualModifier', text: 'virtual'}, // CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'H'}, // CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, @@ -176,6 +183,6 @@ fn F() { // CHECK:STDOUT: {kind: 'VarBindingPattern', text: ':', subtree_size: 3}, // CHECK:STDOUT: {kind: 'VariablePattern', text: 'var', subtree_size: 4}, // CHECK:STDOUT: {kind: 'VariableDecl', text: ';', subtree_size: 7}, -// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 58}, +// CHECK:STDOUT: {kind: 'FunctionDefinition', text: '}', subtree_size: 64}, // CHECK:STDOUT: {kind: 'FileEnd', text: ''}, // CHECK:STDOUT: ] diff --git a/toolchain/parse/testdata/function/declaration.carbon b/toolchain/parse/testdata/function/declaration.carbon index 0b1438ea4a00..b6f4a41b7276 100644 --- a/toolchain/parse/testdata/function/declaration.carbon +++ b/toolchain/parse/testdata/function/declaration.carbon @@ -58,10 +58,10 @@ fn destroy[self: Self]().Foo() {} // --- impl_fn.carbon -impl fn F(); -abstract impl fn G(); -impl abstract fn H(); -private impl default fn I(); +override fn F(); +abstract override fn G(); +override abstract fn H(); +private override default fn I(); // --- fail_identifier_instead_of_sig.carbon @@ -346,20 +346,20 @@ 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: parse_tree: [ // CHECK:STDOUT: {kind: 'FileStart', text: ''}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'ImplModifier', text: 'impl'}, +// CHECK:STDOUT: {kind: 'OverrideModifier', text: 'override'}, // CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'F'}, // CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, // CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, // CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 6}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, // CHECK:STDOUT: {kind: 'AbstractModifier', text: 'abstract'}, -// CHECK:STDOUT: {kind: 'ImplModifier', text: 'impl'}, +// CHECK:STDOUT: {kind: 'OverrideModifier', text: 'override'}, // CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'G'}, // CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, // CHECK:STDOUT: {kind: 'ExplicitParamList', text: ')', subtree_size: 2}, // CHECK:STDOUT: {kind: 'FunctionDecl', text: ';', subtree_size: 7}, // CHECK:STDOUT: {kind: 'FunctionIntroducer', text: 'fn'}, -// CHECK:STDOUT: {kind: 'ImplModifier', text: 'impl'}, +// CHECK:STDOUT: {kind: 'OverrideModifier', text: 'override'}, // CHECK:STDOUT: {kind: 'AbstractModifier', text: 'abstract'}, // CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'H'}, // CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, @@ -367,7 +367,7 @@ 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: 'FunctionIntroducer', text: 'fn'}, // CHECK:STDOUT: {kind: 'PrivateModifier', text: 'private'}, -// CHECK:STDOUT: {kind: 'ImplModifier', text: 'impl'}, +// CHECK:STDOUT: {kind: 'OverrideModifier', text: 'override'}, // CHECK:STDOUT: {kind: 'DefaultModifier', text: 'default'}, // CHECK:STDOUT: {kind: 'IdentifierNameBeforeParams', text: 'I'}, // CHECK:STDOUT: {kind: 'ExplicitParamListStart', text: '('}, diff --git a/toolchain/sem_ir/formatter.cpp b/toolchain/sem_ir/formatter.cpp index e88b6e031ba9..b9ebfa4d028e 100644 --- a/toolchain/sem_ir/formatter.cpp +++ b/toolchain/sem_ir/formatter.cpp @@ -496,8 +496,8 @@ auto Formatter::FormatFunction(FunctionId id, const Function& fn) -> void { case FunctionFields::VirtualModifier::Abstract: function_start += "abstract "; break; - case FunctionFields::VirtualModifier::Impl: - function_start += "impl "; + case FunctionFields::VirtualModifier::Override: + function_start += "override "; break; case FunctionFields::VirtualModifier::None: break; diff --git a/toolchain/sem_ir/function.h b/toolchain/sem_ir/function.h index 109e0ca2ed4b..20cf84e23f29 100644 --- a/toolchain/sem_ir/function.h +++ b/toolchain/sem_ir/function.h @@ -27,7 +27,7 @@ struct FunctionFields { }; // Kinds of virtual modifiers that can apply to functions. - enum class VirtualModifier : uint8_t { None, Virtual, Abstract, Impl }; + enum class VirtualModifier : uint8_t { None, Virtual, Abstract, Override }; // The following members always have values, and do not change throughout the // lifetime of the function.