From 53c6529a9ffc7df8c85a253f867454ce07192632 Mon Sep 17 00:00:00 2001 From: Gusarich <danielsedovzzz@gmail.com> Date: Fri, 7 Feb 2025 13:54:02 +0300 Subject: [PATCH 1/4] feat: include expected type for invalid type error message --- src/types/__snapshots__/resolveStatements.spec.ts.snap | 6 +++--- src/types/resolveExpression.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/types/__snapshots__/resolveStatements.spec.ts.snap b/src/types/__snapshots__/resolveStatements.spec.ts.snap index 37fe22f6bb..6d43a2e8ad 100644 --- a/src/types/__snapshots__/resolveStatements.spec.ts.snap +++ b/src/types/__snapshots__/resolveStatements.spec.ts.snap @@ -100,7 +100,7 @@ exports[`resolveStatements should fail statements for contract-getter-with-metho `; exports[`resolveStatements should fail statements for contract-initof-wrong-arg 1`] = ` -"<unknown>:26:25: Invalid type "String" for argument "owner" +"<unknown>:26:25: Invalid type "String" for argument "owner", expected "Int" 25 | get fun newInit(): StateInit { > 26 | return initOf A("hello"); ^~~~~~~ @@ -385,7 +385,7 @@ exports[`resolveStatements should fail statements for expr-field-does-not-exist- `; exports[`resolveStatements should fail statements for expr-internal-fun-call-bool-param.tact 1`] = ` -"<unknown>:20:27: Invalid type "Bool" for argument "b" +"<unknown>:20:27: Invalid type "Bool" for argument "b", expected "Int" 19 | fun f2(a: Int): Int { > 20 | return self.f1(a, true); ^~~~ @@ -448,7 +448,7 @@ exports[`resolveStatements should fail statements for expr-method-does-not-exist `; exports[`resolveStatements should fail statements for expr-module-fun-call-bool-param 1`] = ` -"<unknown>:13:18: Invalid type "Bool" for argument "b" +"<unknown>:13:18: Invalid type "Bool" for argument "b", expected "Int" 12 | fun f2(a: Int): Int { > 13 | return f1(a, true); ^~~~ diff --git a/src/types/resolveExpression.ts b/src/types/resolveExpression.ts index d8981fe910..a6112e3e97 100644 --- a/src/types/resolveExpression.ts +++ b/src/types/resolveExpression.ts @@ -591,7 +591,7 @@ function resolveStaticCall( const t = getExpType(ctx, e); if (!isAssignable(t, a.type)) { throwCompilationError( - `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}`, + `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}, expected "${printTypeRef(a.type)}"`, e.loc, ); } @@ -658,7 +658,7 @@ function resolveCall( const t = getExpType(ctx, e); if (!isAssignable(t, a.type)) { throwCompilationError( - `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}`, + `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}, expected "${printTypeRef(a.type)}"`, e.loc, ); } @@ -783,7 +783,7 @@ function resolveInitOf( const t = getExpType(ctx, e); if (!isAssignable(t, a.type)) { throwCompilationError( - `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}`, + `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}, expected "${printTypeRef(a.type)}"`, e.loc, ); } From 4b99a9ea19f2e6fdcd18685d2e8af0b4ba82bff8 Mon Sep 17 00:00:00 2001 From: Gusarich <danielsedovzzz@gmail.com> Date: Fri, 7 Feb 2025 13:54:37 +0300 Subject: [PATCH 2/4] feat: update changelog --- dev-docs/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/dev-docs/CHANGELOG.md b/dev-docs/CHANGELOG.md index d4ed5e269a..33808ce7f9 100644 --- a/dev-docs/CHANGELOG.md +++ b/dev-docs/CHANGELOG.md @@ -47,6 +47,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Better error message for `extend function without parameters` error: PR [#1624](https://github.com/tact-lang/tact/pull/1624) - Don't generate `lazy_deployment_completed` by default: PR [#1717](https://github.com/tact-lang/tact/pull/1717) - Optimized `emptyCell()` and `emptySlice()` functions: PR [#1696](https://github.com/tact-lang/tact/pull/1696) +- Error message for invalid type for function argument now shows expected type: PR [#1738](https://github.com/tact-lang/tact/pull/1738) ### Fixed From dcdc51c9b59721eab692c0fddc2e4c776b34e234 Mon Sep 17 00:00:00 2001 From: Gusarich <danielsedovzzz@gmail.com> Date: Mon, 10 Feb 2025 11:58:18 +0300 Subject: [PATCH 3/4] feat: tweak the error message --- src/types/__snapshots__/resolveStatements.spec.ts.snap | 6 +++--- src/types/resolveExpression.ts | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/types/__snapshots__/resolveStatements.spec.ts.snap b/src/types/__snapshots__/resolveStatements.spec.ts.snap index 6d43a2e8ad..14a4765574 100644 --- a/src/types/__snapshots__/resolveStatements.spec.ts.snap +++ b/src/types/__snapshots__/resolveStatements.spec.ts.snap @@ -100,7 +100,7 @@ exports[`resolveStatements should fail statements for contract-getter-with-metho `; exports[`resolveStatements should fail statements for contract-initof-wrong-arg 1`] = ` -"<unknown>:26:25: Invalid type "String" for argument "owner", expected "Int" +"<unknown>:26:25: Cannot pass a value of type "String" to the parameter "owner" of type "Int" 25 | get fun newInit(): StateInit { > 26 | return initOf A("hello"); ^~~~~~~ @@ -385,7 +385,7 @@ exports[`resolveStatements should fail statements for expr-field-does-not-exist- `; exports[`resolveStatements should fail statements for expr-internal-fun-call-bool-param.tact 1`] = ` -"<unknown>:20:27: Invalid type "Bool" for argument "b", expected "Int" +"<unknown>:20:27: Cannot pass a value of type "Bool" to the parameter "b" of type "Int" 19 | fun f2(a: Int): Int { > 20 | return self.f1(a, true); ^~~~ @@ -448,7 +448,7 @@ exports[`resolveStatements should fail statements for expr-method-does-not-exist `; exports[`resolveStatements should fail statements for expr-module-fun-call-bool-param 1`] = ` -"<unknown>:13:18: Invalid type "Bool" for argument "b", expected "Int" +"<unknown>:13:18: Cannot pass a value of type "Bool" to the parameter "b" of type "Int" 12 | fun f2(a: Int): Int { > 13 | return f1(a, true); ^~~~ diff --git a/src/types/resolveExpression.ts b/src/types/resolveExpression.ts index a6112e3e97..1b33000a42 100644 --- a/src/types/resolveExpression.ts +++ b/src/types/resolveExpression.ts @@ -591,7 +591,7 @@ function resolveStaticCall( const t = getExpType(ctx, e); if (!isAssignable(t, a.type)) { throwCompilationError( - `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}, expected "${printTypeRef(a.type)}"`, + `Cannot pass a value of type "${printTypeRef(t)}" to the parameter ${idTextErr(a.name)} of type "${printTypeRef(a.type)}"`, e.loc, ); } @@ -658,7 +658,7 @@ function resolveCall( const t = getExpType(ctx, e); if (!isAssignable(t, a.type)) { throwCompilationError( - `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}, expected "${printTypeRef(a.type)}"`, + `Cannot pass a value of type "${printTypeRef(t)}" to the parameter ${idTextErr(a.name)} of type "${printTypeRef(a.type)}"`, e.loc, ); } @@ -783,7 +783,7 @@ function resolveInitOf( const t = getExpType(ctx, e); if (!isAssignable(t, a.type)) { throwCompilationError( - `Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}, expected "${printTypeRef(a.type)}"`, + `Cannot pass a value of type "${printTypeRef(t)}" to the parameter ${idTextErr(a.name)} of type "${printTypeRef(a.type)}"`, e.loc, ); } From 2c6c10a81694a77bd53f054f4469619518e8b7f6 Mon Sep 17 00:00:00 2001 From: Gusarich <danielsedovzzz@gmail.com> Date: Mon, 10 Feb 2025 15:54:51 +0300 Subject: [PATCH 4/4] feat: refactor check into a helper function & tweak the message --- .../resolveStatements.spec.ts.snap | 6 +-- src/types/resolveExpression.ts | 48 +++++++++---------- 2 files changed, 26 insertions(+), 28 deletions(-) diff --git a/src/types/__snapshots__/resolveStatements.spec.ts.snap b/src/types/__snapshots__/resolveStatements.spec.ts.snap index 14a4765574..f9a116b8c1 100644 --- a/src/types/__snapshots__/resolveStatements.spec.ts.snap +++ b/src/types/__snapshots__/resolveStatements.spec.ts.snap @@ -100,7 +100,7 @@ exports[`resolveStatements should fail statements for contract-getter-with-metho `; exports[`resolveStatements should fail statements for contract-initof-wrong-arg 1`] = ` -"<unknown>:26:25: Cannot pass a value of type "String" to the parameter "owner" of type "Int" +"<unknown>:26:25: Cannot pass an expression of type "String" to the parameter "owner" of type "Int" 25 | get fun newInit(): StateInit { > 26 | return initOf A("hello"); ^~~~~~~ @@ -385,7 +385,7 @@ exports[`resolveStatements should fail statements for expr-field-does-not-exist- `; exports[`resolveStatements should fail statements for expr-internal-fun-call-bool-param.tact 1`] = ` -"<unknown>:20:27: Cannot pass a value of type "Bool" to the parameter "b" of type "Int" +"<unknown>:20:27: Cannot pass an expression of type "Bool" to the parameter "b" of type "Int" 19 | fun f2(a: Int): Int { > 20 | return self.f1(a, true); ^~~~ @@ -448,7 +448,7 @@ exports[`resolveStatements should fail statements for expr-method-does-not-exist `; exports[`resolveStatements should fail statements for expr-module-fun-call-bool-param 1`] = ` -"<unknown>:13:18: Cannot pass a value of type "Bool" to the parameter "b" of type "Int" +"<unknown>:13:18: Cannot pass an expression of type "Bool" to the parameter "b" of type "Int" 12 | fun f2(a: Int): Int { > 13 | return f1(a, true); ^~~~ diff --git a/src/types/resolveExpression.ts b/src/types/resolveExpression.ts index 1b33000a42..b6c6be76d6 100644 --- a/src/types/resolveExpression.ts +++ b/src/types/resolveExpression.ts @@ -15,7 +15,12 @@ import { hasStaticConstant, hasStaticFunction, } from "./resolveDescriptors"; -import { printTypeRef, TypeRef, typeRefEquals } from "./types"; +import { + FunctionParameter, + printTypeRef, + TypeRef, + typeRefEquals, +} from "./types"; import { StatementContext } from "./resolveStatements"; import { MapFunctions } from "../abi/map"; import { GlobalFunctions } from "../abi/global"; @@ -526,6 +531,20 @@ function resolveFieldAccess( } } +function checkParameterType( + expression: A.AstExpression, + parameter: FunctionParameter, + ctx: CompilerContext, +) { + const t = getExpType(ctx, expression); + if (!isAssignable(t, parameter.type)) { + throwCompilationError( + `Cannot pass an expression of type "${printTypeRef(t)}" to the parameter ${idTextErr(parameter.name)} of type "${printTypeRef(parameter.type)}"`, + expression.loc, + ); + } +} + function resolveStaticCall( exp: A.AstStaticCall, sctx: StatementContext, @@ -587,14 +606,7 @@ function resolveStaticCall( ); } for (const [i, a] of f.params.entries()) { - const e = exp.args[i]!; - const t = getExpType(ctx, e); - if (!isAssignable(t, a.type)) { - throwCompilationError( - `Cannot pass a value of type "${printTypeRef(t)}" to the parameter ${idTextErr(a.name)} of type "${printTypeRef(a.type)}"`, - e.loc, - ); - } + checkParameterType(exp.args[i]!, a, ctx); } // Resolve return type @@ -654,14 +666,7 @@ function resolveCall( ); } for (const [i, a] of f.params.entries()) { - const e = exp.args[i]!; - const t = getExpType(ctx, e); - if (!isAssignable(t, a.type)) { - throwCompilationError( - `Cannot pass a value of type "${printTypeRef(t)}" to the parameter ${idTextErr(a.name)} of type "${printTypeRef(a.type)}"`, - e.loc, - ); - } + checkParameterType(exp.args[i]!, a, ctx); } return registerExpType(ctx, exp, f.returns); @@ -779,14 +784,7 @@ function resolveInitOf( ); } for (const [i, a] of type.init.params.entries()) { - const e = ast.args[i]!; - const t = getExpType(ctx, e); - if (!isAssignable(t, a.type)) { - throwCompilationError( - `Cannot pass a value of type "${printTypeRef(t)}" to the parameter ${idTextErr(a.name)} of type "${printTypeRef(a.type)}"`, - e.loc, - ); - } + checkParameterType(ast.args[i]!, a, ctx); } // Register return type