So we’ve established something here: This is a bad idea, and always run tests in ReleaseFast
mode if trying to figure out what kind of weird stuff you can actually get away with.
All of this passes in both Debug and ReleaseFast mode.
const ExampleStruct = struct {
v: u64,
};
fn returnOptional(val: u64) ?ExampleStruct {
var example: ExampleStruct = undefined;
example.v = val;
return example;
}
test "It returns optional" {
const opt = returnOptional(23);
if (opt) |it| {
try expectEqual(23, it.v);
} else {
try expect(false);
}
}
fn takesOptional(maybe_it: ?ExampleStruct) !void {
if (maybe_it) |it| {
try expectEqual(128, it.v);
} else {
try expect(false);
}
}
test "It passes optional" {
var example: ExampleStruct = undefined;
example.v = 128;
try takesOptional(example);
}
test "Trivial assignment case" {
var example: ExampleStruct = undefined;
example.v = 128;
const maybe_example: ?ExampleStruct = example;
try takesOptional(maybe_example);
}
I don’t think real code exists where doing things this way would not be strongly preferred. You can always assign a T
to a ?T
. So if you need to build a T
up by parts, you don’t need to create it as a ?T
, create it as a T
and: return it, pass it, or assign it to a ?T
.