Skip to content

Commit 55ebf6a

Browse files
committed
[error] Reject dynamic object initializers for abstract classes.
#200
1 parent 6826e2f commit 55ebf6a

File tree

6 files changed

+68
-40
lines changed

6 files changed

+68
-40
lines changed

Sema.fu

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -673,6 +673,20 @@ public class FuSema
673673
this.CurrentScope = this.CurrentScope.Parent;
674674
}
675675

676+
void CheckInstantiable!(FuClass klass, FuExpr location)
677+
{
678+
switch (klass.CallType) {
679+
case FuCallType.Static:
680+
ReportError(location, "Cannot instantiate static class");
681+
break;
682+
case FuCallType.Abstract:
683+
ReportError(location, "Cannot instantiate abstract class");
684+
break;
685+
default:
686+
break;
687+
}
688+
}
689+
676690
FuExpr# ResolveNew!(FuPrefixExpr# expr)
677691
{
678692
if (expr.Type != null)
@@ -682,6 +696,7 @@ public class FuSema
682696
type = ToType(binaryNew.Left, true);
683697
if (!(type is FuClassType klass) || klass is FuReadWriteClassType)
684698
return PoisonError(expr, "Invalid argument to new");
699+
CheckInstantiable(klass.Class, expr);
685700
assert binaryNew.Right is FuAggregateInitializer# init;
686701
ResolveObjectLiteral(klass, init);
687702
expr.Type = new FuDynamicPtrType { Loc = expr.Loc, Class = klass.Class };
@@ -1657,16 +1672,7 @@ public class FuSema
16571672
if (call.Method.Name == "string")
16581673
return this.Host.Program.System.StringStorageType;
16591674
if (this.Host.Program.TryLookup(call.Method.Name, true) is FuClass! klass2) {
1660-
switch (klass2.CallType) {
1661-
case FuCallType.Static:
1662-
ReportError(expr, "Cannot instantiate static class");
1663-
break;
1664-
case FuCallType.Abstract:
1665-
ReportError(expr, "Cannot instantiate abstract class");
1666-
break;
1667-
default:
1668-
break;
1669-
}
1675+
CheckInstantiable(klass2, expr);
16701676
call.Method.Symbol = klass2; // for vscode goto
16711677
return new FuStorageType { Class = klass2 };
16721678
}

libfut.cpp

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5168,6 +5168,20 @@ void FuSema::closeScope()
51685168
this->currentScope = this->currentScope->parent;
51695169
}
51705170

5171+
void FuSema::checkInstantiable(const FuClass * klass, const FuExpr * location)
5172+
{
5173+
switch (klass->callType) {
5174+
case FuCallType::static_:
5175+
reportError(location, "Cannot instantiate static class");
5176+
break;
5177+
case FuCallType::abstract:
5178+
reportError(location, "Cannot instantiate abstract class");
5179+
break;
5180+
default:
5181+
break;
5182+
}
5183+
}
5184+
51715185
std::shared_ptr<FuExpr> FuSema::resolveNew(std::shared_ptr<FuPrefixExpr> expr)
51725186
{
51735187
if (expr->type != nullptr)
@@ -5179,6 +5193,7 @@ std::shared_ptr<FuExpr> FuSema::resolveNew(std::shared_ptr<FuPrefixExpr> expr)
51795193
const FuClassType * klass;
51805194
if (!(klass = dynamic_cast<const FuClassType *>(type.get())) || dynamic_cast<const FuReadWriteClassType *>(klass))
51815195
return poisonError(expr.get(), "Invalid argument to new");
5196+
checkInstantiable(klass->class_, expr.get());
51825197
std::shared_ptr<FuAggregateInitializer> init = std::static_pointer_cast<FuAggregateInitializer>(binaryNew->right);
51835198
resolveObjectLiteral(klass, init.get());
51845199
std::shared_ptr<FuDynamicPtrType> futemp0 = std::make_shared<FuDynamicPtrType>();
@@ -6239,16 +6254,7 @@ std::shared_ptr<FuType> FuSema::toBaseType(FuExpr * expr, FuToken ptrModifier, b
62396254
if (call->method->name == "string")
62406255
return this->host->program->system->stringStorageType;
62416256
if (FuClass *klass2 = dynamic_cast<FuClass *>(this->host->program->tryLookup(call->method->name, true).get())) {
6242-
switch (klass2->callType) {
6243-
case FuCallType::static_:
6244-
reportError(expr, "Cannot instantiate static class");
6245-
break;
6246-
case FuCallType::abstract:
6247-
reportError(expr, "Cannot instantiate abstract class");
6248-
break;
6249-
default:
6250-
break;
6251-
}
6257+
checkInstantiable(klass2, expr);
62526258
call->method->symbol = klass2;
62536259
std::shared_ptr<FuStorageType> futemp0 = std::make_shared<FuStorageType>();
62546260
futemp0->class_ = klass2;

libfut.cs

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5397,6 +5397,20 @@ void CloseScope()
53975397
this.CurrentScope = this.CurrentScope.Parent;
53985398
}
53995399

5400+
void CheckInstantiable(FuClass klass, FuExpr location)
5401+
{
5402+
switch (klass.CallType) {
5403+
case FuCallType.Static:
5404+
ReportError(location, "Cannot instantiate static class");
5405+
break;
5406+
case FuCallType.Abstract:
5407+
ReportError(location, "Cannot instantiate abstract class");
5408+
break;
5409+
default:
5410+
break;
5411+
}
5412+
}
5413+
54005414
FuExpr ResolveNew(FuPrefixExpr expr)
54015415
{
54025416
if (expr.Type != null)
@@ -5406,6 +5420,7 @@ FuExpr ResolveNew(FuPrefixExpr expr)
54065420
type = ToType(binaryNew.Left, true);
54075421
if (!(type is FuClassType klass) || klass is FuReadWriteClassType)
54085422
return PoisonError(expr, "Invalid argument to new");
5423+
CheckInstantiable(klass.Class, expr);
54095424
FuAggregateInitializer init = (FuAggregateInitializer) binaryNew.Right;
54105425
ResolveObjectLiteral(klass, init);
54115426
expr.Type = new FuDynamicPtrType { Loc = expr.Loc, Class = klass.Class };
@@ -6326,16 +6341,7 @@ FuType ToBaseType(FuExpr expr, FuToken ptrModifier, bool nullable)
63266341
if (call.Method.Name == "string")
63276342
return this.Host.Program.System.StringStorageType;
63286343
if (this.Host.Program.TryLookup(call.Method.Name, true) is FuClass klass2) {
6329-
switch (klass2.CallType) {
6330-
case FuCallType.Static:
6331-
ReportError(expr, "Cannot instantiate static class");
6332-
break;
6333-
case FuCallType.Abstract:
6334-
ReportError(expr, "Cannot instantiate abstract class");
6335-
break;
6336-
default:
6337-
break;
6338-
}
6344+
CheckInstantiable(klass2, expr);
63396345
call.Method.Symbol = klass2;
63406346
return new FuStorageType { Class = klass2 };
63416347
}

libfut.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2347,6 +2347,7 @@ class FuSema
23472347
void checkComparison(const FuExpr * left, const FuExpr * right) const;
23482348
void openScope(FuScope * scope);
23492349
void closeScope();
2350+
void checkInstantiable(const FuClass * klass, const FuExpr * location);
23502351
std::shared_ptr<FuExpr> resolveNew(std::shared_ptr<FuPrefixExpr> expr);
23512352
std::shared_ptr<FuExpr> visitPrefixExpr(std::shared_ptr<FuPrefixExpr> expr);
23522353
std::shared_ptr<FuExpr> visitPostfixExpr(std::shared_ptr<FuPostfixExpr> expr);

libfut.js

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -5659,6 +5659,20 @@ export class FuSema
56595659
this.#currentScope = this.#currentScope.parent;
56605660
}
56615661

5662+
#checkInstantiable(klass, location)
5663+
{
5664+
switch (klass.callType) {
5665+
case FuCallType.STATIC:
5666+
this.#reportError(location, "Cannot instantiate static class");
5667+
break;
5668+
case FuCallType.ABSTRACT:
5669+
this.#reportError(location, "Cannot instantiate abstract class");
5670+
break;
5671+
default:
5672+
break;
5673+
}
5674+
}
5675+
56625676
#resolveNew(expr)
56635677
{
56645678
if (expr.type != null)
@@ -5670,6 +5684,7 @@ export class FuSema
56705684
let klass;
56715685
if (!((klass = type) instanceof FuClassType) || klass instanceof FuReadWriteClassType)
56725686
return this.#poisonError(expr, "Invalid argument to new");
5687+
this.#checkInstantiable(klass.class, expr);
56735688
let init = binaryNew.right;
56745689
this.#resolveObjectLiteral(klass, init);
56755690
expr.type = Object.assign(new FuDynamicPtrType(), { loc: expr.loc, class: klass.class });
@@ -6703,16 +6718,7 @@ export class FuSema
67036718
return this.#host.program.system.stringStorageType;
67046719
let klass2;
67056720
if ((klass2 = this.#host.program.tryLookup(call.method.name, true)) instanceof FuClass) {
6706-
switch (klass2.callType) {
6707-
case FuCallType.STATIC:
6708-
this.#reportError(expr, "Cannot instantiate static class");
6709-
break;
6710-
case FuCallType.ABSTRACT:
6711-
this.#reportError(expr, "Cannot instantiate abstract class");
6712-
break;
6713-
default:
6714-
break;
6715-
}
6721+
this.#checkInstantiable(klass2, expr);
67166722
call.method.symbol = klass2;
67176723
return Object.assign(new FuStorageType(), { class: klass2 });
67186724
}

test/error/ClassAbstractInstance.fu

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
public abstract class Test
22
{
3+
int X;
4+
35
public static bool Run()
46
{
57
Test() o; //ERROR: Cannot instantiate abstract class
68
Test()[3] a; //ERROR: Cannot instantiate abstract class
79
Test# p = new Test(); //ERROR: Cannot instantiate abstract class
10+
p = new Test { X = 5 }; //ERROR: Cannot instantiate abstract class
811
return true;
912
}
1013
}

0 commit comments

Comments
 (0)