Improve error message on unique_ptr of incomplete forward declared type
diff --git a/gen/src/builtin.rs b/gen/src/builtin.rs
index 53facbf..35620db 100644
--- a/gen/src/builtin.rs
+++ b/gen/src/builtin.rs
@@ -25,6 +25,8 @@
pub exception: bool,
pub relocatable: bool,
pub friend_impl: bool,
+ pub is_complete: bool,
+ pub deleter_if: bool,
pub content: Content<'a>,
}
@@ -226,6 +228,33 @@
writeln!(out, "}};");
}
+ if builtin.is_complete {
+ include.type_traits = true;
+ out.next_section();
+ writeln!(out, "template <typename T, typename = size_t>");
+ writeln!(out, "struct is_complete : std::false_type {{}};");
+ out.next_section();
+ writeln!(out, "template <typename T>");
+ writeln!(
+ out,
+ "struct is_complete<T, decltype(sizeof(T))> : std::true_type {{}};",
+ );
+ }
+
+ if builtin.deleter_if {
+ out.next_section();
+ writeln!(out, "template <bool> struct deleter_if {{");
+ writeln!(out, " template <typename T> void operator()(T *) {{}}");
+ writeln!(out, "}};");
+ out.next_section();
+ writeln!(out, "template <> struct deleter_if<true> {{");
+ writeln!(
+ out,
+ " template <typename T> void operator()(T *ptr) {{ ptr->~T(); }}",
+ );
+ writeln!(out, "}};");
+ }
+
out.end_block(Block::AnonymousNamespace);
out.end_block(Block::InlineNamespace("cxxbridge1"));
diff --git a/gen/src/write.rs b/gen/src/write.rs
index e33197c..a12af31 100644
--- a/gen/src/write.rs
+++ b/gen/src/write.rs
@@ -1242,6 +1242,26 @@
UniquePtr::CxxVector(_) => false,
};
+ let conditional_delete = match ty {
+ UniquePtr::Ident(ident) => {
+ !out.types.structs.contains_key(&ident.rust)
+ && !out.types.enums.contains_key(&ident.rust)
+ }
+ UniquePtr::CxxVector(_) => false,
+ };
+
+ if conditional_delete {
+ out.builtin.is_complete = true;
+ let definition = match ty {
+ UniquePtr::Ident(ty) => &out.types.resolve(ty).cxx,
+ UniquePtr::CxxVector(_) => unreachable!(),
+ };
+ writeln!(
+ out,
+ "static_assert(::rust::is_complete<{}>::value, \"definition of {} is required\");",
+ inner, definition,
+ );
+ }
writeln!(
out,
"static_assert(sizeof(::std::unique_ptr<{}>) == sizeof(void *), \"\");",
@@ -1298,7 +1318,16 @@
"void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
instance, inner,
);
- writeln!(out, " ptr->~unique_ptr();");
+ if conditional_delete {
+ out.builtin.deleter_if = true;
+ writeln!(
+ out,
+ " ::rust::deleter_if<::rust::is_complete<{}>::value>{{}}(ptr);",
+ inner,
+ );
+ } else {
+ writeln!(out, " ptr->~unique_ptr();");
+ }
writeln!(out, "}}");
}