Date: Mon, 8 Jun 2020 11:52:39 +0100
Hi,
I was thinking about error-handling recently (see references [1] and [2]
below). Of course, there are several proposals aimed at improving the
error-handling mechanisms in C++ (p0709, p1028, p1029, p1144; p0323, p0798).
I was particularly interested in p0709 (title: "Zero-overhead deterministic
exceptions: Throwing values"). I would summarise this proposal here as
making error-handling better by making exceptions better. My thought was
that maybe one could tackle the problem of error-handling at a lower level
first, and only bring exceptions into the picture later, especially given
that some people don’t want to use exceptions.
So, my idea was to allow functions to have multiple, alternative
return-paths at the language level. Basically, a function declaration would
be allowed to declare any number of alternative return-paths (each with an
associated alternative return-type). The function implementation could then
return along any of those return-paths at any point in its execution. The
caller of such a function would always be required to handle all
alternative return-paths in some way: either (a) explicitly (e.g. by
throwing an exception or handling the error otherwise) or (b) by declaring
the same alternative return-path (in which case the mechanism would work
similar to stack unwinding). Failure to do either (a) or (b) results in a
compile-time error.
Here is a short snippet of what it might look like (inspired by [2]):
int parse_int(std::string_view const str)
->[parse_error] std::string
{
std::stringstream ss; ss << str;
int i; ss >> i;
if (ss.fail()) {
return[parse_error] "parse_positive_int: not an int";
}
else {
return i;
}
}
auto parse_int_square(std::string_view const str)
-> std::tuple<int, int>
->[parse_error] std::string
{
auto const i = parse_int(str);
return i, i * i;
}
int main() {
std::string input;
std::cin >> input;
auto const [i, i_sq] = parse_int_square(input)
->[parse_error] auto const& msg {
std::cerr << “Error: “ << msg;
return 1;
};
assert(i * i == i_sq);
std::cout << "i_sq = " << i_sq << '\n';
return 0;
}
More extensive brain storming here:
https://github.com/TobyBrull/scratchpad/blob/master/alternative_return_paths.cpp
I imagine all this would still be compatible with p1028/std::error. It
might also have other applications besides error-handling; essentially,
every function that returns a std::variant could use this mechanism.
I don't have any experience working on compilers, but I imagine this should
be possible to implement efficiently, although it would require an ABI
extension. I imagine the alternative returns-paths to be part of the
function type and thus affect name mangling.
What do you think?
Cheers,
Toby
References:
[1] http://lucteo.ro/2018/04/21/exception-exploration-2/
[2] Phil Nash's CppCon 2019 talk,
"The Dawn of a New Error" ( https://www.youtube.com/watch?v=ZUH8p1EQswA )
I was thinking about error-handling recently (see references [1] and [2]
below). Of course, there are several proposals aimed at improving the
error-handling mechanisms in C++ (p0709, p1028, p1029, p1144; p0323, p0798).
I was particularly interested in p0709 (title: "Zero-overhead deterministic
exceptions: Throwing values"). I would summarise this proposal here as
making error-handling better by making exceptions better. My thought was
that maybe one could tackle the problem of error-handling at a lower level
first, and only bring exceptions into the picture later, especially given
that some people don’t want to use exceptions.
So, my idea was to allow functions to have multiple, alternative
return-paths at the language level. Basically, a function declaration would
be allowed to declare any number of alternative return-paths (each with an
associated alternative return-type). The function implementation could then
return along any of those return-paths at any point in its execution. The
caller of such a function would always be required to handle all
alternative return-paths in some way: either (a) explicitly (e.g. by
throwing an exception or handling the error otherwise) or (b) by declaring
the same alternative return-path (in which case the mechanism would work
similar to stack unwinding). Failure to do either (a) or (b) results in a
compile-time error.
Here is a short snippet of what it might look like (inspired by [2]):
int parse_int(std::string_view const str)
->[parse_error] std::string
{
std::stringstream ss; ss << str;
int i; ss >> i;
if (ss.fail()) {
return[parse_error] "parse_positive_int: not an int";
}
else {
return i;
}
}
auto parse_int_square(std::string_view const str)
-> std::tuple<int, int>
->[parse_error] std::string
{
auto const i = parse_int(str);
return i, i * i;
}
int main() {
std::string input;
std::cin >> input;
auto const [i, i_sq] = parse_int_square(input)
->[parse_error] auto const& msg {
std::cerr << “Error: “ << msg;
return 1;
};
assert(i * i == i_sq);
std::cout << "i_sq = " << i_sq << '\n';
return 0;
}
More extensive brain storming here:
https://github.com/TobyBrull/scratchpad/blob/master/alternative_return_paths.cpp
I imagine all this would still be compatible with p1028/std::error. It
might also have other applications besides error-handling; essentially,
every function that returns a std::variant could use this mechanism.
I don't have any experience working on compilers, but I imagine this should
be possible to implement efficiently, although it would require an ABI
extension. I imagine the alternative returns-paths to be part of the
function type and thus affect name mangling.
What do you think?
Cheers,
Toby
References:
[1] http://lucteo.ro/2018/04/21/exception-exploration-2/
[2] Phil Nash's CppCon 2019 talk,
"The Dawn of a New Error" ( https://www.youtube.com/watch?v=ZUH8p1EQswA )
Received on 2020-06-08 05:56:00