Skip to content

Commit

Permalink
fix: disallow comparisons of null with non-optional types (tact-lang#571
Browse files Browse the repository at this point in the history
)

Co-authored-by: Anton Trunov <[email protected]>
  • Loading branch information
Gusarich and anton-trunov authored Jul 19, 2024
1 parent 88cbdcd commit 72665ba
Show file tree
Hide file tree
Showing 18 changed files with 381 additions and 70 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- All identifiers in error messages are now quoted for consistency: PR [#363](https://github.com/tact-lang/tact/pull/363)
- The Tact grammar has been refactored for better readability: PR [#365](https://github.com/tact-lang/tact/pull/365)
- Error messages now use relative file paths: PR [#456](https://github.com/tact-lang/tact/pull/456)
- Comparison between `null` and non-optionals now throws a compilation error: PR [#571](https://github.com/tact-lang/tact/pull/571)

### Fixed

Expand Down
14 changes: 7 additions & 7 deletions src/test/e2e-emulated/__snapshots__/sample-jetton.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,19 @@ exports[`bugs should deploy sample jetton correctly 1`] = `
"$type": "received",
"message": {
"body": {
"cell": "x{178D45190000000000000000502540BE400800F4E48F7C7669DBB98B5860A3DF843B6A47BE760733A53682DC8C2D7888E272890016E3A425A4E75B646191AC9A34FE5D050BD101A5C490F87D01C66D885D09BC1082_}",
"cell": "x{178D45190000000000000000502540BE400801F9508078B18164B590F620AAE2DF1AD4044D12F868972380370D0DB9DF1646D30016E3A425A4E75B646191AC9A34FE5D050BD101A5C490F87D01C66D885D09BC1082_}",
"type": "cell",
},
"bounce": false,
"from": "kQB6cke-OzTt3MWsMFHvwh21I987A5nSm0FuRha8RHE5RLcf",
"to": "kQAs-ScGiWnp9mLiF2J01NJKNIqVEKcmrFCZJBm9zSs-z5mo",
"from": "kQD8qEA8WMCyWsh7EFVxb41qAiaJfDRLkcAbhobc74sjadtu",
"to": "kQD_kli7qXhKTyPFPipl-Ck2p0dQI88j6_0nqo_U79hCL7zM",
"type": "internal",
"value": "9.961639",
"value": "9.961192",
},
},
{
"$type": "processed",
"gasUsed": 12277n,
"gasUsed": 12484n,
},
{
"$type": "sent",
Expand All @@ -38,10 +38,10 @@ exports[`bugs should deploy sample jetton correctly 1`] = `
},
},
"bounce": false,
"from": "kQAs-ScGiWnp9mLiF2J01NJKNIqVEKcmrFCZJBm9zSs-z5mo",
"from": "kQD_kli7qXhKTyPFPipl-Ck2p0dQI88j6_0nqo_U79hCL7zM",
"to": "@treasure(treasure)",
"type": "internal",
"value": "9.920430846",
"value": "9.919639844",
},
],
},
Expand Down
6 changes: 3 additions & 3 deletions src/test/e2e-emulated/contracts/sample-jetton.tact
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ message(0xf8a7ea5) TokenTransfer {
queryId: Int as uint64;
amount: Int as coins;
destination: Address;
response_destination: Address;
response_destination: Address?;
custom_payload: Cell?;
forward_ton_amount: Int as coins;
forward_payload: Slice as remaining;
Expand All @@ -150,7 +150,7 @@ message(0x178d4519) TokenTransferInternal {
queryId: Int as uint64;
amount: Int as coins;
from: Address;
response_destination: Address;
response_destination: Address?;
forward_ton_amount: Int as coins;
forward_payload: Slice as remaining;
}
Expand Down Expand Up @@ -265,7 +265,7 @@ contract JettonDefaultWallet {

if (msg.response_destination != null) { // Cashback
send(SendParameters {
to: msg.response_destination,
to: msg.response_destination!!,
value: msgValue,
bounce: false,
body: TokenExcesses { // 0xd53276db
Expand Down
201 changes: 201 additions & 0 deletions src/types/__snapshots__/resolveStatements.spec.ts.snap
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,17 @@ Line 5, col 12:
"
`;
exports[`resolveStatements should fail statements for expr-cmp-bounced 1`] = `
"<unknown>:6:10: Expressions of "bounced<S>" type cannot be used for (non)equality operator "=="
See https://docs.tact-lang.org/book/operators#binary-equality
Line 6, col 10:
5 | fun foo(b: bounced<S>): Bool {
> 6 | return b == b;
^~~~~~
7 | }
"
`;
exports[`resolveStatements should fail statements for expr-cmp-int-bool 1`] = `
"<unknown>:5:12: Incompatible types "Int" and "Bool" for binary operator "=="
Line 5, col 12:
Expand All @@ -40,8 +51,84 @@ Line 5, col 12:
"
`;
exports[`resolveStatements should fail statements for expr-cmp-map-map 1`] = `
"<unknown>:6:12: Incompatible types "map<Int, Address>" and "map<Address, Int>" for binary operator "=="
Line 6, col 12:
5 | fun foo(m1: map<Int, Address>, m2: map<Address, Int>): Bool {
> 6 | return m1 == m2;
^~~~~~~~
7 | }
"
`;
exports[`resolveStatements should fail statements for expr-cmp-null-1 1`] = `
"<unknown>:18:13: Expressions of "S" type cannot be used for (non)equality operator "!="
See https://docs.tact-lang.org/book/operators#binary-equality
Line 18, col 13:
17 | get fun test(): Int {
> 18 | if (self.s != null) {
^~~~~~~~~~~~~~
19 | return self.s.a;
"
`;
exports[`resolveStatements should fail statements for expr-cmp-null-2 1`] = `
"<unknown>:18:13: Expressions of "S" type cannot be used for (non)equality operator "!="
See https://docs.tact-lang.org/book/operators#binary-equality
Line 18, col 13:
17 | get fun test(): Int {
> 18 | if (null != self.s) {
^~~~~~~~~~~~~~
19 | return self.s.a;
"
`;
exports[`resolveStatements should fail statements for expr-cmp-null-3 1`] = `
"<unknown>:5:9: Incompatible types "<null>" and "Int" for binary operator "=="
Line 5, col 9:
4 | let x: Int = 42;
> 5 | if (null == x) { return }
^~~~~~~~~
6 | }
"
`;
exports[`resolveStatements should fail statements for expr-cmp-null-bounced 1`] = `
"<unknown>:7:10: Expressions of "bounced<S>" type cannot be used for (non)equality operator "=="
See https://docs.tact-lang.org/book/operators#binary-equality
Line 7, col 10:
6 | fun foo(b: bounced<S>): Bool {
> 7 | return b == null;
^~~~~~~~~
8 | }
"
`;
exports[`resolveStatements should fail statements for expr-cmp-optional-struct-null 1`] = `
"<unknown>:7:16: Expressions of "S" type cannot be used for (non)equality operator "=="
See https://docs.tact-lang.org/book/operators#binary-equality
Line 7, col 16:
6 | if (s != null) {
> 7 | return s!! == null
^~~~~~~~~~~
8 | }
"
`;
exports[`resolveStatements should fail statements for expr-cmp-void-null 1`] = `
"<unknown>:6:12: Expressions of "<void>" type cannot be used for (non)equality operator "=="
See https://docs.tact-lang.org/book/operators#binary-equality
Line 6, col 12:
5 | fun baz(): Bool {
> 6 | return foo() == null
^~~~~~~~~~~~~
7 | }
"
`;
exports[`resolveStatements should fail statements for expr-cmp-void1 1`] = `
"<unknown>:7:12: Expressions of "<void>" type cannot be used for (non)equality operator "=="
See https://docs.tact-lang.org/book/operators#binary-equality
Line 7, col 12:
6 | fun baz(): Bool {
> 7 | return foo() == bar()
Expand All @@ -52,6 +139,7 @@ Line 7, col 12:
exports[`resolveStatements should fail statements for expr-cmp-void2 1`] = `
"<unknown>:7:12: Expressions of "<void>" type cannot be used for (non)equality operator "!="
See https://docs.tact-lang.org/book/operators#binary-equality
Line 7, col 12:
6 | fun baz(): Bool {
> 7 | return foo() != bar()
Expand Down Expand Up @@ -950,6 +1038,119 @@ exports[`resolveStatements should resolve statements for expr-cmp-literal 1`] =
]
`;
exports[`resolveStatements should resolve statements for expr-cmp-map-map 1`] = `
[
[
"m1",
"map<Int, Address>",
],
[
"m2",
"map<Int, Address>",
],
[
"m1 == m2",
"Bool",
],
]
`;
exports[`resolveStatements should resolve statements for expr-cmp-map-null 1`] = `
[
[
"m",
"map<Int, Address>",
],
[
"null",
"<null>",
],
[
"m == null",
"Bool",
],
]
`;
exports[`resolveStatements should resolve statements for expr-cmp-null-null 1`] = `
[
[
"null",
"<null>",
],
[
"null",
"<null>",
],
[
"null == null",
"Bool",
],
]
`;
exports[`resolveStatements should resolve statements for expr-cmp-optional-null 1`] = `
[
[
"42",
"Int",
],
[
"null",
"<null>",
],
[
"x",
"Int?",
],
[
"null == x",
"Bool",
],
]
`;
exports[`resolveStatements should resolve statements for expr-cmp-optional-struct-null 1`] = `
[
[
"s",
"S?",
],
[
"null",
"<null>",
],
[
"s != null",
"Bool",
],
[
"s",
"S?",
],
[
"s!!",
"S",
],
[
"s!!.f",
"Int",
],
[
"42",
"Int",
],
[
"s!!.f == 42",
"Bool",
],
[
"false",
"Bool",
],
]
`;
exports[`resolveStatements should resolve statements for expr-conditional-with-subtyping 1`] = `
[
[
Expand Down
Loading

0 comments on commit 72665ba

Please sign in to comment.