&?Box is “a Box or nothing”; &Box is “definitely a Box”. Converting the first into the second with to &Box is a promise that it isn’t null, and Turf only accepts that promise where it can see it kept. Copying the value out with to Box reads through the reference, so it needs the same check.
struct Box { val: int }fn bad(b: &?Box): int { mut safe: &Box = b to &Box; // b might be null return safe.val;}Check it first, and convert inside the check:
fn good(b: &?Box): int { if b != null { mut safe: &Box = b to &Box; // proven non-null here return safe.val; } return 0;}Often you don’t need the conversion at all: inside the if b != null { ... }, b can be used directly.
Only a variable can be checked, so only a variable can be converted. For a &?Box that is a field, a call result or a list element (h.item to &Box), store it in a variable first, check that, and convert inside the check:
struct Holder { item: &?Box }fn good(h: Holder): int { mut b: &?Box = h.item; if b != null { mut safe: &Box = b to &Box; return safe.val; } return 0;}Run turf --explain E082 in a terminal to read this again.