diff --git a/libsafecxx/test/broken/optional_take_if2.cxx b/libsafecxx/test/broken/optional_take_if2.cxx new file mode 100644 index 0000000..04dce1b --- /dev/null +++ b/libsafecxx/test/broken/optional_take_if2.cxx @@ -0,0 +1,71 @@ +#feature on safety + +template +T replace/(a)(T^/a dst, T src) safe +{ + unsafe { + T result = __rel_read(addr *dst); + __rel_write(addr *dst, rel src); + return result; + } +} + +template +concept FnMut = requires(F f, Args ...args) +{ + requires safe(mut f(^args...)); +}; + +template +choice optional +{ + default none, + [[safety::unwrap]] some(T); + + T unwrap(self) noexcept safe { + return match(rel self) -> T { + .some(t) => rel t; + .none => throw "invalid"; + }; + } + + template + optional take_if(self^, P p) safe + requires FnMut + { + return match(*self) -> optional { + .some(^x) => return ( + p(x) ? replace>(self, .none) : optional::none + ); + .none => return .none; + }; + } + + bool is_some(self const^) noexcept safe { + return match(*self) { + .some(_) => true; + .none => false; + }; + } + + bool is_none(self const^) noexcept safe { + return !self.is_some(); + } +}; + +int main() safe +{ + struct C + { + static + bool invoke/(a)(int^/a x) safe { + bool b = (*x < 4321); + return b; + } + }; + + optional opt = .some(1234); + auto m_p = mut opt.take_if(addr C::invoke); + + if(!m_p.is_some()) throw 1234; +}