macro_rules! polonius_break_dependent { ( $e:expr $(,)? ) => { ... }; }
Expand description
break
a dependent value out of a polonius_loop!
.
To be used in conjunction with a
polonius_loop!(|var| -> …, break: … {
invocation.
- If the
, break: …
type annotation is forgotten, then invocations topolonius_break_dependent!
will fail with an error message complaining aboutcannot_use__polonius_break_dependentǃ__without_a_break_type_annotation_on__polonius_loopǃ
§Example
-
use { ::std::{ collections::HashMap, }, ::polonius_the_crab::{ *, }, }; fn example (mut map: &'_ mut HashMap<u8, i32>) { let mut i = 0; // needed for `polonius_break_dependent!` to work. // vvvvvvvvvvvvvvvvvvvvvvvvvvv let entry = polonius_loop!(|map| -> _, break: &'polonius mut i32 { // ^^^^^^^^^ // don't forget the special annotation PoloniusResult. if let Some(entry) = map.get_mut(&i) { polonius_break_dependent!(entry); } i += 1; }); // `map` was consumed by the loop, and is thus unusable. // But the `break_dependent!`-yielded items is allowed to still be // borrowing it. *entry = 0; }
Now let’s compare it to what happens when polonius_break!
is
(incorrectly) used in its stead:
§Incorrect usage
The following fails to compile:
-
ⓘ
use { ::std::{ collections::HashMap, }, ::polonius_the_crab::{ *, }, }; fn example (mut map: &'_ mut HashMap<u8, i32>) { let mut i = 0; let entry = polonius_loop!(|map| -> _ { if let Some(entry) = map.get_mut(&i) { polonius_break!(entry); } i += 1; }); *entry = 0; }
with the following error message:
ⓘerror: lifetime may not live long enough --> src/lib.rs:467:13 | 16 | let entry = polonius_loop!(|map| -> _ { | _________________- 17 | | if let Some(entry) = map.get_mut(&i) { 18 | | polonius_break!(entry); | | ^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'2` 19 | | } 20 | | i += 1; 21 | | }); | | - | | | | |______let's call the lifetime of this reference `'1` | return type of closure is Result<Dependent<()>, ControlFlow<&'2 mut i32>>
Using
RUSTC_BOOTSTRAP=1 cargo rustc --profile-check -- -Zmacro-backtrace
to “improve” the error message, we can get:ⓘerror: lifetime may not live long enough --> polonius-the-crab/src/lib.rs:442:12 | 351 | |mut $var: &mut _| { | - - return type of closure is Result<Dependent<()>, ControlFlow<&'2 mut i32>> | | | let's call the lifetime of this reference `'1` ... 441 | / macro_rules! polonius_break {( $($e:expr $(,)?)? ) => ( 442 | | return $crate::ඞ::core::result::Result::Err( | |____________^ 443 | || $crate::ඞ::core::ops::ControlFlow::Break( 444 | || ($($e ,)? () ,).0 445 | || ) 446 | || ) | ||_____^ returning this value requires that `'1` must outlive `'2` 447 | | )} | |__- in this expansion of `polonius_break!` | ::: src/lib.rs:552:13 | 18 | polonius_break!(entry); | ----------------------- in this macro invocation
Which may be a bit better at hinting that we have a borrowing problem with
polonius_break!
, whereby the returned value cannot reach some borrowing /
lifetime requirements (those stemming from an actually-dependent break
value).