|
|
@@ -5167,16 +5167,27 @@ auto TypeChecker::DeclareClassDeclaration(Nonnull<ClassDeclaration*> class_decl,
|
|
|
}
|
|
|
CARBON_CHECK(!fun->name().is_qualified())
|
|
|
<< "qualified function name not permitted in class scope";
|
|
|
+
|
|
|
+ if (fun->virt_override() == VirtualOverride::Abstract &&
|
|
|
+ fun->body().has_value()) {
|
|
|
+ return ProgramError(fun->source_loc())
|
|
|
+ << "Error declaring `" << fun->name() << "`"
|
|
|
+ << ": abstract method cannot have a body.";
|
|
|
+ }
|
|
|
+
|
|
|
bool has_vtable_entry =
|
|
|
class_vtable.find(fun->name().inner_name()) != class_vtable.end();
|
|
|
// TODO: Implement complete declaration logic from
|
|
|
// `/docs/design/classes.md#virtual-methods`.
|
|
|
switch (fun->virt_override()) {
|
|
|
case VirtualOverride::Abstract:
|
|
|
- // Not supported yet.
|
|
|
- return ProgramError(fun->source_loc())
|
|
|
- << "Error declaring `" << fun->name() << "`"
|
|
|
- << ": `abstract` methods are not yet supported.";
|
|
|
+ if (class_decl->extensibility() != ClassExtensibility::Abstract) {
|
|
|
+ return ProgramError(fun->source_loc())
|
|
|
+ << "Error declaring `" << fun->name() << "`"
|
|
|
+ << ": `abstract` methods are allowed only in abstract "
|
|
|
+ "classes.";
|
|
|
+ }
|
|
|
+ break;
|
|
|
case VirtualOverride::None:
|
|
|
case VirtualOverride::Virtual:
|
|
|
if (has_vtable_entry) {
|
|
|
@@ -5237,6 +5248,24 @@ auto TypeChecker::DeclareClassDeclaration(Nonnull<ClassDeclaration*> class_decl,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ if (class_decl->extensibility() != ClassExtensibility::Abstract) {
|
|
|
+ auto abstract_method_it = std::find_if(
|
|
|
+ class_vtable.begin(), class_vtable.end(), [](const auto& vt) {
|
|
|
+ const auto* const fun = vt.getValue().first;
|
|
|
+ return fun->is_method() &&
|
|
|
+ fun->virt_override() == VirtualOverride::Abstract;
|
|
|
+ });
|
|
|
+
|
|
|
+ if (abstract_method_it != class_vtable.end()) {
|
|
|
+ auto fun_name = GetName(*abstract_method_it->getValue().first);
|
|
|
+ CARBON_CHECK(fun_name.has_value());
|
|
|
+ return ProgramError(class_decl->source_loc())
|
|
|
+ << "Error declaring `" << class_decl->name() << "`"
|
|
|
+ << ": non abstract class should implement abstract method `"
|
|
|
+ << *fun_name << "`.";
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
// For class declaration `class MyType(T:! type, U:! AnInterface)`, `Self`
|
|
|
// should have the value `MyType(T, U)`.
|
|
|
const auto* self_type = arena_->New<NominalClassType>(
|