From 0579766a366c674f52ba4ed26d1b436e78becddd Mon Sep 17 00:00:00 2001 From: Anton Trunov Date: Fri, 16 Aug 2024 01:05:51 +0900 Subject: [PATCH] fix: better error message if constant shadows stdlib identifier (#694) --- CHANGELOG.md | 1 + .../scope-const-shadows-stdlib-ident.tact | 1 + .../compilation-failed/scope-errors.spec.ts | 14 ++++++++++++++ src/test/compilation-failed/tact.config.json | 5 +++++ src/types/resolveStatements.ts | 17 +++++++++++++---- 5 files changed, 34 insertions(+), 4 deletions(-) create mode 100644 src/test/compilation-failed/contracts/scope-const-shadows-stdlib-ident.tact create mode 100644 src/test/compilation-failed/scope-errors.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index 636046e86..bef20a717 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Parsing of optional nested struct fields does not cause the `Not a tuple` error anymore: PR [#692](https://github.com/tact-lang/tact/pull/692) - Disallow shadowing of recursive function names: PR [#693](https://github.com/tact-lang/tact/pull/693) +- Better error message for the case when a constant shadows an stdlib identifier: PR [#694](https://github.com/tact-lang/tact/pull/694) ## [1.4.2] - 2024-08-13 diff --git a/src/test/compilation-failed/contracts/scope-const-shadows-stdlib-ident.tact b/src/test/compilation-failed/contracts/scope-const-shadows-stdlib-ident.tact new file mode 100644 index 000000000..2d1f11c62 --- /dev/null +++ b/src/test/compilation-failed/contracts/scope-const-shadows-stdlib-ident.tact @@ -0,0 +1 @@ +const b: Int = 42; diff --git a/src/test/compilation-failed/scope-errors.spec.ts b/src/test/compilation-failed/scope-errors.spec.ts new file mode 100644 index 000000000..2fcc16b65 --- /dev/null +++ b/src/test/compilation-failed/scope-errors.spec.ts @@ -0,0 +1,14 @@ +import { __DANGER_resetNodeId } from "../../grammar/ast"; +import { itShouldNotCompile } from "./util"; + +describe("scope-errors", () => { + beforeEach(() => { + __DANGER_resetNodeId(); + }); + + itShouldNotCompile({ + testName: "scope-const-shadows-stdlib-ident", + errorMessage: + 'Constant "b" is shadowing an identifier defined in the Tact standard library: pick a different constant name', + }); +}); diff --git a/src/test/compilation-failed/tact.config.json b/src/test/compilation-failed/tact.config.json index a2109296f..16fab850f 100644 --- a/src/test/compilation-failed/tact.config.json +++ b/src/test/compilation-failed/tact.config.json @@ -136,6 +136,11 @@ "name": "func-function-does-not-exist", "path": "./contracts/func-function-does-not-exist.tact", "output": "./contracts/output" + }, + { + "name": "scope-const-shadows-stdlib-ident", + "path": "./contracts/scope-const-shadows-stdlib-ident.tact", + "output": "./contracts/output" } ] } diff --git a/src/types/resolveStatements.ts b/src/types/resolveStatements.ts index bb247c6bf..59b5fb9a9 100644 --- a/src/types/resolveStatements.ts +++ b/src/types/resolveStatements.ts @@ -20,6 +20,7 @@ import { import { getAllStaticFunctions, getAllTypes, + getStaticConstant, getType, hasStaticConstant, resolveTypeRef, @@ -68,10 +69,18 @@ function checkVariableExists( ); } if (hasStaticConstant(ctx, idText(name))) { - throwCompilationError( - `Variable ${idTextErr(name)} is trying to shadow an existing constant with the same name`, - name.loc, - ); + if (name.loc.origin === "stdlib") { + const constLoc = getStaticConstant(ctx, idText(name)).loc; + throwCompilationError( + `Constant ${idTextErr(name)} is shadowing an identifier defined in the Tact standard library: pick a different constant name`, + constLoc, + ); + } else { + throwCompilationError( + `Variable ${idTextErr(name)} is trying to shadow an existing constant with the same name`, + name.loc, + ); + } } }