Skip to content

Commit 97864b8

Browse files
Gusarichgithub-actions[bot]
authored andcommitted
feat: include expected type for invalid type error message (tact-lang#1738)
1 parent ecae8d7 commit 97864b8

File tree

3 files changed

+27
-28
lines changed

3 files changed

+27
-28
lines changed

dev-docs/CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4848
- Don't generate `lazy_deployment_completed` by default: PR [#1717](https://github.com/tact-lang/tact/pull/1717)
4949
- Optimized `emptyCell()` and `emptySlice()` functions: PR [#1696](https://github.com/tact-lang/tact/pull/1696)
5050
- Rearrange parameters of some asm methods in order described in `AsmShuffle`: PR [#1702](https://github.com/tact-lang/tact/pull/1702)
51+
- Error message for invalid type for function argument now shows expected type: PR [#1738](https://github.com/tact-lang/tact/pull/1738)
5152

5253
### Fixed
5354

src/types/__snapshots__/resolveStatements.spec.ts.snap

+3-3
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ exports[`resolveStatements should fail statements for contract-getter-with-metho
100100
`;
101101

102102
exports[`resolveStatements should fail statements for contract-initof-wrong-arg 1`] = `
103-
"<unknown>:26:25: Invalid type "String" for argument "owner"
103+
"<unknown>:26:25: Cannot pass an expression of type "String" to the parameter "owner" of type "Int"
104104
25 | get fun newInit(): StateInit {
105105
> 26 | return initOf A("hello");
106106
^~~~~~~
@@ -385,7 +385,7 @@ exports[`resolveStatements should fail statements for expr-field-does-not-exist-
385385
`;
386386

387387
exports[`resolveStatements should fail statements for expr-internal-fun-call-bool-param.tact 1`] = `
388-
"<unknown>:20:27: Invalid type "Bool" for argument "b"
388+
"<unknown>:20:27: Cannot pass an expression of type "Bool" to the parameter "b" of type "Int"
389389
19 | fun f2(a: Int): Int {
390390
> 20 | return self.f1(a, true);
391391
^~~~
@@ -448,7 +448,7 @@ exports[`resolveStatements should fail statements for expr-method-does-not-exist
448448
`;
449449

450450
exports[`resolveStatements should fail statements for expr-module-fun-call-bool-param 1`] = `
451-
"<unknown>:13:18: Invalid type "Bool" for argument "b"
451+
"<unknown>:13:18: Cannot pass an expression of type "Bool" to the parameter "b" of type "Int"
452452
12 | fun f2(a: Int): Int {
453453
> 13 | return f1(a, true);
454454
^~~~

src/types/resolveExpression.ts

+23-25
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,12 @@ import {
1515
hasStaticConstant,
1616
hasStaticFunction,
1717
} from "./resolveDescriptors";
18-
import { printTypeRef, TypeRef, typeRefEquals } from "./types";
18+
import {
19+
FunctionParameter,
20+
printTypeRef,
21+
TypeRef,
22+
typeRefEquals,
23+
} from "./types";
1924
import { StatementContext } from "./resolveStatements";
2025
import { MapFunctions } from "../abi/map";
2126
import { GlobalFunctions } from "../abi/global";
@@ -526,6 +531,20 @@ function resolveFieldAccess(
526531
}
527532
}
528533

534+
function checkParameterType(
535+
expression: A.AstExpression,
536+
parameter: FunctionParameter,
537+
ctx: CompilerContext,
538+
) {
539+
const t = getExpType(ctx, expression);
540+
if (!isAssignable(t, parameter.type)) {
541+
throwCompilationError(
542+
`Cannot pass an expression of type "${printTypeRef(t)}" to the parameter ${idTextErr(parameter.name)} of type "${printTypeRef(parameter.type)}"`,
543+
expression.loc,
544+
);
545+
}
546+
}
547+
529548
function resolveStaticCall(
530549
exp: A.AstStaticCall,
531550
sctx: StatementContext,
@@ -587,14 +606,7 @@ function resolveStaticCall(
587606
);
588607
}
589608
for (const [i, a] of f.params.entries()) {
590-
const e = exp.args[i]!;
591-
const t = getExpType(ctx, e);
592-
if (!isAssignable(t, a.type)) {
593-
throwCompilationError(
594-
`Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}`,
595-
e.loc,
596-
);
597-
}
609+
checkParameterType(exp.args[i]!, a, ctx);
598610
}
599611

600612
// Resolve return type
@@ -654,14 +666,7 @@ function resolveCall(
654666
);
655667
}
656668
for (const [i, a] of f.params.entries()) {
657-
const e = exp.args[i]!;
658-
const t = getExpType(ctx, e);
659-
if (!isAssignable(t, a.type)) {
660-
throwCompilationError(
661-
`Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}`,
662-
e.loc,
663-
);
664-
}
669+
checkParameterType(exp.args[i]!, a, ctx);
665670
}
666671

667672
return registerExpType(ctx, exp, f.returns);
@@ -779,14 +784,7 @@ function resolveInitOf(
779784
);
780785
}
781786
for (const [i, a] of type.init.params.entries()) {
782-
const e = ast.args[i]!;
783-
const t = getExpType(ctx, e);
784-
if (!isAssignable(t, a.type)) {
785-
throwCompilationError(
786-
`Invalid type "${printTypeRef(t)}" for argument ${idTextErr(a.name)}`,
787-
e.loc,
788-
);
789-
}
787+
checkParameterType(ast.args[i]!, a, ctx);
790788
}
791789

792790
// Register return type

0 commit comments

Comments
 (0)