From 2e502020e638c1b9ef5ec88496c7a1bd6ca2bad2 Mon Sep 17 00:00:00 2001 From: Piotr Fusik Date: Wed, 9 Oct 2024 14:11:48 +0200 Subject: [PATCH] [error] Reject attempts to copy object storage. Fix #176 --- Sema.fu | 5 +++++ libfut.cpp | 18 +++++++++++++----- libfut.cs | 4 ++++ libfut.js | 6 ++++++ test/error/ObjectStgCopy.fu | 11 +++++++++++ 5 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 test/error/ObjectStgCopy.fu diff --git a/Sema.fu b/Sema.fu index 8a425971..65843863 100644 --- a/Sema.fu +++ b/Sema.fu @@ -1088,6 +1088,9 @@ public class FuSema case FuToken.Assign: CheckLValue(left); CoercePermanent(right, left.Type); + if (left.Type is FuStorageType && right is FuSymbolReference + && !(left is FuSymbolReference symbol && symbol.Symbol is FuNamedValue storageDef && storageDef.IsAssignableStorage())) + ReportError(right, "Cannot copy object storage"); SetSharedAssign(left, right); expr.Left = left; expr.Right = right; @@ -1462,6 +1465,8 @@ public class FuSema if (!(expr.Value is FuLiteral literal) || !literal.IsDefaultValue()) ReportError(expr.Value, "Only null, zero and false supported as an array initializer"); } + else if (type is FuStorageType && expr.Value is FuSymbolReference) + ReportError(expr.Value, "Cannot copy object storage"); CoercePermanent(expr.Value, type); } } diff --git a/libfut.cpp b/libfut.cpp index 5a536e2e..545d3683 100644 --- a/libfut.cpp +++ b/libfut.cpp @@ -5601,11 +5601,17 @@ std::shared_ptr FuSema::visitBinaryExpr(std::shared_ptr ex case FuToken::assign: checkLValue(left.get()); coercePermanent(right.get(), left->type.get()); - setSharedAssign(left.get(), right.get()); - expr->left = left; - expr->right = right; - expr->type = left->type; - return expr; + { + const FuSymbolReference * symbol; + const FuNamedValue * storageDef; + if (dynamic_cast(left->type.get()) && dynamic_cast(right.get()) && !((symbol = dynamic_cast(left.get())) && (storageDef = dynamic_cast(symbol->symbol)) && storageDef->isAssignableStorage())) + reportError(right.get(), "Cannot copy object storage"); + setSharedAssign(left.get(), right.get()); + expr->left = left; + expr->right = right; + expr->type = left->type; + return expr; + } case FuToken::addAssign: checkLValue(left.get()); if (left->type->id == FuId::stringStorageType) @@ -5998,6 +6004,8 @@ void FuSema::visitVar(std::shared_ptr expr) if (!(literal = dynamic_cast(expr->value.get())) || !literal->isDefaultValue()) reportError(expr->value.get(), "Only null, zero and false supported as an array initializer"); } + else if (dynamic_cast(type) && dynamic_cast(expr->value.get())) + reportError(expr->value.get(), "Cannot copy object storage"); coercePermanent(expr->value.get(), type); } } diff --git a/libfut.cs b/libfut.cs index 8f37ecd3..37ed3996 100644 --- a/libfut.cs +++ b/libfut.cs @@ -5743,6 +5743,8 @@ FuExpr VisitBinaryExpr(FuBinaryExpr expr) case FuToken.Assign: CheckLValue(left); CoercePermanent(right, left.Type); + if (left.Type is FuStorageType && right is FuSymbolReference && !(left is FuSymbolReference symbol && symbol.Symbol is FuNamedValue storageDef && storageDef.IsAssignableStorage())) + ReportError(right, "Cannot copy object storage"); SetSharedAssign(left, right); expr.Left = left; expr.Right = right; @@ -6097,6 +6099,8 @@ void VisitVar(FuVar expr) if (!(expr.Value is FuLiteral literal) || !literal.IsDefaultValue()) ReportError(expr.Value, "Only null, zero and false supported as an array initializer"); } + else if (type is FuStorageType && expr.Value is FuSymbolReference) + ReportError(expr.Value, "Cannot copy object storage"); CoercePermanent(expr.Value, type); } } diff --git a/libfut.js b/libfut.js index 56197a23..be3a02df 100644 --- a/libfut.js +++ b/libfut.js @@ -6043,6 +6043,10 @@ export class FuSema case FuToken.ASSIGN: this.#checkLValue(left); this.#coercePermanent(right, left.type); + let symbol; + let storageDef; + if (left.type instanceof FuStorageType && right instanceof FuSymbolReference && !((symbol = left) instanceof FuSymbolReference && (storageDef = symbol.symbol) instanceof FuNamedValue && storageDef.isAssignableStorage())) + this.#reportError(right, "Cannot copy object storage"); this.#setSharedAssign(left, right); expr.left = left; expr.right = right; @@ -6430,6 +6434,8 @@ export class FuSema if (!((literal = expr.value) instanceof FuLiteral) || !literal.isDefaultValue()) this.#reportError(expr.value, "Only null, zero and false supported as an array initializer"); } + else if (type instanceof FuStorageType && expr.value instanceof FuSymbolReference) + this.#reportError(expr.value, "Cannot copy object storage"); this.#coercePermanent(expr.value, type); } } diff --git a/test/error/ObjectStgCopy.fu b/test/error/ObjectStgCopy.fu new file mode 100644 index 00000000..c5f2da38 --- /dev/null +++ b/test/error/ObjectStgCopy.fu @@ -0,0 +1,11 @@ +public class Test +{ + public static bool Run() + { + Test() o; + Test() c = o; //ERROR: Cannot copy object storage + Test() t; + t = o; //ERROR: Cannot copy object storage + return true; + } +}