//! > Test closure wrong return type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
|| -> i32 {
let d: u32 = 3;
d
};
}
//! > function_name
foo
//! > expected_diagnostics
error[E2042]: Unexpected return type. Expected: "core::integer::i32", found: "core::integer::u32".
--> lib.cairo:2:11
|| -> i32 {
^^^
//! > ==========================================================================
//! > Test closure inferred param type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > function_code
fn foo() {
|a| -> i32 {
let d: i32 = a;
d
};
}
//! > function_name
foo
//! > expected_diagnostics
//! > ==========================================================================
//! > Test closure typed param type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
|a: u32| -> i32 {
let d: i32 = a;
d
};
}
//! > function_name
foo
//! > expected_diagnostics
error[E2041]: Unexpected argument type. Expected: "core::integer::i32", found: "core::integer::u32".
--> lib.cairo:3:22
let d: i32 = a;
^
//! > ==========================================================================
//! > Test assignment wrong type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let _x: i32 = || {
let d: u32 = 3;
d
};
}
//! > function_name
foo
//! > expected_diagnostics
error[E2041]: Unexpected argument type. Expected: "core::integer::i32", found: "{closure@lib.cairo:2:19: 2:21}".
--> lib.cairo:2:19-5:5
let _x: i32 = || {
___________________^
| ...
| };
|_____^
//! > ==========================================================================
//! > Test closure in global context.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {}
//! > function_name
foo
//! > module_code
const _x: i32 = || {
let d: u32 = 3;
d
};
//! > expected_diagnostics
error[E2182]: Closures are not allowed in this context.
--> lib.cairo:1:17-4:1
const _x: i32 = || {
_________________^
| ...
| };
|_^
error[E2302]: Type mismatch: `{closure@lib.cairo:1:17: 1:19}` and `core::integer::i32`.
--> lib.cairo:1:1-4:2
const _x: i32 = || {
_^
| ...
| };
|__^
//! > ==========================================================================
//! > Test closure in generic const context.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
bar::<{ || -> u32 {
2
} }>();
}
//! > function_name
foo
//! > module_code
fn bar<const N: u32>() {}
//! > expected_diagnostics
error[E2182]: Closures are not allowed in this context.
--> lib.cairo:3:13-5:5
bar::<{ || -> u32 {
_____________^
| 2
| } }>();
|_____^
error[E2302]: Type mismatch: `{closure@lib.cairo:3:13: 3:15}` and `core::integer::u32`.
--> lib.cairo:3:11-5:7
bar::<{ || -> u32 {
___________^
| 2
| } }>();
|_______^
//! > ==========================================================================
//! > Test closure params need type annotations.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
|a| {
let d = a;
d
};
}
//! > function_name
foo
//! > expected_diagnostics
error[E2314]: Type annotations needed. Failed to infer ?0.
--> lib.cairo:2:7
|a| {
^
//! > ==========================================================================
//! > Test closure infer type from impl.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > function_code
fn foo() {
let c = |a| {
let d = a;
d.into()
};
let _k: felt252 = bar(c);
}
//! > function_name
foo
//! > module_code
fn bar<T, +core::ops::FnOnce<T, (u32,)>>(c: T) -> core::ops::FnOnce::<T, (u32,)>::Output {
core::ops::FnOnce::call(c, (2,))
}
//! > expected_diagnostics
//! > ==========================================================================
//! > Test closure infer type from impl wrong param.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let c = |a| {
let d = a;
d.into()
};
let _f: felt252 = core::ops::FnOnce::call(c, (2_u64,));
let _k: felt252 = bar(c);
}
//! > function_name
foo
//! > module_code
fn bar<T, +core::ops::FnOnce<T, (u32,)>>(c: T) -> core::ops::FnOnce::<T, (u32,)>::Output {
core::ops::FnOnce::call(c, (2,))
}
//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: core::ops::function::FnOnce::<{closure@lib.cairo:5:13: 5:16}, (core::integer::u32,)>.
--> lib.cairo:10:23
let _k: felt252 = bar(c);
^^^
//! > ==========================================================================
//! > Test closure infer type from impl wrong return type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let c = |a| {
let d = a;
d.into()
};
let _f: u128 = core::ops::FnOnce::call(c, (2,));
let _k: felt252 = bar(c);
}
//! > function_name
foo
//! > module_code
fn bar<T, +core::ops::FnOnce<T, (u32,)>>(c: T) -> core::ops::FnOnce::<T, (u32,)>::Output {
core::ops::FnOnce::call(c, (2,))
}
//! > expected_diagnostics
error[E2308]: `core::ops::function::FnOnceImpl::<{closure@lib.cairo:5:13: 5:16}, (core::integer::u32,), core::traits::DestructFromDrop::<{closure@lib.cairo:5:13: 5:16}, Generated core::traits::Drop::<{closure@lib.cairo:5:13: 5:16}>>, Generated core::ops::function::Fn::<{closure@lib.cairo:5:13: 5:16}, (core::integer::u32,)>>::Output` type mismatch: `core::integer::u128` and `core::felt252`.
--> lib.cairo:9:39
let _f: u128 = core::ops::FnOnce::call(c, (2,));
^^^^
//! > ==========================================================================
//! > Test closure calling.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > function_code
fn foo() {
let c = |a, b, c| {
a.into() + b.into() + c.into()
};
let _f: u256 = c(2_felt252, 2_u256, 6_u64);
}
//! > function_name
foo
//! > expected_diagnostics
//! > ==========================================================================
//! > Test closure calling with diagnostics.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let c = |a, b, c| {
a.into() + b.into() + c.into()
};
let _f: u32 = c(2_felt252, 2_u256, 6_u64);
}
//! > function_name
foo
//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: core::traits::Into::<core::integer::u256, core::integer::u32>.
--> lib.cairo:3:22
a.into() + b.into() + c.into()
^^^^
//! > ==========================================================================
//! > Test shadowing of a function with a variable.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: warnings_only)
//! > function_code
fn foo() {
let bar: u8 = 3;
let _f: u32 = bar(2);
}
//! > function_name
foo
//! > module_code
fn bar() -> u32 {
2
}
//! > expected_diagnostics
warning[E2184]: Function `bar` is shadowed by a local variable.
--> lib.cairo:6:19
let _f: u32 = bar(2);
^^^
//! > ==========================================================================
//! > Test shadowing of a function with a variable when closure are in context.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let _y: u16 = baz(|a| {
a.into()
});
}
//! > function_name
foo
//! > module_code
fn bar() -> u32 {
2
}
fn baz<T, +core::ops::FnOnce<T, (u32,)>>(c: T) -> core::ops::FnOnce::<T, (u32,)>::Output {
let bar = 3;
let _x: u32 = bar();
c(9)
}
//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: core::ops::function::Fn::<core::felt252, ()>.
--> lib.cairo:7:19
let _x: u32 = bar();
^^^^^
error[E2311]: Trait has no implementation in context: core::traits::Into::<core::integer::u32, core::integer::u16>.
--> lib.cairo:12:11
a.into()
^^^^
//! > ==========================================================================
//! > Test shadowing of a function with a closure.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let bar = |_a, _b, _c| -> u32 {
3
};
let _f: u32 = bar(2);
}
//! > function_name
foo
//! > module_code
fn bar(a: felt252) -> u32 {
2
}
//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: core::ops::function::Fn::<{closure@lib.cairo:5:15: 5:27}, (core::felt252,)>.
--> lib.cairo:8:19
let _f: u32 = bar(2);
^^^^^^
//! > ==========================================================================
//! > Closure ref argument.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let bar = |a| -> u32 {
a
};
let a = 5;
let _f: u32 = bar(ref a);
}
//! > function_name
foo
//! > expected_diagnostics
error[E2185]: Arguments to closure functions cannot be references
--> lib.cairo:6:23
let _f: u32 = bar(ref a);
^^^^^
//! > ==========================================================================
//! > Closure with return statement argument.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > function_code
fn foo() {
let bar = |a| {
return a;
};
let a = 5;
let _f: u32 = bar(a);
}
//! > function_name
foo
//! > expected_diagnostics
//! > ==========================================================================
//! > Closure with option propagation.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > function_code
fn foo() {
let bar = |a: Option<u32>| -> Option<u32> {
Some(a?)
};
let a = Some(5);
let _f: u32 = bar(a).unwrap();
}
//! > function_name
foo
//! > expected_diagnostics
//! > ==========================================================================
//! > Closure with option propagation inference required.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
//TODO(Tomer): Add support for inference of Option type in closures.
fn foo() {
let bar1 = |a| -> Option<u32> {
Some(a?)
};
let bar2 = |b: Option<u32>| {
Some(b?)
};
let a = Some(5);
let _f: u32 = bar(a).unwrap();
let _f: u32 = bar2(a).unwrap();
}
//! > function_name
foo
//! > expected_diagnostics
error[E2063]: Type "?0" cannot error propagate
--> lib.cairo:4:14
Some(a?)
^^
error[E2061]: `?` can only be used in a function with `Option` or `Result` return type.
--> lib.cairo:7:14
Some(b?)
^^
warning[E0001]: Unused variable. Consider ignoring by prefixing with `_`.
--> lib.cairo:6:17
let bar2 = |b: Option<u32>| {
^^^^^^^^^^^^^^
error[E0006]: Function not found.
--> lib.cairo:10:19
let _f: u32 = bar(a).unwrap();
^^^
error[E2046]: Ambiguous method call. More than one applicable trait function with a suitable self type was found: OptionTrait::unwrap and ResultTrait::unwrap. Consider adding type annotations or explicitly refer to the impl function.
--> lib.cairo:10:26
let _f: u32 = bar(a).unwrap();
^^^^^^
warning[E0001]: Unused variable. Consider ignoring by prefixing with `_`.
--> lib.cairo:3:9
let bar1 = |a| -> Option<u32> {
^^^^
//! > ==========================================================================
//! > break inside a closure.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
loop {
let c = || {
break;
};
c();
}
}
//! > function_name
foo
//! > expected_diagnostics
error[E2146]: `break` only allowed inside a `loop`.
--> lib.cairo:4:13
break;
^^^^^^
//! > ==========================================================================
//! > continue inside a closure.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
loop {
let c = || {
continue;
};
c();
}
}
//! > function_name
foo
//! > expected_diagnostics
error[E2145]: `continue` only allowed inside a `loop`.
--> lib.cairo:4:13
continue;
^^^^^^^^^
//! > ==========================================================================
//! > capturing mutable variables.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let mut a = 5;
let b = a;
|| -> u32 {
a + b
};
}
//! > function_name
foo
//! > expected_diagnostics
error[E2188]: Capture of mutable variables in a closure is not supported
--> lib.cairo:5:9
a + b
^
//! > ==========================================================================
//! > Not generating destruct impl when drop impl exists.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > function_code
fn foo() {
bar(|| {});
}
//! > function_name
foo
//! > module_code
fn bar<T, +Destruct<T>>(a: T) {}
//! > expected_diagnostics
//! > ==========================================================================
//! > Calling a non closure type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let _y = || 2;
let x: u32 = 5;
x()
}
//! > function_name
foo
//! > expected_diagnostics
error[E2138]: Call expression requires a function, found `core::integer::u32`.
Candidate `core::ops::function::FnOnce::call` inference failed with: Trait has no implementation in context: core::ops::function::FnOnce::<core::integer::u32, ?4>.
--> lib.cairo:4:5
x()
^^^
//! > ==========================================================================
//! > Implementing a closure trait.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() -> u32 {
let _y = || 2;
let x: u32 = 5;
x()
}
//! > function_name
foo
//! > module_code
impl MyImpl of core::ops::FnOnce<u32, ()> {
type Output = u32;
fn call(self: u32, args: ()) -> u32 {
self
}
}
//! > expected_diagnostics
error[E2181]: Trait `core::ops::function::FnOnce` should not be implemented outside of the corelib.
--> lib.cairo:1:16
impl MyImpl of core::ops::FnOnce<u32, ()> {
^^^^^^^^^^^^^^^^^^^^^^^^^^
//! > ==========================================================================
//! > Mutating non mutable closure param.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let _ = |a| {
a = a + 2
};
}
//! > function_name
foo
//! > expected_diagnostics
error[E2083]: Cannot assign to an immutable variable.
--> lib.cairo:3:9
a = a + 2
^^^^^^^^^
//! > ==========================================================================
//! > Closures with ref arguments.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let _ = |ref a| {
a = a + 2
};
}
//! > function_name
foo
//! > expected_diagnostics
error[E2186]: Closure parameters cannot be references
--> lib.cairo:2:14
let _ = |ref a| {
^^^^^
//! > ==========================================================================
//! > Passing closures as args with less explicit typing.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > function_code
fn foo() -> Option<u32> {
let x: Option<Array<i32>> = Some(array![1, 2, 3]);
x.map(|x| x.len())
}
//! > function_name
foo
//! > expected_diagnostics
//! > ==========================================================================
//! > Passing closures as trait generics with less explicit typing.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
MyTrait::call_with(|arr| {
arr.len();
});
}
//! > function_name
foo
//! > module_code
trait MyTrait<F, +core::ops::Fn<F, (Array::<i32>,)>> {
fn call_with(func: F) {
func(ArrayTrait::<i32>::new());
}
}
impl MyImpl<F, impl Func: core::ops::Fn<F, (Array::<i32>,)>> of MyTrait<F, Func>;
//! > expected_diagnostics
error[E2046]: Ambiguous method call. More than one applicable trait function with a suitable self type was found: ArrayTrait::len and SpanTrait::len. Consider adding type annotations or explicitly refer to the impl function.
--> lib.cairo:9:13
arr.len();
^^^
//! > ==========================================================================
//! > Closures bad param count.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
call_with(|| {})
}
//! > function_name
foo
//! > module_code
fn call_with<F, +core::ops::Fn<F, (i32,)>>(func: F) {
func(1);
}
//! > expected_diagnostics
error[E2302]: Type mismatch: `()` and `(core::integer::i32,)`.
--> lib.cairo:5:15
call_with(|| {})
^^^^^
//! > ==========================================================================
//! > Closures with named arguments.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > function_code
fn foo() {
let c = |a, b| {
a + b
};
c(b: 2_u32, a: 1_u32);
}
//! > function_name
foo
//! > expected_diagnostics
error[E2121]: Named arguments are not supported in this context.
--> lib.cairo:5:7
c(b: 2_u32, a: 1_u32);
^^^^^^^^