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