From d1afb26f4b3ee3a6729ba71c693727ac9e2f4e49 Mon Sep 17 00:00:00 2001 From: David Tolnay Date: Sat, 15 Oct 2022 13:10:09 -0700 Subject: [PATCH] Factor out the Fail lambda from all trycatch calls --- gen/src/builtin.rs | 28 +++++++++++++++++----------- gen/src/write.rs | 10 +--------- src/cxx.cc | 23 +++++++++++++++++++++++ 3 files changed, 41 insertions(+), 20 deletions(-) diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs index 93cf23806..2035210b1 100644 --- a/gen/src/builtin.rs +++ b/gen/src/builtin.rs @@ -26,7 +26,6 @@ pub struct Builtins<'a> { pub rust_str_repr: bool, pub rust_slice_new: bool, pub rust_slice_repr: bool, - pub exception: bool, pub relocatable: bool, pub relocatable_or_array: bool, pub friend_impl: bool, @@ -138,6 +137,10 @@ pub(super) fn write(out: &mut OutFile) { builtin.unsafe_bitcopy_t = true; } + if builtin.trycatch { + builtin.ptr_len = true; + } + out.begin_block(Block::Namespace("rust")); out.begin_block(Block::InlineNamespace("cxxbridge1")); @@ -251,6 +254,19 @@ pub(super) fn write(out: &mut OutFile) { writeln!(out, "}};"); } + if builtin.trycatch { + out.next_section(); + writeln!(out, "class Fail final {{"); + writeln!(out, " ::rust::repr::PtrLen &throw$;"); + writeln!(out, "public:"); + writeln!( + out, + " Fail(::rust::repr::PtrLen &throw$) : throw$(throw$) {{}}" + ); + writeln!(out, " void operator()(const char *) noexcept;"); + writeln!(out, "}};"); + } + out.end_block(Block::Namespace("detail")); if builtin.manually_drop { @@ -401,14 +417,4 @@ pub(super) fn write(out: &mut OutFile) { } out.end_block(Block::Namespace("rust")); - - if builtin.exception { - include.cstddef = true; - out.begin_block(Block::ExternC); - writeln!( - out, - "const char *cxxbridge1$exception(const char *, ::std::size_t) noexcept;", - ); - out.end_block(Block::ExternC); - } } diff --git a/gen/src/write.rs b/gen/src/write.rs index dddec7a55..d5a8b6556 100644 --- a/gen/src/write.rs +++ b/gen/src/write.rs @@ -847,17 +847,9 @@ fn write_cxx_function_shim<'a>(out: &mut OutFile<'a>, efn: &'a ExternFn) { } writeln!(out, ";"); if efn.throws { - out.include.cstring = true; - out.builtin.exception = true; writeln!(out, " throw$.ptr = nullptr;"); writeln!(out, " }},"); - writeln!(out, " [&](const char *catch$) noexcept {{"); - writeln!(out, " throw$.len = ::std::strlen(catch$);"); - writeln!( - out, - " throw$.ptr = const_cast(::cxxbridge1$exception(catch$, throw$.len));", - ); - writeln!(out, " }});"); + writeln!(out, " ::rust::detail::Fail(throw$));"); writeln!(out, " return throw$;"); } writeln!(out, "}}"); diff --git a/src/cxx.cc b/src/cxx.cc index 1601a05ab..c0e96d407 100644 --- a/src/cxx.cc +++ b/src/cxx.cc @@ -68,6 +68,9 @@ void cxxbridge1$slice$new(void *self, const void *ptr, std::size_t len) noexcept; void *cxxbridge1$slice$ptr(const void *self) noexcept; std::size_t cxxbridge1$slice$len(const void *self) noexcept; + +// try/catch +const char *cxxbridge1$exception(const char *, std::size_t len) noexcept; } // extern "C" namespace rust { @@ -506,6 +509,13 @@ union MaybeUninit { }; } // namespace +namespace repr { +struct PtrLen final { + void *ptr; + std::size_t len; +}; +} // namespace repr + namespace detail { // On some platforms size_t is the same C++ type as one of the sized integer // types; on others it is a distinct type. Only in the latter case do we need to @@ -519,6 +529,19 @@ using isize_if_unique = typename std::conditional::value || std::is_same::value, struct isize_ignore, rust::isize>::type; + +class Fail final { + repr::PtrLen &throw$; + +public: + Fail(repr::PtrLen &throw$) : throw$(throw$) {} + void operator()(const char *) noexcept; +}; + +void Fail::operator()(const char *catch$) noexcept { + throw$.len = std::strlen(catch$); + throw$.ptr = const_cast(cxxbridge1$exception(catch$, throw$.len)); +} } // namespace detail } // namespace cxxbridge1