feat: prevent metaclass inheritance and disallow super in static methods

Remove the metaclass inheritance chain that mirrored the class hierarchy, instead always binding metaclasses directly to Class. This prevents static methods from being inherited by subclasses. Also add a compile-time error when `super` is used inside a static method, since it would always delegate to Class without useful effect. Update the `isInsideMethod` check to use `compiler->fields` instead of walking the parent chain for correctness. Add test cases for the new restrictions and remove the old test that verified static method inheritance.
This commit is contained in:
Bob Nystrom
2014-01-18 01:29:10 +00:00
parent 4605b70c6e
commit 15d9dc229c
5 changed files with 20 additions and 42 deletions
+5 -8
View File
@@ -1645,14 +1645,7 @@ static void string(Compiler* compiler, bool allowAssignment)
// directly or indirectly contained in a method for a class.
static bool isInsideMethod(Compiler* compiler)
{
// Walk up the parent chain to see if there is an enclosing method.
while (compiler != NULL)
{
if (compiler->methodName != NULL) return true;
compiler = compiler->parent;
}
return false;
return compiler->fields != NULL;
}
static void new_(Compiler* compiler, bool allowAssignment)
@@ -1676,6 +1669,10 @@ static void super_(Compiler* compiler, bool allowAssignment)
{
error(compiler, "Cannot use 'super' outside of a method.");
}
else if (compiler->isStaticMethod)
{
error(compiler, "Cannot use 'super' in a static method.");
}
loadThis(compiler);
+3 -11
View File
@@ -72,17 +72,9 @@ ObjClass* wrenNewClass(WrenVM* vm, ObjClass* superclass, int numFields)
PinnedObj pinned;
pinObj(vm, (Obj*)metaclass, &pinned);
// The metaclass inheritance chain mirrors the class's inheritance chain
// except that when the latter bottoms out at "Object", the metaclass one
// bottoms out at "Class".
if (superclass == vm->objectClass)
{
wrenBindSuperclass(vm, metaclass, vm->classClass);
}
else
{
wrenBindSuperclass(vm, metaclass, superclass->metaclass);
}
// Metaclasses always inherit Class and do not parallel the non-metaclass
// hierarchy.
wrenBindSuperclass(vm, metaclass, vm->classClass);
ObjClass* classObj = wrenNewSingleClass(vm, numFields);