Improve error message on unique_ptr of incomplete forward declared type

This commit is contained in:
David Tolnay 2020-11-25 07:08:10 -08:00
parent ee9b9eebad
commit 534627667d
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
2 changed files with 59 additions and 1 deletions

View File

@ -25,6 +25,8 @@ pub struct Builtins<'a> {
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 @@ pub(super) fn write(out: &mut OutFile) {
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"));

View File

@ -1242,6 +1242,26 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
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 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: UniquePtr) {
"void cxxbridge1$unique_ptr${}$drop(::std::unique_ptr<{}> *ptr) noexcept {{",
instance, inner,
);
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, "}}");
}