Skip to content

Commit 4d59949

Browse files
committed
[Tolk] Enhance overload resolution rules for method receivers
This commit focuses on overload resolution for generic methods: strict ordering, type shapes, etc.
1 parent 7b89b2a commit 4d59949

19 files changed

+717
-103
lines changed

tolk-tester/tests/invalid-semantics/err-4104.tolk

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ fun Container<T?>.createFrom<U>(item: U): Container<T?> {
88

99
fun cantUseAsNonCall() {
1010
Container<int?>.createFrom<slice>; // ok
11-
Container<slice>.createFrom<Container<int>>; // ok
11+
Container<slice?>.createFrom<Container<int>>; // ok
1212

1313
Container<int?>.createFrom;
1414
}
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
struct Wrapper<T> { item: T }
2+
3+
type AssetBuilder = builder
4+
type BalanceBuilder = builder
5+
6+
fun Wrapper<AssetBuilder>.validate(self) { return 0 }
7+
8+
fun main() {
9+
var b: BalanceBuilder = beginCell();
10+
Wrapper{item:b}.validate();
11+
}
12+
13+
/**
14+
@compilation_should_fail
15+
@stderr method `validate` not found for type `Wrapper<BalanceBuilder>`
16+
@stderr but it exists for type `Wrapper<AssetBuilder>`
17+
*/
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun int.realValue(self): int8 { return 1 }
2+
fun int?.realValue(self): uint256 { return 1 }
3+
4+
fun main() {
5+
(5 as int8).realValue();
6+
}
7+
8+
/**
9+
@compilation_should_fail
10+
@stderr call to method `realValue` for type `int8` is ambiguous
11+
@stderr candidate function: `int.realValue`
12+
@stderr candidate function: `int?.realValue`
13+
*/
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
fun int8.doSome2() {}
2+
fun int16.doSome2() {}
3+
4+
fun main() {
5+
int.doSome2();
6+
}
7+
8+
/**
9+
@compilation_should_fail
10+
@stderr call to method `doSome2` for type `int` is ambiguous
11+
@stderr candidate function: `int8.doSome2`
12+
@stderr candidate function: `int16.doSome2`
13+
*/
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
struct MyMap<K, V>
2+
3+
fun MyMap<K, slice>.amb(self) { return 0 }
4+
fun MyMap<int, V>.amb(self) { return 0 }
5+
6+
fun main() {
7+
MyMap<int8, slice>{}.amb(); // ok
8+
MyMap<int, slice?>{}.amb(); // ok
9+
10+
MyMap<int, slice>{}.amb();
11+
}
12+
13+
/**
14+
@compilation_should_fail
15+
@stderr call to method `amb` for type `MyMap<int, slice>` is ambiguous
16+
@stderr candidate function: `MyMap<K,slice>.amb` with K=`int`
17+
@stderr candidate function: `MyMap<int,V>.amb` with V=`slice`
18+
*/
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
struct MyMap<K, V>
2+
3+
fun MyMap<K, slice>.amb(self) { return 0 }
4+
fun MyMap<int, V>.amb(self) { return 0 }
5+
6+
fun main() {
7+
MyMap<(int, int, MyMap<int, coins>), slice>{}.amb(); // ok
8+
MyMap<int, cell|()>{}.amb(); // ok
9+
10+
MyMap<cell, builder>{}.amb();
11+
}
12+
13+
/**
14+
@compilation_should_fail
15+
@stderr method `amb` not found for type `MyMap<cell, builder>`
16+
@stderr (but it exists for type `MyMap<K, slice>`)
17+
*/
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
type AssetBuilder = builder
2+
type BalanceBuilder = builder
3+
4+
fun AssetBuilder.validate(self) { return 0 }
5+
fun BalanceBuilder.validate(self) { return 0 }
6+
7+
fun main() {
8+
(beginCell() as AssetBuilder).validate(); // ok
9+
(beginCell() as BalanceBuilder).validate(); // ok
10+
11+
beginCell().validate();
12+
}
13+
14+
/**
15+
@compilation_should_fail
16+
@stderr call to method `validate` for type `builder` is ambiguous
17+
@stderr candidate function: `AssetBuilder.validate`
18+
@stderr candidate function: `BalanceBuilder.validate`
19+
*/
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
struct Wrapper<T> { item: T; }
2+
fun Wrapper<T?>.createNull(): Wrapper<T?> { return { item: null } }
3+
4+
fun main() {
5+
Wrapper<int>.createNull();
6+
}
7+
8+
/**
9+
@compilation_should_fail
10+
@stderr method `createNull` not found for type `Wrapper<int>`
11+
@stderr (but it exists for type `Wrapper<T?>`)
12+
*/
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
struct Point {
2+
x: int8
3+
y: int8
4+
}
5+
6+
fun Cell<T>.myMethod<U>(self, v: U): int
7+
asm "DROP" "HASHCU"
8+
9+
fun main() {
10+
Point{x:10,y:20}.toCell().myMethod(4); // ok
11+
Point{x:10,y:20}.toCell().myMethod((4, 5));
12+
}
13+
14+
/**
15+
@compilation_should_fail
16+
@stderr can not call `Cell<T>.myMethod<U>` with U=(int, int), because it occupies 2 stack slots in TVM, not 1
17+
*/

tolk-tester/tests/methods-tests.tolk

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -191,11 +191,11 @@ fun T?.arbitraryMethod(self): never { throw 123; }
191191

192192
fun test12() {
193193
__expect_type(10.arbitraryMethod(), "int?");
194-
__expect_type((10 as int8?).arbitraryMethod(), "int?");
195194
__expect_type((10 as coins?)!.arbitraryMethod(), "int?");
196195

197-
__expect_type(null.arbitraryMethod(), "int?");
198-
__expect_type((10 as coins?).arbitraryMethod(), "int?");
196+
__expect_type((10 as int8?).arbitraryMethod(), "never");
197+
__expect_type(null.arbitraryMethod(), "never");
198+
__expect_type((10 as coins?).arbitraryMethod(), "never");
199199

200200
__expect_type(Wrapper { item: 10 }.arbitraryMethod(), "Wrapper<MInt>");
201201
__expect_type(Wrapper<int> { item: 10 as int8 }.arbitraryMethod(), "Wrapper<MInt>");
@@ -280,7 +280,7 @@ fun Wrapper<T>.createFrom<U>(item: U): Wrapper<T> { return {item}; }
280280
fun test18() {
281281
__expect_type(10.copy, "(int) -> int");
282282
__expect_type(Wrapper{item:null as int8?}.copy, "(Wrapper<int8?>) -> Wrapper<int8?>");
283-
__expect_type(Wrapper<int>.createNull, "() -> Wrapper<int?>");
283+
__expect_type(Wrapper<int?>.createNull, "() -> Wrapper<int?>");
284284
__expect_type(Wrapper<Wrapper<slice?>?>.createNull, "() -> Wrapper<Wrapper<slice?>?>");
285285
__expect_type(Wrapper<int?>.createFrom<int8>, "(int8) -> Wrapper<int?>");
286286

@@ -319,7 +319,7 @@ fun main() {}
319319
@testcase | 107 | | 2 1 -1
320320
@testcase | 108 | 5 | 17 5
321321
@testcase | 109 | | 5 100500 20 30 5 5 31
322-
@testcase | 110 | | [ 2 3 1 1 3 1 1 ] -1
322+
@testcase | 110 | | [ 2 3 1 1 1 1 1 ] -1
323323
@testcase | 111 | | [ 1 2 3 3 2 ]
324324
@testcase | 113 | | 0 -1 -1 -1 0 -1
325325
@testcase | 114 | | -1 -1 0 0 0

0 commit comments

Comments
 (0)