@@ -55,11 +55,37 @@ pub fn test_is_none_some_max() -> bool {
5555
5656// ----- is_some_and -----------------------------------------------------------
5757
58- // TODO(closure-extraction): is_some_and takes a closure; revisit when we exercise FnOnce.
58+ #[ rust_lean_test]
59+ pub fn test_is_some_and_some_true ( ) -> bool {
60+ Some ( 4u8 ) . is_some_and ( |x| x > 0 ) == true
61+ }
62+
63+ #[ rust_lean_test]
64+ pub fn test_is_some_and_some_false ( ) -> bool {
65+ Some ( 0u8 ) . is_some_and ( |x| x > 0 ) == false
66+ }
67+
68+ #[ rust_lean_test]
69+ pub fn test_is_some_and_none ( ) -> bool {
70+ none_u8 ( ) . is_some_and ( |x| x > 0 ) == false
71+ }
5972
6073// ----- is_none_or ------------------------------------------------------------
6174
62- // TODO(closure-extraction): is_none_or takes a closure; revisit when we exercise FnOnce.
75+ #[ rust_lean_test]
76+ pub fn test_is_none_or_some_true ( ) -> bool {
77+ Some ( 4u8 ) . is_none_or ( |x| x > 0 ) == true
78+ }
79+
80+ #[ rust_lean_test]
81+ pub fn test_is_none_or_some_false ( ) -> bool {
82+ Some ( 0u8 ) . is_none_or ( |x| x > 0 ) == false
83+ }
84+
85+ #[ rust_lean_test]
86+ pub fn test_is_none_or_none ( ) -> bool {
87+ none_u8 ( ) . is_none_or ( |x| x > 0 ) == true
88+ }
6389
6490// ----- as_ref ----------------------------------------------------------------
6591
@@ -154,7 +180,20 @@ pub fn test_unwrap_or_none_default_max() -> bool {
154180
155181// ----- unwrap_or_else --------------------------------------------------------
156182
157- // TODO(closure-extraction): unwrap_or_else takes a closure; revisit when we exercise FnOnce.
183+ #[ rust_lean_test]
184+ pub fn test_unwrap_or_else_some_zero ( ) -> bool {
185+ Some ( 0u8 ) . unwrap_or_else ( || 42 ) == 0
186+ }
187+
188+ #[ rust_lean_test]
189+ pub fn test_unwrap_or_else_some_max ( ) -> bool {
190+ Some ( u8:: MAX ) . unwrap_or_else ( || 0 ) == u8:: MAX
191+ }
192+
193+ #[ rust_lean_test]
194+ pub fn test_unwrap_or_else_none ( ) -> bool {
195+ none_u8 ( ) . unwrap_or_else ( || 7 ) == 7
196+ }
158197
159198// ----- unwrap_or_default -----------------------------------------------------
160199
@@ -184,19 +223,60 @@ pub fn test_unwrap_or_default_none() -> bool {
184223
185224// ----- map -------------------------------------------------------------------
186225
187- // TODO(closure-extraction): map takes a closure; revisit when we exercise FnOnce.
226+ // TODO(closure-extraction-map): `Option::map` returns `Option<U>`; observing the
227+ // result requires either `Option::PartialEq` (blocked by option-eq-extraction)
228+ // or destructuring through `match`, but the latter goes back through
229+ // `Option::PartialEq` once we compare the inner value. Revisit alongside
230+ // option-eq-extraction.
231+
232+ #[ rust_lean_test]
233+ pub fn test_map_some_via_unwrap_or ( ) -> bool {
234+ Some ( 3u8 ) . map ( |x| x + 1 ) . unwrap_or ( 0 ) == 4
235+ }
236+
237+ #[ rust_lean_test]
238+ pub fn test_map_none_via_unwrap_or ( ) -> bool {
239+ none_u8 ( ) . map ( |x| x + 1 ) . unwrap_or ( 99 ) == 99
240+ }
241+
242+ #[ rust_lean_test]
243+ pub fn test_map_some_is_some ( ) -> bool {
244+ Some ( 3u8 ) . map ( |x| x + 1 ) . is_some ( )
245+ }
246+
247+ #[ rust_lean_test]
248+ pub fn test_map_none_is_none ( ) -> bool {
249+ none_u8 ( ) . map ( |x| x + 1 ) . is_none ( )
250+ }
188251
189252// ----- map_or ----------------------------------------------------------------
190253
191- // TODO(closure-extraction): map_or takes a closure; revisit when we exercise FnOnce.
254+ #[ rust_lean_test]
255+ pub fn test_map_or_some_zero ( ) -> bool {
256+ Some ( 3u8 ) . map_or ( 0u8 , |x| x + 1 ) == 4
257+ }
258+
259+ #[ rust_lean_test]
260+ pub fn test_map_or_some_max ( ) -> bool {
261+ Some ( 0u8 ) . map_or ( 99u8 , |x| x + 1 ) == 1
262+ }
263+
264+ #[ rust_lean_test]
265+ pub fn test_map_or_none ( ) -> bool {
266+ none_u8 ( ) . map_or ( 99u8 , |x| x + 1 ) == 99
267+ }
192268
193269// ----- map_or_else -----------------------------------------------------------
194270
195- // TODO(closure-extraction): map_or_else takes two closures; revisit when we exercise FnOnce.
271+ // TODO(closure-extraction-order): `Option::map_or_else` takes (default: D, f: F)
272+ // in source order but the model lists the trait instances in (F, D) order, so
273+ // Aeneas emits them swapped and the Lean elaboration fails for the `None`
274+ // branch. Revisit once the closure-instance ordering is fixed.
196275
197276// ----- map_or_default --------------------------------------------------------
198277
199- // TODO(closure-extraction): map_or_default takes a closure; revisit when we exercise FnOnce.
278+ // TODO(map_or_default-unstable): `Option::map_or_default` is gated behind
279+ // `result_option_map_or_default` on stable. Revisit once it stabilises.
200280
201281// ----- ok_or -----------------------------------------------------------------
202282
@@ -220,9 +300,40 @@ pub fn test_ok_or_none_err_max() -> bool {
220300 matches ! ( none_u8( ) . ok_or( u8 :: MAX ) , Err ( v) if v == u8 :: MAX )
221301}
222302
303+ // ----- ok_or_else ------------------------------------------------------------
304+
305+ #[ rust_lean_test]
306+ pub fn test_ok_or_else_some ( ) -> bool {
307+ matches ! ( Some ( 7u8 ) . ok_or_else( || 99u8 ) , Ok ( 7 ) )
308+ }
309+
310+ #[ rust_lean_test]
311+ pub fn test_ok_or_else_none ( ) -> bool {
312+ matches ! ( none_u8( ) . ok_or_else( || 42u8 ) , Err ( 42 ) )
313+ }
314+
315+ // ----- and_then --------------------------------------------------------------
316+
317+ #[ rust_lean_test]
318+ pub fn test_and_then_some_to_some ( ) -> bool {
319+ Some ( 3u8 ) . and_then ( |x| Some ( x + 1 ) ) . unwrap_or ( 0 ) == 4
320+ }
321+
322+ #[ rust_lean_test]
323+ pub fn test_and_then_some_to_none ( ) -> bool {
324+ Some ( 3u8 ) . and_then ( |_| none_u8 ( ) ) . is_none ( )
325+ }
326+
327+ #[ rust_lean_test]
328+ pub fn test_and_then_none ( ) -> bool {
329+ none_u8 ( ) . and_then ( |x| Some ( x + 1 ) ) . is_none ( )
330+ }
331+
223332// ----- filter ----------------------------------------------------------------
224333
225- // TODO(closure-extraction): filter takes a closure; revisit when we exercise FnOnce.
334+ // TODO(closure-by-ref-extraction): `Option::filter` takes `FnOnce(&T) -> bool`;
335+ // Aeneas trips on the borrow with "Region ids should not be visited directly".
336+ // Revisit once closures whose parameter is a reference extract.
226337
227338// ----- or --------------------------------------------------------------------
228339
@@ -257,7 +368,25 @@ pub fn test_or_none_none() -> bool {
257368
258369// ----- or_else ---------------------------------------------------------------
259370
260- // TODO(closure-extraction): or_else takes a closure; revisit when we exercise FnOnce.
371+ #[ rust_lean_test]
372+ pub fn test_or_else_some_kept ( ) -> bool {
373+ Some ( 0u8 ) . or_else ( || Some ( 99u8 ) ) . unwrap_or ( 7 ) == 0
374+ }
375+
376+ #[ rust_lean_test]
377+ pub fn test_or_else_some_max_kept ( ) -> bool {
378+ Some ( u8:: MAX ) . or_else ( || none_u8 ( ) ) . unwrap_or ( 0 ) == u8:: MAX
379+ }
380+
381+ #[ rust_lean_test]
382+ pub fn test_or_else_none_to_some ( ) -> bool {
383+ none_u8 ( ) . or_else ( || Some ( 42u8 ) ) . unwrap_or ( 0 ) == 42
384+ }
385+
386+ #[ rust_lean_test]
387+ pub fn test_or_else_none_to_none ( ) -> bool {
388+ none_u8 ( ) . or_else ( || none_u8 ( ) ) . is_none ( )
389+ }
261390
262391// ----- xor -------------------------------------------------------------------
263392
@@ -337,7 +466,9 @@ pub fn test_zip_none_none() -> bool {
337466
338467// ----- inspect ---------------------------------------------------------------
339468
340- // TODO(closure-extraction): inspect takes a closure; revisit when we exercise FnOnce.
469+ // TODO(closure-by-ref-extraction): `Option::inspect` takes `FnOnce(&T)`;
470+ // Aeneas trips on the borrow with "Region ids should not be visited directly".
471+ // Revisit once closures whose parameter is a reference extract.
341472
342473// ----- flatten ---------------------------------------------------------------
343474
0 commit comments