Skip to content

Commit

Permalink
[move-compiler-v2] fix issue 6922 by allowing type annotations for la…
Browse files Browse the repository at this point in the history
…mbda parameters (#14254)

Allowing declared type annotations for lambda parameters.

Fixes #6922.
  • Loading branch information
brmataptos authored Sep 20, 2024
1 parent 25499ae commit f5134a5
Show file tree
Hide file tree
Showing 98 changed files with 3,711 additions and 16 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@

Diagnostics:
warning: Unused parameter `f`. Consider removing or prefixing with an underscore: `_f`
┌─ tests/checking-lang-v1/eq_inline_typed.move:3:20
3 │ inline fun foo(f: |&u64|) {
│ ^

// -- Model dump before bytecode pipeline
module 0x42::m {
private inline fun foo(f: |&u64|) {
Tuple()
}
private fun g() {
Tuple();
Tuple()
}
} // end 0x42::m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
module 0x42::m {

inline fun foo(f: |&u64|) {
}

fun g() {
foo(|v: &u64| {
v == &1;
});
}


}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

Diagnostics:
error: Break outside of a loop not currently supported in inline functions
┌─ tests/checking/inlining/break_continue_in_lambda_typed.move:3:9
3 │ break;
│ ^^^^^

error: Break outside of a loop not supported in function-typed arguments (lambda expressions)
┌─ tests/checking/inlining/break_continue_in_lambda_typed.move:40:32
40 │ brk2(|_x: u64| break);
│ ^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
module 0xc0ffee::m {
inline fun brk() {
break;
}

inline fun brk2(f: |u64|) {
f(2);
}

inline fun brk3() {
while (true) {
break;
}
}

inline fun brk4() {
while (true) {
continue;
}
}

public fun foo(): u64 {
let i = 0;
while (i < 10) {
i = i + 1;
if (i == 5) {
brk();
brk3();
brk4();
}
};
i
}

public fun bar(): u64 {
let i = 0;
while (i < 10) {
i = i + 1;
if (i == 5) {
brk2(|_x: u64| break);
brk2(|_x: u64| while (true) { break });
brk2(|_x: u64| while (true) { continue });
}
};
i
}

fun broken() {
break;
}

fun continued() {
continue;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Diagnostics:
error: no function named `beans` found
┌─ tests/checking/inlining/cool_inlining_test_typed.move:15:22
15 │ foo(|_x: u8| beans())
│ ^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
module 0xc0ffee::cool {
public fun beans(): u64 {
42
}
}

module 0xc0ffee::m {
inline fun foo(f: |u8| u64): u64 {
use 0xc0ffee::cool::beans;
beans(); // discharge unused use warning
f(3)
}

public fun bar(): u64 {
foo(|_x: u8| beans())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@

Diagnostics:
error: Currently, a function-typed parameter to an inline function must be a literal lambda expression
┌─ tests/checking/inlining/lambda_param_typed.move:7:15
7 │ inline_apply(f, b)
│ ^

error: Currently, a function-typed parameter to an inline function must be a literal lambda expression
┌─ tests/checking/inlining/lambda_param_typed.move:11:16
11 │ inline_apply4(f, b)
│ ^
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
module 0x42::LambdaParam {
public inline fun inline_apply(f: |u64|u64, b: u64) : u64 {
f(b)
}

public inline fun inline_apply2(f: |u64|u64, b: u64) : u64 {
inline_apply(f, b)
}

public inline fun inline_apply3(f: |u64|u64, b: u64) : u64 {
inline_apply4(f, b)
}

public inline fun inline_apply4(_f: |u64|u64, b: u64) : u64 {
b
}

fun test_lambda_symbol_param1() {
let a = inline_apply2(|x: u64| x, 3);
assert!(a == 3, 0);
}

fun test_lambda_symbol_param2() {
let a = inline_apply2(|x: u64| x, 3);
assert!(a == 3, 0);
let b = inline_apply(|x: u64| x, 3);
assert!(b == 3, 0);
let b = inline_apply3(|x: u64| x, 3);
assert!(b == 3, 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

Diagnostics:
error: Return not currently supported in inline functions
┌─ tests/checking/inlining/lambda_return_typed.move:3:2
3 │ return f(b)
│ ^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
module 0x42::LambdaReturn {
public inline fun inline_apply2(f: |u64|u64, b: u64) : u64 {
return f(b)
}

fun test_lambda_symbol_param() {
let a = inline_apply2(|x: u64| { x }, 3);
assert!(a == 3, 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
// -- Model dump before bytecode pipeline
module 0x42::LambdaTest1 {
public inline fun inline_apply(f: |u64|u64,b: u64): u64 {
(f)(b)
}
public inline fun inline_apply1(f: |u64|u64,b: u64): u64 {
{
let (a: u64, b: u64): (u64, u64) = Tuple(Add<u64>((f)(b), 1), 12);
Mul<u64>(a, 12)
}
}
public inline fun inline_mul(a: u64,b: u64): u64 {
Mul<u64>(a, b)
}
} // end 0x42::LambdaTest1
module 0x42::LambdaTest2 {
use 0x42::LambdaTest1; // resolved as: 0x42::LambdaTest1
use std::vector;
public inline fun foreach<T>(v: &vector<#0>,action: |&#0|) {
{
let i: u64 = 0;
loop {
if Lt<u64>(i, vector::length<T>(v)) {
(action)(vector::borrow<T>(v, i));
i: u64 = Add<u64>(i, 1);
Tuple()
} else {
break
}
}
}
}
public inline fun inline_apply2(g: |u64|u64,c: u64): u64 {
Add<u64>({
let (b: u64): (u64) = Tuple((g)({
let (a: u64, b: u64): (u64, u64) = Tuple(c, 3);
Mul<u64>(a, 3)
}));
{
let (a: u64, b: u64): (u64, u64) = Tuple(Add<u64>({
let (z: u64): (u64) = Tuple(b);
z
}, 1), 12);
Mul<u64>(a, 12)
}
}, 2)
}
public inline fun inline_apply3(g: |u64|u64,c: u64): u64 {
Add<u64>(LambdaTest1::inline_apply1(g, LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x: u64| LambdaTest1::inline_apply(|y: u64| y, x), 3))), 4)
}
public fun test_inline_lambda() {
{
let product: u64 = 1;
{
let (v: &vector<u64>): (&vector<u64>) = Tuple(Borrow(Immutable)([Number(1), Number(2), Number(3)]));
{
let i: u64 = 0;
loop {
if Lt<u64>(i, vector::length<u64>(v)) {
{
let (e: &u64): (&u64) = Tuple(vector::borrow<u64>(v, i));
product: u64 = {
let (a: u64, b: u64): (u64, u64) = Tuple(product, Deref(e));
Mul<u64>(a, b)
}
};
i: u64 = Add<u64>(i, 1);
Tuple()
} else {
break
}
}
}
};
Tuple()
}
}
} // end 0x42::LambdaTest2
module 0x42::LambdaTest {
use 0x42::LambdaTest2; // resolved as: 0x42::LambdaTest2
public inline fun inline_apply(f: |u64|u64,b: u64): u64 {
(f)(b)
}
public inline fun inline_apply_test(): u64 {
1120
}
private fun test_lambda() {
if false {
Tuple()
} else {
Abort(0)
};
Tuple()
}
} // end 0x42::LambdaTest


============ bytecode verification succeeded ========
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module 0x42::LambdaTest1 {
public inline fun inline_mul(a: u64, b: u64): u64 {
a * b
}

public inline fun inline_apply1(f: |u64|u64, b: u64) : u64 {
inline_mul(f(b) + 1, inline_mul(3, 4))
}

public inline fun inline_apply(f: |u64|u64, b: u64) : u64 {
f(b)
}
}

module 0x42::LambdaTest2 {
use 0x42::LambdaTest1;
use std::vector;

public inline fun foreach<T>(v: &vector<T>, action: |&T|) { // expected to be not implemented
let i = 0;
while (i < vector::length(v)) {
action(vector::borrow(v, i));
i = i + 1;
}
}

public fun test_inline_lambda() {
let v = vector[1, 2, 3];
let product = 1;
foreach(&v, |e: &u64| product = LambdaTest1::inline_mul(product, *e));
}

public inline fun inline_apply2(g: |u64|u64, c: u64) : u64 {
LambdaTest1::inline_apply1(|z: u64|z, g(LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x: u64|x, 3)))) + 2
}

public inline fun inline_apply3(g: |u64|u64, c: u64) : u64 {
LambdaTest1::inline_apply1(g,
LambdaTest1::inline_mul(c, LambdaTest1::inline_apply(|x:u64| {
LambdaTest1::inline_apply(|y: u64|y, x)
},
3))) + 4
}
}

module 0x42::LambdaTest {
use 0x42::LambdaTest2;

public inline fun inline_apply(f: |u64|u64, b: u64) : u64 {
f(b)
}

public inline fun inline_apply_test() : u64 {
LambdaTest2::inline_apply2(|x: u64| x + 1, 3) +
LambdaTest2::inline_apply2(|x: u64| x * x, inline_apply(|y: u64|y, 3))
}

fun test_lambda() {
let a = inline_apply_test();
assert!(a == 1, 0);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@

Diagnostics:
error: Return not currently supported in function-typed arguments (lambda expressions)
┌─ tests/checking/inlining/return_in_lambda_typed.move:13:13
13 │ return adder(x, y)
│ ^^^^^^^^^^^^^^^^^^

error: Return not currently supported in function-typed arguments (lambda expressions)
┌─ tests/checking/inlining/return_in_lambda_typed.move:16:13
16 │ return adder(x, y)
│ ^^^^^^^^^^^^^^^^^^

error: Return not currently supported in function-typed arguments (lambda expressions)
┌─ tests/checking/inlining/return_in_lambda_typed.move:19:13
19 │ return adder(x, y)
│ ^^^^^^^^^^^^^^^^^^
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
module 0x42::Test {

inline fun apply(f:|u64, u64| u64, x: u64, y: u64): u64 {
f(x, y)
}

inline fun adder(x: u64, y: u64): u64 {
x + y
}

public fun main(): u64 {
apply(|x: u64, y: u64| {
return adder(x, y)
}, 10, 100);
apply(|x: u64, y| {
return adder(x, y)
}, 10, 100);
apply(|x, y: u64| {
return adder(x, y)
}, 10, 100)
}
}
Loading

0 comments on commit f5134a5

Please sign in to comment.