cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

as(): make as() cast to use type_safety.enforce

Open filipsajdak opened this issue 5 months ago • 1 comments

The current implementation of as() for std::any, std::optional, and std::variant throws exceptions in case of tunability to cast. This behavior is inconsistent with runtime checked as() for signed/unsigned integral cast where it calls terminate().

This implementation switch runtime checked as() to use type_safety, which allows the setup of one approach for all type_safety issues.

The current behavior is to terminate, but it can be changed, e.g., to throw an exception. The following example is an excellent example of how it can be used.

void throw_error(CPP2_MESSAGE_PARAM msg CPP2_SOURCE_LOCATION_PARAM) {
    throw std::runtime_error(std::string("Type safety exception: ") + msg);
}

make_throwable: (inout cg : cpp2::contract_group) -> _ = {
    h := cg.get_handler();
    sh := :(pcg : *cpp2::contract_group) = {
        pcg*.set_handler(h$);
    };
    cg.set_handler(throw_error);
    return std::unique_ptr<cpp2::contract_group, decltype(sh)>(cg&, sh);
}

void expect_no_throw(auto&& fun) try {
    fun();
} catch(std::exception const& e) {
    std::cout << e.what() << std::endl;
} catch(...) {
    std::cout << "Unknown exception!" << std::endl;
}

main: () = {
    o : std::optional<int> = ();

    (_ := make_throwable(cpp2::type_safety)) {
        expect_no_throw( :() = {
            std::cout << (o$ as int) << std::endl; // that will throw
        });
    }

    std::cout << (o as int) << std::endl; // that will terminate
}

and the result is the following:

Type safety exception: 'as' cast failed for 'std::optional'
Type safety violation: 'as' cast failed for 'std::optional'
libc++abi: terminating

filipsajdak avatar Aug 30 '24 23:08 filipsajdak