//! > Test closure wrong return type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn foo() {
|| -> i32 {
let d: u32 = 3;
d
};
}
//! > expected_diagnostics
error[E2042]: Unexpected return type. Expected: "i32", found: "u32".
--> lib.cairo:2:11
|| -> i32 {
^^^
//! > ==========================================================================
//! > Test closure inferred param type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > cairo_code
fn foo() {
|a| -> i32 {
let d: i32 = a;
d
};
}
//! > expected_diagnostics
//! > ==========================================================================
//! > Test closure typed param type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn foo() {
|a: u32| -> i32 {
let d: i32 = a;
d
};
}
//! > expected_diagnostics
error[E2041]: Unexpected argument type. Expected: "i32", found: "u32".
--> lib.cairo:3:22
let d: i32 = a;
^
//! > ==========================================================================
//! > Test assignment wrong type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn foo() {
let _x: i32 = || {
let d: u32 = 3;
d
};
}
//! > expected_diagnostics
error[E2041]: Unexpected argument type. Expected: "i32", found: "test::foo::{closure#0}".
--> lib.cairo:2:19-5:5
let _x: i32 = || {
___________________^
| ...
| };
|_____^
//! > ==========================================================================
//! > Test closure in global context.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_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: `<lib.cairo:1:17: 1:19>::{closure#0}` and `i32`.
--> lib.cairo:1:17-4:1
const _x: i32 = || {
_________________^
| ...
| };
|_^
//! > ==========================================================================
//! > Test closure in generic const context.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn bar<const N: u32>() {}
fn foo() {
bar::<{ || -> u32 {
2
} }>();
}
//! > expected_diagnostics
error[E2182]: Closures are not allowed in this context.
--> lib.cairo:3:13-5:5
bar::<{ || -> u32 {
_____________^
| 2
| } }>();
|_____^
error[E2302]: Type mismatch: `<lib.cairo:3:13: 3:15>::{closure#0}` and `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)
//! > cairo_code
fn foo() {
|a| {
let d = a;
d
};
}
//! > 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)
//! > cairo_code
fn bar<T, +core::ops::FnOnce<T, (u32,)>>(c: T) -> core::ops::FnOnce::<T, (u32,)>::Output {
core::ops::FnOnce::call(c, (2,))
}
fn foo() {
let c = |a| {
let d = a;
d.into()
};
let _k: felt252 = bar(c);
}
//! > expected_diagnostics
//! > ==========================================================================
//! > Test closure infer type from impl wrong param.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn bar<T, +core::ops::FnOnce<T, (u32,)>>(c: T) -> core::ops::FnOnce::<T, (u32,)>::Output {
core::ops::FnOnce::call(c, (2,))
}
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);
}
//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: core::ops::function::FnOnce::<test::foo::{closure#0}, (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)
//! > cairo_code
fn bar<T, +core::ops::FnOnce<T, (u32,)>>(c: T) -> core::ops::FnOnce::<T, (u32,)>::Output {
core::ops::FnOnce::call(c, (2,))
}
fn foo() {
let c = |a| {
let d = a;
d.into()
};
let _f: u128 = core::ops::FnOnce::call(c, (2,));
let _k: felt252 = bar(c);
}
//! > expected_diagnostics
error[E2308]: `core::ops::function::FnOnceImpl::<test::foo::{closure#0}, (u32,), traits::DestructFromDrop::<test::foo::{closure#0}, Generated core::traits::Drop::<test::foo::{closure#0}>>, Generated core::ops::function::Fn::<test::foo::{closure#0}, (core::integer::u32,)>>::Output` type mismatch: `u128` and `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)
//! > cairo_code
fn foo() {
let c = |a, b, c| {
a.into() + b.into() + c.into()
};
let _f: u256 = c(2_felt252, 2_u256, 6_u64);
}
//! > expected_diagnostics
//! > ==========================================================================
//! > Test closure calling with diagnostics.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn foo() {
let c = |a, b, c| {
a.into() + b.into() + c.into()
};
let _f: u32 = c(2_felt252, 2_u256, 6_u64);
}
//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: Into::<u256, 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)
//! > cairo_code
fn bar() -> u32 {
2
}
fn foo() {
let bar: u8 = 3;
let _f: u32 = bar(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)
//! > cairo_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)
}
fn foo() {
let _y: u16 = baz(|a| {
a.into()
});
}
//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: core::ops::function::Fn::<felt252, ()>.
--> lib.cairo:7:19
let _x: u32 = bar();
^^^^^
error[E2311]: Trait has no implementation in context: Into::<u32, u16>.
--> lib.cairo:12:11
a.into()
^^^^
//! > ==========================================================================
//! > Test shadowing of a function with a closure.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn bar(a: felt252) -> u32 {
2
}
fn foo() {
let bar = |_a, _b, _c| -> u32 {
3
};
let _f: u32 = bar(2);
}
//! > expected_diagnostics
error[E2311]: Trait has no implementation in context: core::ops::function::Fn::<test::foo::{closure#0}, (felt252,)>.
--> lib.cairo:8:19
let _f: u32 = bar(2);
^^^^^^
//! > ==========================================================================
//! > Closure ref argument.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn foo() {
let bar = |a| -> u32 {
a
};
let a = 5;
let _f: u32 = bar(ref a);
}
//! > 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)
//! > cairo_code
fn foo() {
let bar = |a| {
return a;
};
let a = 5;
let _f: u32 = bar(a);
}
//! > expected_diagnostics
//! > ==========================================================================
//! > Closure with option propagation.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: false)
//! > cairo_code
fn foo() {
let bar = |a: Option<u32>| -> Option<u32> {
Some(a?)
};
let a = Some(5);
let _f: u32 = bar(a).unwrap();
}
//! > expected_diagnostics
//! > ==========================================================================
//! > Closure with option propagation inference required.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_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();
}
//! > 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)
//! > cairo_code
fn foo() {
loop {
let c = || {
break;
};
c();
}
}
//! > 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)
//! > cairo_code
fn foo() {
loop {
let c = || {
continue;
};
c();
}
}
//! > 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)
//! > cairo_code
fn foo() {
let mut a = 5;
let b = a;
|| -> u32 {
a + b
};
}
//! > 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)
//! > cairo_code
fn bar<T, +Destruct<T>>(a: T) {}
fn foo() {
bar(|| {});
}
//! > expected_diagnostics
//! > ==========================================================================
//! > Calling a non closure type.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn foo() {
let _y = || 2;
let x: u32 = 5;
x()
}
//! > expected_diagnostics
error[E2138]: Call expression requires a function, found `u32`.
Candidate `core::ops::function::FnOnce::call` inference failed with: Trait has no implementation in context: core::ops::function::FnOnce::<u32, ?4>.
--> lib.cairo:4:5
x()
^^^
//! > ==========================================================================
//! > Implementing a closure trait.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
impl MyImpl of core::ops::FnOnce<u32, ()> {
type Output = u32;
fn call(self: u32, args: ()) -> u32 {
self
}
}
fn foo() -> u32 {
let _y = || 2;
let x: u32 = 5;
x()
}
//! > 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)
//! > cairo_code
fn foo() {
let _ = |a| {
a = a + 2
};
}
//! > 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)
//! > cairo_code
fn foo() {
let _ = |ref a| {
a = a + 2
};
}
//! > 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)
//! > cairo_code
fn foo() -> Option<u32> {
let x: Option<Array<i32>> = Some(array![1, 2, 3]);
x.map(|x| x.len())
}
//! > expected_diagnostics
//! > ==========================================================================
//! > Passing closures as trait generics with less explicit typing.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_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>;
fn foo() {
MyTrait::call_with(|arr| {
arr.len();
});
}
//! > 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)
//! > cairo_code
fn call_with<F, +core::ops::Fn<F, (i32,)>>(func: F) {
func(1);
}
fn foo() {
call_with(|| {})
}
//! > expected_diagnostics
error[E2302]: Type mismatch: `()` and `(i32,)`.
--> lib.cairo:5:15
call_with(|| {})
^^^^^
//! > ==========================================================================
//! > Closures with named arguments.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn foo() {
let c = |a, b| {
a + b
};
c(b: 2_u32, a: 1_u32);
}
//! > expected_diagnostics
error[E2121]: Named arguments are not supported in this context.
--> lib.cairo:5:7
c(b: 2_u32, a: 1_u32);
^^^^^^^^
//! > ==========================================================================
//! > Closure capturing an inferred-type value, unified with the closure type (occurs-check regression: must not stack-overflow).
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
fn unify<T, +Drop<T>>(_a: T, _b: T) {}
fn foo() {
let x = Default::default();
let f = || {
let _s = @x;
};
unify(x, f);
}
//! > expected_diagnostics
error[E2041]: Unexpected argument type. Expected: "?0", found: "test::foo::{closure#0}".
--> lib.cairo:7:14
unify(x, f);
^
//! > ==========================================================================
//! > Test the path a generated function is named by, in every scope one can be defined in.
//! > test_runner_name
test_function_diagnostics(expect_diagnostics: true)
//! > cairo_code
// Numbered per kind, in their order in the function - the loop does not renumber the closures.
fn ordering() {
let _first: felt252 = |x: u32| x;
loop {
break;
}
let _second: felt252 = |x: u32| x;
}
// Nested in the path of the generated function containing them, each scope numbered from 0
// independently of its depth.
fn nesting() {
let _outer = |x: u32| {
let _mid = |y: u32| {
let _inner: felt252 = |z: u32| z;
y
};
loop {
let _in_loop: felt252 = |z: u32| z;
break;
}
x
};
loop {
let _in_loop: felt252 = |z: u32| z;
break;
}
let _last: felt252 = |v: u32| v;
}
// Only the body of a `for` is lowered into its loop function, so a closure in its iterable is
// scoped outside the loop.
fn for_scopes(a: Array<u32>) {
for _x in a.into_iter().map(|y: u32| {
let _in_iterable: felt252 = |z: u32| z;
y
}) {
let _in_body: felt252 = |z: u32| z;
}
}
// Named per macro expansion, as the expansion is in a file of its own.
fn macro_expansions() {
let _a = array![{
let _in_macro: felt252 = |z: u32| z;
1_u32
}];
let _b = array![{
let _in_macro: felt252 = |z: u32| z;
2_u32
}];
}
// Relative to the trait function with a default body, or the impl function, defining them.
trait MyTrait {
fn defaulted() {
let _in_trait: felt252 = |y: u32| y;
}
fn required();
}
impl MyImpl of MyTrait {
fn required() {
let _in_impl: felt252 = |y: u32| y;
}
}
//! > expected_diagnostics
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::ordering::{closure#0}".
--> lib.cairo:3:27
let _first: felt252 = |x: u32| x;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::ordering::{closure#1}".
--> lib.cairo:7:28
let _second: felt252 = |x: u32| x;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::nesting::{closure#0}::{closure#0}::{closure#0}".
--> lib.cairo:15:35
let _inner: felt252 = |z: u32| z;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::nesting::{closure#0}::{loop#0}::{closure#0}".
--> lib.cairo:19:37
let _in_loop: felt252 = |z: u32| z;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::nesting::{loop#0}::{closure#0}".
--> lib.cairo:25:33
let _in_loop: felt252 = |z: u32| z;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::nesting::{closure#1}".
--> lib.cairo:28:26
let _last: felt252 = |v: u32| v;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::for_scopes::{closure#0}::{closure#0}".
--> lib.cairo:35:37
let _in_iterable: felt252 = |z: u32| z;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::for_scopes::{loop#0}::{closure#0}".
--> lib.cairo:38:33
let _in_body: felt252 = |z: u32| z;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::macro_expansions::{array_inline_macro@1142}::{closure#0}".
--> lib.cairo:45:34
let _in_macro: felt252 = |z: u32| z;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::macro_expansions::{array_inline_macro@1231}::{closure#0}".
--> lib.cairo:49:34
let _in_macro: felt252 = |z: u32| z;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::MyTrait::defaulted::{closure#0}".
--> lib.cairo:57:34
let _in_trait: felt252 = |y: u32| y;
^^^^^^^^^^
error[E2041]: Unexpected argument type. Expected: "felt252", found: "test::MyImpl::required::{closure#0}".
--> lib.cairo:64:33
let _in_impl: felt252 = |y: u32| y;
^^^^^^^^^^