aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/c_char.rs69
-rw-r--r--src/cxx.cc89
-rw-r--r--src/cxx_string.rs9
-rw-r--r--src/cxx_vector.rs10
-rw-r--r--src/exception.rs5
-rw-r--r--src/extern_type.rs8
-rw-r--r--src/fmt.rs2
-rw-r--r--src/hash.rs12
-rw-r--r--src/lib.rs55
-rw-r--r--src/lossy.rs67
-rw-r--r--src/result.rs7
-rw-r--r--src/rust_string.rs1
-rw-r--r--src/rust_vec.rs5
-rw-r--r--src/shared_ptr.rs10
-rw-r--r--src/sip.rs228
-rw-r--r--src/symbols/exception.rs14
-rw-r--r--src/symbols/rust_str.rs2
-rw-r--r--src/symbols/rust_string.rs26
-rw-r--r--src/symbols/rust_vec.rs10
-rw-r--r--src/unique_ptr.rs16
-rw-r--r--src/unwind.rs47
-rw-r--r--src/weak_ptr.rs6
22 files changed, 630 insertions, 68 deletions
diff --git a/src/c_char.rs b/src/c_char.rs
new file mode 100644
index 00000000..333d8491
--- /dev/null
+++ b/src/c_char.rs
@@ -0,0 +1,69 @@
+#[allow(missing_docs)]
+pub type c_char = c_char_definition::c_char;
+
+// Validate that our definition is consistent with libstd's definition, without
+// introducing a dependency on libstd in ordinary builds.
+#[cfg(all(test, feature = "std"))]
+const _: self::c_char = 0 as std::os::raw::c_char;
+
+#[allow(dead_code)]
+mod c_char_definition {
+ // These are the targets on which c_char is unsigned.
+ #[cfg(any(
+ all(
+ target_os = "linux",
+ any(
+ target_arch = "aarch64",
+ target_arch = "arm",
+ target_arch = "hexagon",
+ target_arch = "powerpc",
+ target_arch = "powerpc64",
+ target_arch = "s390x",
+ target_arch = "riscv64",
+ target_arch = "riscv32"
+ )
+ ),
+ all(
+ target_os = "android",
+ any(target_arch = "aarch64", target_arch = "arm")
+ ),
+ all(target_os = "l4re", target_arch = "x86_64"),
+ all(
+ target_os = "freebsd",
+ any(
+ target_arch = "aarch64",
+ target_arch = "arm",
+ target_arch = "powerpc",
+ target_arch = "powerpc64",
+ target_arch = "riscv64"
+ )
+ ),
+ all(
+ target_os = "netbsd",
+ any(target_arch = "aarch64", target_arch = "arm", target_arch = "powerpc")
+ ),
+ all(target_os = "openbsd", target_arch = "aarch64"),
+ all(
+ target_os = "vxworks",
+ any(
+ target_arch = "aarch64",
+ target_arch = "arm",
+ target_arch = "powerpc64",
+ target_arch = "powerpc"
+ )
+ ),
+ all(target_os = "fuchsia", target_arch = "aarch64")
+ ))]
+ pub use self::unsigned::c_char;
+
+ // On every other target, c_char is signed.
+ pub use self::signed::*;
+
+ mod unsigned {
+ pub type c_char = u8;
+ }
+
+ mod signed {
+ pub type c_char = i8;
+ }
+}
diff --git a/src/cxx.cc b/src/cxx.cc
index 5dca531b..a7cb6797 100644
--- a/src/cxx.cc
+++ b/src/cxx.cc
@@ -40,8 +40,12 @@ void cxxbridge1$string$clone(rust::String *self,
const rust::String &other) noexcept;
bool cxxbridge1$string$from_utf8(rust::String *self, const char *ptr,
std::size_t len) noexcept;
+void cxxbridge1$string$from_utf8_lossy(rust::String *self, const char *ptr,
+ std::size_t len) noexcept;
bool cxxbridge1$string$from_utf16(rust::String *self, const char16_t *ptr,
std::size_t len) noexcept;
+void cxxbridge1$string$from_utf16_lossy(rust::String *self, const char16_t *ptr,
+ std::size_t len) noexcept;
void cxxbridge1$string$drop(rust::String *self) noexcept;
const char *cxxbridge1$string$ptr(const rust::String *self) noexcept;
std::size_t cxxbridge1$string$len(const rust::String *self) noexcept;
@@ -81,6 +85,12 @@ void panic [[noreturn]] (const char *msg) {
template void panic<std::out_of_range> [[noreturn]] (const char *msg);
+template <typename T>
+static bool is_aligned(const void *ptr) noexcept {
+ auto iptr = reinterpret_cast<std::uintptr_t>(ptr);
+ return !(iptr % alignof(T));
+}
+
String::String() noexcept { cxxbridge1$string$new(this); }
String::String(const String &other) noexcept {
@@ -121,17 +131,60 @@ String::String(const char *s, std::size_t len) {
String::String(const char16_t *s) {
assert(s != nullptr);
+ assert(is_aligned<char16_t>(s));
initString(this, s, std::char_traits<char16_t>::length(s));
}
String::String(const char16_t *s, std::size_t len) {
assert(s != nullptr || len == 0);
+ assert(is_aligned<char16_t>(s));
initString(this,
s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2)
: s,
len);
}
+struct String::lossy_t {};
+
+String::String(lossy_t, const char *s, std::size_t len) noexcept {
+ cxxbridge1$string$from_utf8_lossy(
+ this, s == nullptr && len == 0 ? reinterpret_cast<const char *>(1) : s,
+ len);
+}
+
+String::String(lossy_t, const char16_t *s, std::size_t len) noexcept {
+ cxxbridge1$string$from_utf16_lossy(
+ this,
+ s == nullptr && len == 0 ? reinterpret_cast<const char16_t *>(2) : s,
+ len);
+}
+
+String String::lossy(const std::string &s) noexcept {
+ return String::lossy(s.data(), s.length());
+}
+
+String String::lossy(const char *s) noexcept {
+ assert(s != nullptr);
+ return String::lossy(s, std::strlen(s));
+}
+
+String String::lossy(const char *s, std::size_t len) noexcept {
+ assert(s != nullptr || len == 0);
+ return String(lossy_t{}, s, len);
+}
+
+String String::lossy(const char16_t *s) noexcept {
+ assert(s != nullptr);
+ assert(is_aligned<char16_t>(s));
+ return String(lossy_t{}, s, std::char_traits<char16_t>::length(s));
+}
+
+String String::lossy(const char16_t *s, std::size_t len) noexcept {
+ assert(s != nullptr || len == 0);
+ assert(is_aligned<char16_t>(s));
+ return String(lossy_t{}, s, len);
+}
+
String &String::operator=(const String &other) &noexcept {
if (this != &other) {
cxxbridge1$string$drop(this);
@@ -453,6 +506,17 @@ union MaybeUninit {
};
} // namespace
+namespace repr {
+struct PtrLen final {
+ void *ptr;
+ std::size_t len;
+};
+} // namespace repr
+
+extern "C" {
+repr::PtrLen cxxbridge1$exception(const char *, std::size_t len) noexcept;
+}
+
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
@@ -466,6 +530,23 @@ using isize_if_unique =
typename std::conditional<std::is_same<rust::isize, int64_t>::value ||
std::is_same<rust::isize, int32_t>::value,
struct isize_ignore, rust::isize>::type;
+
+class Fail final {
+ repr::PtrLen &throw$;
+
+public:
+ Fail(repr::PtrLen &throw$) noexcept : throw$(throw$) {}
+ void operator()(const char *) noexcept;
+ void operator()(const std::string &) noexcept;
+};
+
+void Fail::operator()(const char *catch$) noexcept {
+ throw$ = cxxbridge1$exception(catch$, std::strlen(catch$));
+}
+
+void Fail::operator()(const std::string &catch$) noexcept {
+ throw$ = cxxbridge1$exception(catch$.data(), catch$.length());
+}
} // namespace detail
} // namespace cxxbridge1
@@ -568,7 +649,9 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
void cxxbridge1$rust_vec$##RUST_TYPE##$reserve_total( \
rust::Vec<CXX_TYPE> *ptr, std::size_t new_cap) noexcept; \
void cxxbridge1$rust_vec$##RUST_TYPE##$set_len(rust::Vec<CXX_TYPE> *ptr, \
- std::size_t len) noexcept;
+ std::size_t len) noexcept; \
+ void cxxbridge1$rust_vec$##RUST_TYPE##$truncate(rust::Vec<CXX_TYPE> *ptr, \
+ std::size_t len) noexcept;
#define RUST_VEC_OPS(RUST_TYPE, CXX_TYPE) \
template <> \
@@ -598,6 +681,10 @@ static_assert(sizeof(std::string) <= kMaxExpectedWordsInString * sizeof(void *),
template <> \
void Vec<CXX_TYPE>::set_len(std::size_t len) noexcept { \
cxxbridge1$rust_vec$##RUST_TYPE##$set_len(this, len); \
+ } \
+ template <> \
+ void Vec<CXX_TYPE>::truncate(std::size_t len) { \
+ cxxbridge1$rust_vec$##RUST_TYPE##$truncate(this, len); \
}
#define SHARED_PTR_OPS(RUST_TYPE, CXX_TYPE) \
diff --git a/src/cxx_string.rs b/src/cxx_string.rs
index 626c2c85..9ecbcc64 100644
--- a/src/cxx_string.rs
+++ b/src/cxx_string.rs
@@ -1,5 +1,8 @@
use crate::actually_private::Private;
+use crate::lossy;
+#[cfg(feature = "alloc")]
use alloc::borrow::Cow;
+#[cfg(feature = "alloc")]
use alloc::string::String;
use core::cmp::Ordering;
use core::fmt::{self, Debug, Display};
@@ -144,6 +147,8 @@ impl CxxString {
/// Cow::Owned String.
///
/// [replacement character]: https://doc.rust-lang.org/std/char/constant.REPLACEMENT_CHARACTER.html
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
pub fn to_string_lossy(&self) -> Cow<str> {
String::from_utf8_lossy(self.as_bytes())
}
@@ -204,13 +209,13 @@ impl CxxString {
impl Display for CxxString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- Display::fmt(self.to_string_lossy().as_ref(), f)
+ lossy::display(self.as_bytes(), f)
}
}
impl Debug for CxxString {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
- Debug::fmt(self.to_string_lossy().as_ref(), f)
+ lossy::debug(self.as_bytes(), f)
}
}
diff --git a/src/cxx_vector.rs b/src/cxx_vector.rs
index d1fa23a2..abf9297a 100644
--- a/src/cxx_vector.rs
+++ b/src/cxx_vector.rs
@@ -368,7 +368,6 @@ pub unsafe trait VectorElement: Sized {
macro_rules! vector_element_by_value_methods {
(opaque, $segment:expr, $ty:ty) => {};
(trivial, $segment:expr, $ty:ty) => {
- #[doc(hidden)]
unsafe fn __push_back(v: Pin<&mut CxxVector<$ty>>, value: &mut ManuallyDrop<$ty>) {
extern "C" {
attr! {
@@ -378,7 +377,6 @@ macro_rules! vector_element_by_value_methods {
}
unsafe { __push_back(v, value) }
}
- #[doc(hidden)]
unsafe fn __pop_back(v: Pin<&mut CxxVector<$ty>>, out: &mut MaybeUninit<$ty>) {
extern "C" {
attr! {
@@ -397,11 +395,9 @@ macro_rules! impl_vector_element {
const_assert_eq!(1, mem::align_of::<CxxVector<$ty>>());
unsafe impl VectorElement for $ty {
- #[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
f.write_str($name)
}
- #[doc(hidden)]
fn __vector_size(v: &CxxVector<$ty>) -> usize {
extern "C" {
attr! {
@@ -411,7 +407,6 @@ macro_rules! impl_vector_element {
}
unsafe { __vector_size(v) }
}
- #[doc(hidden)]
unsafe fn __get_unchecked(v: *mut CxxVector<$ty>, pos: usize) -> *mut $ty {
extern "C" {
attr! {
@@ -422,7 +417,6 @@ macro_rules! impl_vector_element {
unsafe { __get_unchecked(v, pos) }
}
vector_element_by_value_methods!($kind, $segment, $ty);
- #[doc(hidden)]
fn __unique_ptr_null() -> MaybeUninit<*mut c_void> {
extern "C" {
attr! {
@@ -434,7 +428,6 @@ macro_rules! impl_vector_element {
unsafe { __unique_ptr_null(&mut repr) }
repr
}
- #[doc(hidden)]
unsafe fn __unique_ptr_raw(raw: *mut CxxVector<Self>) -> MaybeUninit<*mut c_void> {
extern "C" {
attr! {
@@ -446,7 +439,6 @@ macro_rules! impl_vector_element {
unsafe { __unique_ptr_raw(&mut repr, raw) }
repr
}
- #[doc(hidden)]
unsafe fn __unique_ptr_get(repr: MaybeUninit<*mut c_void>) -> *const CxxVector<Self> {
extern "C" {
attr! {
@@ -456,7 +448,6 @@ macro_rules! impl_vector_element {
}
unsafe { __unique_ptr_get(&repr) }
}
- #[doc(hidden)]
unsafe fn __unique_ptr_release(mut repr: MaybeUninit<*mut c_void>) -> *mut CxxVector<Self> {
extern "C" {
attr! {
@@ -466,7 +457,6 @@ macro_rules! impl_vector_element {
}
unsafe { __unique_ptr_release(&mut repr) }
}
- #[doc(hidden)]
unsafe fn __unique_ptr_drop(mut repr: MaybeUninit<*mut c_void>) {
extern "C" {
attr! {
diff --git a/src/exception.rs b/src/exception.rs
index 2ae470e7..259b27d4 100644
--- a/src/exception.rs
+++ b/src/exception.rs
@@ -1,7 +1,10 @@
+#![cfg(feature = "alloc")]
+
use alloc::boxed::Box;
use core::fmt::{self, Display};
/// Exception thrown from an `extern "C++"` function.
+#[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
#[derive(Debug)]
pub struct Exception {
pub(crate) what: Box<str>,
@@ -13,6 +16,8 @@ impl Display for Exception {
}
}
+#[cfg(feature = "std")]
+#[cfg_attr(doc_cfg, doc(cfg(feature = "std")))]
impl std::error::Error for Exception {}
impl Exception {
diff --git a/src/extern_type.rs b/src/extern_type.rs
index 8c9c2860..d131ae12 100644
--- a/src/extern_type.rs
+++ b/src/extern_type.rs
@@ -1,5 +1,6 @@
use self::kind::{Kind, Opaque, Trivial};
use crate::CxxString;
+#[cfg(feature = "alloc")]
use alloc::string::String;
/// A type for which the layout is determined by its C++ definition.
@@ -186,9 +187,11 @@ pub fn verify_extern_type<T: ExternType<Id = Id>, Id>() {}
pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
macro_rules! impl_extern_type {
- ($([$kind:ident] $($ty:path = $cxxpath:literal)*)*) => {
+ ($([$kind:ident] $($(#[$($attr:tt)*])* $ty:path = $cxxpath:literal)*)*) => {
$($(
+ $(#[$($attr)*])*
unsafe impl ExternType for $ty {
+ #[allow(unused_attributes)] // incorrect lint; this doc(hidden) attr *is* respected by rustdoc
#[doc(hidden)]
type Id = crate::type_id!($cxxpath);
type Kind = $kind;
@@ -212,6 +215,9 @@ impl_extern_type! {
isize = "rust::isize"
f32 = "float"
f64 = "double"
+
+ #[cfg(feature = "alloc")]
+ #[cfg_attr(doc_cfg, doc(cfg(feature = "alloc")))]
String = "rust::String"
[Opaque]
diff --git a/src/fmt.rs b/src/fmt.rs
index db14a7c0..69614f80 100644
--- a/src/fmt.rs
+++ b/src/fmt.rs
@@ -1,4 +1,4 @@
-use std::fmt::{self, Display};
+use core::fmt::{self, Display};
pub(crate) fn display(fmt: impl Fn(&mut fmt::Formatter) -> fmt::Result) -> impl Display {
DisplayInvoke(fmt)
diff --git a/src/hash.rs b/src/hash.rs
new file mode 100644
index 00000000..4c92173f
--- /dev/null
+++ b/src/hash.rs
@@ -0,0 +1,12 @@
+use core::hash::{Hash, Hasher};
+
+#[doc(hidden)]
+pub fn hash<V: Hash>(value: &V) -> usize {
+ #[cfg(feature = "std")]
+ let mut hasher = std::collections::hash_map::DefaultHasher::new();
+ #[cfg(not(feature = "std"))]
+ let mut hasher = crate::sip::SipHasher13::new();
+
+ Hash::hash(value, &mut hasher);
+ Hasher::finish(&hasher) as usize
+}
diff --git a/src/lib.rs b/src/lib.rs
index 9880e711..3ddd887d 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -2,7 +2,7 @@
//!
//! [github]: https://img.shields.io/badge/github-8da0cb?style=for-the-badge&labelColor=555555&logo=github
//! [crates-io]: https://img.shields.io/badge/crates.io-fc8d62?style=for-the-badge&labelColor=555555&logo=rust
-//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logoColor=white&logo=data:image/svg+xml;base64,PHN2ZyByb2xlPSJpbWciIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgdmlld0JveD0iMCAwIDUxMiA1MTIiPjxwYXRoIGZpbGw9IiNmNWY1ZjUiIGQ9Ik00ODguNiAyNTAuMkwzOTIgMjE0VjEwNS41YzAtMTUtOS4zLTI4LjQtMjMuNC0zMy43bC0xMDAtMzcuNWMtOC4xLTMuMS0xNy4xLTMuMS0yNS4zIDBsLTEwMCAzNy41Yy0xNC4xIDUuMy0yMy40IDE4LjctMjMuNCAzMy43VjIxNGwtOTYuNiAzNi4yQzkuMyAyNTUuNSAwIDI2OC45IDAgMjgzLjlWMzk0YzAgMTMuNiA3LjcgMjYuMSAxOS45IDMyLjJsMTAwIDUwYzEwLjEgNS4xIDIyLjEgNS4xIDMyLjIgMGwxMDMuOS01MiAxMDMuOSA1MmMxMC4xIDUuMSAyMi4xIDUuMSAzMi4yIDBsMTAwLTUwYzEyLjItNi4xIDE5LjktMTguNiAxOS45LTMyLjJWMjgzLjljMC0xNS05LjMtMjguNC0yMy40LTMzLjd6TTM1OCAyMTQuOGwtODUgMzEuOXYtNjguMmw4NS0zN3Y3My4zek0xNTQgMTA0LjFsMTAyLTM4LjIgMTAyIDM4LjJ2LjZsLTEwMiA0MS40LTEwMi00MS40di0uNnptODQgMjkxLjFsLTg1IDQyLjV2LTc5LjFsODUtMzguOHY3NS40em0wLTExMmwtMTAyIDQxLjQtMTAyLTQxLjR2LS42bDEwMi0zOC4yIDEwMiAzOC4ydi42em0yNDAgMTEybC04NSA0Mi41di03OS4xbDg1LTM4Ljh2NzUuNHptMC0xMTJsLTEwMiA0MS40LTEwMi00MS40di0uNmwxMDItMzguMiAxMDIgMzguMnYuNnoiPjwvcGF0aD48L3N2Zz4K
+//! [docs-rs]: https://img.shields.io/badge/docs.rs-66c2a5?style=for-the-badge&labelColor=555555&logo=docs.rs
//!
//! <br>
//!
@@ -364,10 +364,11 @@
//! </table>
#![no_std]
-#![doc(html_root_url = "https://docs.rs/cxx/1.0.54")]
+#![doc(html_root_url = "https://docs.rs/cxx/1.0.85")]
#![deny(improper_ctypes, improper_ctypes_definitions, missing_docs)]
#![cfg_attr(not(no_unsafe_op_in_unsafe_fn_lint), deny(unsafe_op_in_unsafe_fn))]
#![cfg_attr(no_unsafe_op_in_unsafe_fn_lint, allow(unused_unsafe))]
+#![cfg_attr(doc_cfg, feature(doc_cfg))]
#![allow(non_camel_case_types)]
#![allow(
clippy::cognitive_complexity,
@@ -388,6 +389,7 @@
clippy::or_fun_call,
clippy::ptr_arg,
clippy::toplevel_ref_arg,
+ clippy::transmute_undefined_repr, // clippy bug: https://github.com/rust-lang/rust-clippy/issues/8417
clippy::useless_let_if_seq,
clippy::wrong_self_convention
)]
@@ -395,18 +397,53 @@
#[cfg(built_with_cargo)]
extern crate link_cplusplus;
-extern crate alloc;
extern crate self as cxx;
-extern crate std;
+
+#[doc(hidden)]
+pub extern crate core;
+
+#[cfg(feature = "alloc")]
+#[doc(hidden)]
+pub extern crate alloc;
+
+#[cfg(not(feature = "alloc"))]
+extern crate core as alloc;
+
+#[cfg(feature = "std")]
+#[doc(hidden)]
+pub extern crate std;
+
+// Block inadvertent use of items from libstd, which does not otherwise produce
+// a compile-time error on edition 2018+.
+#[cfg(not(feature = "std"))]
+extern crate core as std;
+
+#[cfg(not(any(feature = "alloc", cxx_experimental_no_alloc)))]
+compile_error! {
+ r#"cxx support for no_alloc is incomplete and semver exempt; you must build with at least one of feature="std", feature="alloc", or RUSTFLAGS='--cfg cxx_experimental_no_alloc'"#
+}
+
+#[cfg(all(compile_error_if_alloc, feature = "alloc"))]
+compile_error! {
+ r#"feature="alloc" is unexpectedly enabled"#
+}
+
+#[cfg(all(compile_error_if_std, feature = "std"))]
+compile_error! {
+ r#"feature="std" is unexpectedly enabled"#
+}
#[macro_use]
mod macros;
+mod c_char;
mod cxx_vector;
mod exception;
mod extern_type;
mod fmt;
mod function;
+mod hash;
+mod lossy;
pub mod memory;
mod opaque;
mod result;
@@ -416,6 +453,7 @@ mod rust_string;
mod rust_type;
mod rust_vec;
mod shared_ptr;
+mod sip;
#[path = "cxx_string.rs"]
mod string;
mod symbols;
@@ -426,6 +464,7 @@ pub mod vector;
mod weak_ptr;
pub use crate::cxx_vector::CxxVector;
+#[cfg(feature = "alloc")]
pub use crate::exception::Exception;
pub use crate::extern_type::{kind, ExternType};
pub use crate::shared_ptr::SharedPtr;
@@ -451,21 +490,27 @@ pub type Vector<T> = CxxVector<T>;
// Not public API.
#[doc(hidden)]
pub mod private {
+ pub use crate::c_char::c_char;
pub use crate::cxx_vector::VectorElement;
pub use crate::extern_type::{verify_extern_kind, verify_extern_type};
pub use crate::function::FatFunction;
+ pub use crate::hash::hash;
pub use crate::opaque::Opaque;
+ #[cfg(feature = "alloc")]
pub use crate::result::{r#try, Result};
pub use crate::rust_slice::RustSlice;
pub use crate::rust_str::RustStr;
+ #[cfg(feature = "alloc")]
pub use crate::rust_string::RustString;
pub use crate::rust_type::{ImplBox, ImplVec, RustType};
+ #[cfg(feature = "alloc")]
pub use crate::rust_vec::RustVec;
pub use crate::shared_ptr::SharedPtrTarget;
pub use crate::string::StackString;
pub use crate::unique_ptr::UniquePtrTarget;
- pub use crate::unwind::catch_unwind;
+ pub use crate::unwind::prevent_unwind;
pub use crate::weak_ptr::WeakPtrTarget;
+ pub use core::{concat, module_path};
pub use cxxbridge_macro::type_id;
}
diff --git a/src/lossy.rs b/src/lossy.rs
new file mode 100644
index 00000000..d68a2e7b
--- /dev/null
+++ b/src/lossy.rs
@@ -0,0 +1,67 @@
+use core::char;
+use core::fmt::{self, Write as _};
+use core::str;
+
+pub fn display(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
+ loop {
+ match str::from_utf8(bytes) {
+ Ok(valid) => return f.write_str(valid),
+ Err(utf8_error) => {
+ let valid_up_to = utf8_error.valid_up_to();
+ let valid = unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) };
+ f.write_str(valid)?;
+ f.write_char(char::REPLACEMENT_CHARACTER)?;
+ if let Some(error_len) = utf8_error.error_len() {
+ bytes = &bytes[valid_up_to + error_len..];
+ } else {
+ return Ok(());
+ }
+ }
+ }
+ }
+}
+
+pub fn debug(mut bytes: &[u8], f: &mut fmt::Formatter) -> fmt::Result {
+ f.write_char('"')?;
+
+ while !bytes.is_empty() {
+ let from_utf8_result = str::from_utf8(bytes);
+ let valid = match from_utf8_result {
+ Ok(valid) => valid,
+ Err(utf8_error) => {
+ let valid_up_to = utf8_error.valid_up_to();
+ unsafe { str::from_utf8_unchecked(&bytes[..valid_up_to]) }
+ }
+ };
+
+ let mut written = 0;
+ for (i, ch) in valid.char_indices() {
+ let esc = ch.escape_debug();
+ if esc.len() != 1 {
+ f.write_str(&valid[written..i])?;
+ for ch in esc {
+ f.write_char(ch)?;
+ }
+ written = i + ch.len_utf8();
+ }
+ }
+ f.write_str(&valid[written..])?;
+
+ match from_utf8_result {
+ Ok(_valid) => break,
+ Err(utf8_error) => {
+ let end_of_broken = if let Some(error_len) = utf8_error.error_len() {
+ valid.len() + error_len
+ } else {
+ bytes.len()
+ };
+ for b in &bytes[valid.len()..end_of_broken] {
+ write!(f, "\\x{:02x}", b)?;
+ }
+ bytes = &bytes[end_of_broken..];
+ }
+ }
+ }
+
+ f.write_char('"')
+}
diff --git a/src/result.rs b/src/result.rs
index d7a31f02..ba77858e 100644
--- a/src/result.rs
+++ b/src/result.rs
@@ -1,3 +1,4 @@
+#![cfg(feature = "alloc")]
#![allow(missing_docs)]
use crate::exception::Exception;
@@ -11,9 +12,9 @@ use core::str;
#[repr(C)]
#[derive(Copy, Clone)]
-struct PtrLen {
- ptr: NonNull<u8>,
- len: usize,
+pub struct PtrLen {
+ pub ptr: NonNull<u8>,
+ pub len: usize,
}
#[repr(C)]
diff --git a/src/rust_string.rs b/src/rust_string.rs
index 051e35c3..0e0c5a83 100644
--- a/src/rust_string.rs
+++ b/src/rust_string.rs
@@ -1,3 +1,4 @@
+#![cfg(feature = "alloc")]
#![allow(missing_docs)]
use alloc::string::String;
diff --git a/src/rust_vec.rs b/src/rust_vec.rs
index 9f4484db..acb7e890 100644
--- a/src/rust_vec.rs
+++ b/src/rust_vec.rs
@@ -1,3 +1,4 @@
+#![cfg(feature = "alloc")]
#![allow(missing_docs)]
use crate::rust_string::RustString;
@@ -67,6 +68,10 @@ impl<T> RustVec<T> {
pub unsafe fn set_len(&mut self, len: usize) {
unsafe { self.as_mut_vec().set_len(len) }
}
+
+ pub fn truncate(&mut self, len: usize) {
+ self.as_mut_vec().truncate(len);
+ }
}
impl RustVec<RustString> {
diff --git a/src/shared_ptr.rs b/src/shared_ptr.rs
index 317773d4..64c86619 100644
--- a/src/shared_ptr.rs
+++ b/src/shared_ptr.rs
@@ -101,6 +101,10 @@ where
}
}
+// SharedPtr is not a self-referential type and is safe to move out of a Pin,
+// regardless whether the pointer's target is Unpin.
+impl<T> Unpin for SharedPtr<T> where T: SharedPtrTarget {}
+
impl<T> Drop for SharedPtr<T>
where
T: SharedPtrTarget,
@@ -204,11 +208,9 @@ pub unsafe trait SharedPtrTarget {
macro_rules! impl_shared_ptr_target {
($segment:expr, $name:expr, $ty:ty) => {
unsafe impl SharedPtrTarget for $ty {
- #[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
f.write_str($name)
}
- #[doc(hidden)]
unsafe fn __null(new: *mut c_void) {
extern "C" {
attr! {
@@ -218,7 +220,6 @@ macro_rules! impl_shared_ptr_target {
}
unsafe { __null(new) }
}
- #[doc(hidden)]
unsafe fn __new(value: Self, new: *mut c_void) {
extern "C" {
attr! {
@@ -228,7 +229,6 @@ macro_rules! impl_shared_ptr_target {
}
unsafe { __uninit(new).cast::<$ty>().write(value) }
}
- #[doc(hidden)]
unsafe fn __clone(this: *const c_void, new: *mut c_void) {
extern "C" {
attr! {
@@ -238,7 +238,6 @@ macro_rules! impl_shared_ptr_target {
}
unsafe { __clone(this, new) }
}
- #[doc(hidden)]
unsafe fn __get(this: *const c_void) -> *const Self {
extern "C" {
attr! {
@@ -248,7 +247,6 @@ macro_rules! impl_shared_ptr_target {
}
unsafe { __get(this) }.cast()
}
- #[doc(hidden)]
unsafe fn __drop(this: *mut c_void) {
extern "C" {
attr! {
diff --git a/src/sip.rs b/src/sip.rs
new file mode 100644
index 00000000..9e1d050a
--- /dev/null
+++ b/src/sip.rs
@@ -0,0 +1,228 @@
+// Vendored from libstd:
+// https://github.com/rust-lang/rust/blob/1.57.0/library/core/src/hash/sip.rs
+//
+// TODO: maybe depend on a hasher from crates.io if this becomes annoying to
+// maintain, or change this to a simpler one.
+
+#![cfg(not(feature = "std"))]
+
+use core::cmp;
+use core::hash::Hasher;
+use core::mem;
+use core::ptr;
+
+/// An implementation of SipHash 1-3.
+///
+/// This is currently the default hashing function used by standard library
+/// (e.g., `collections::HashMap` uses it by default).
+///
+/// See: <https://131002.net/siphash>
+pub struct SipHasher13 {
+ k0: u64,
+ k1: u64,
+ length: usize, // how many bytes we've processed
+ state: State, // hash State
+ tail: u64, // unprocessed bytes le
+ ntail: usize, // how many bytes in tail are valid
+}
+
+#[derive(Clone, Copy)]
+#[repr(C)]
+struct State {
+ // v0, v2 and v1, v3 show up in pairs in the algorithm,
+ // and simd implementations of SipHash will use vectors
+ // of v02 and v13. By placing them in this order in the struct,
+ // the compiler can pick up on just a few simd optimizations by itself.
+ v0: u64,
+ v2: u64,
+ v1: u64,
+ v3: u64,
+}
+
+macro_rules! compress {
+ ($state:expr) => {
+ compress!($state.v0, $state.v1, $state.v2, $state.v3)
+ };
+ ($v0:expr, $v1:expr, $v2:expr, $v3:expr) => {
+ $v0 = $v0.wrapping_add($v1);
+ $v1 = $v1.rotate_left(13);
+ $v1 ^= $v0;
+ $v0 = $v0.rotate_left(32);
+ $v2 = $v2.wrapping_add($v3);
+ $v3 = $v3.rotate_left(16);
+ $v3 ^= $v2;
+ $v0 = $v0.wrapping_add($v3);
+ $v3 = $v3.rotate_left(21);
+ $v3 ^= $v0;
+ $v2 = $v2.wrapping_add($v1);
+ $v1 = $v1.rotate_left(17);
+ $v1 ^= $v2;
+ $v2 = $v2.rotate_left(32);
+ };
+}
+
+/// Loads an integer of the desired type from a byte stream, in LE order. Uses
+/// `copy_nonoverlapping` to let the compiler generate the most efficient way
+/// to load it from a possibly unaligned address.
+///
+/// Unsafe because: unchecked indexing at i..i+size_of(int_ty)
+macro_rules! load_int_le {
+ ($buf:expr, $i:expr, $int_ty:ident) => {{
+ debug_assert!($i + mem::size_of::<$int_ty>() <= $buf.len());
+ let mut data = 0 as $int_ty;
+ ptr::copy_nonoverlapping(
+ $buf.as_ptr().add($i),
+ &mut data as *mut _ as *mut u8,
+ mem::size_of::<$int_ty>(),
+ );
+ data.to_le()
+ }};
+}
+
+/// Loads a u64 using up to 7 bytes of a byte slice. It looks clumsy but the
+/// `copy_nonoverlapping` calls that occur (via `load_int_le!`) all have fixed
+/// sizes and avoid calling `memcpy`, which is good for speed.
+///
+/// Unsafe because: unchecked indexing at start..start+len
+unsafe fn u8to64_le(buf: &[u8], start: usize, len: usize) -> u64 {
+ debug_assert!(len < 8);
+ let mut i = 0; // current byte index (from LSB) in the output u64
+ let mut out = 0;
+ if i + 3 < len {
+ // SAFETY: `i` cannot be greater than `len`, and the caller must guarantee
+ // that the index start..start+len is in bounds.
+ out = unsafe { load_int_le!(buf, start + i, u32) } as u64;
+ i += 4;
+ }
+ if i + 1 < len {
+ // SAFETY: same as above.
+ out |= (unsafe { load_int_le!(buf, start + i, u16) } as u64) << (i * 8);
+ i += 2
+ }
+ if i < len {
+ // SAFETY: same as above.
+ out |= (unsafe { *buf.get_unchecked(start + i) } as u64) << (i * 8);
+ i += 1;
+ }
+ debug_assert_eq!(i, len);
+ out
+}
+
+impl SipHasher13 {
+ /// Creates a new `SipHasher13` with the two initial keys set to 0.
+ pub fn new() -> Self {
+ Self::new_with_keys(0, 0)
+ }
+
+ /// Creates a `SipHasher13` that is keyed off the provided keys.
+ fn new_with_keys(key0: u64, key1: u64) -> Self {
+ let mut state = SipHasher13 {
+ k0: key0,
+ k1: key1,
+ length: 0,
+ state: State {
+ v0: 0,
+ v1: 0,
+ v2: 0,
+ v3: 0,
+ },
+ tail: 0,
+ ntail: 0,
+ };
+ state.reset();
+ state
+ }
+
+ fn reset(&mut self) {
+ self.length = 0;
+ self.state.v0 = self.k0 ^ 0x736f6d6570736575;
+ self.state.v1 = self.k1 ^ 0x646f72616e646f6d;
+ self.state.v2 = self.k0 ^ 0x6c7967656e657261;
+ self.state.v3 = self.k1 ^ 0x7465646279746573;
+ self.ntail = 0;
+ }
+}
+
+impl Hasher for SipHasher13 {
+ // Note: no integer hashing methods (`write_u*`, `write_i*`) are defined
+ // for this type. We could add them, copy the `short_write` implementation
+ // in librustc_data_structures/sip128.rs, and add `write_u*`/`write_i*`
+ // methods to `SipHasher`, `SipHasher13`, and `DefaultHasher`. This would
+ // greatly speed up integer hashing by those hashers, at the cost of
+ // slightly slowing down compile speeds on some benchmarks. See #69152 for
+ // details.
+ fn write(&mut self, msg: &[u8]) {
+ let length = msg.len();
+ self.length += length;
+
+ let mut needed = 0;
+
+ if self.ntail != 0 {
+ needed = 8 - self.ntail;
+ // SAFETY: `cmp::min(length, needed)` is guaranteed to not be over `length`
+ self.tail |= unsafe { u8to64_le(msg, 0, cmp::min(length, needed)) } << (8 * self.ntail);
+ if length < needed {
+ self.ntail += length;
+ return;
+ } else {
+ self.state.v3 ^= self.tail;
+ Sip13Rounds::c_rounds(&mut self.state);
+ self.state.v0 ^= self.tail;
+ self.ntail = 0;
+ }
+ }
+
+ // Buffered tail is now flushed, process new input.
+ let len = length - needed;
+ let left = len & 0x7; // len % 8
+
+ let mut i = needed;
+ while i < len - left {
+ // SAFETY: because `len - left` is the biggest multiple of 8 under
+ // `len`, and because `i` starts at `needed` where `len` is `length - needed`,
+ // `i + 8` is guaranteed to be less than or equal to `length`.
+ let mi = unsafe { load_int_le!(msg, i, u64) };
+
+ self.state.v3 ^= mi;
+ Sip13Rounds::c_rounds(&mut self.state);
+ self.state.v0 ^= mi;
+
+ i += 8;
+ }
+
+ // SAFETY: `i` is now `needed + len.div_euclid(8) * 8`,
+ // so `i + left` = `needed + len` = `length`, which is by
+ // definition equal to `msg.len()`.
+ self.tail = unsafe { u8to64_le(msg, i, left) };
+ self.ntail = left;
+ }
+
+ fn finish(&self) -> u64 {
+ let mut state = self.state;
+
+ let b: u64 = ((self.length as u64 & 0xff) << 56) | self.tail;
+
+ state.v3 ^= b;
+ Sip13Rounds::c_rounds(&mut state);
+ state.v0 ^= b;
+
+ state.v2 ^= 0xff;
+ Sip13Rounds::d_rounds(&mut state);
+
+ state.v0 ^ state.v1 ^ state.v2 ^ state.v3
+ }
+}
+
+struct Sip13Rounds;
+
+impl Sip13Rounds {
+ fn c_rounds(state: &mut State) {
+ compress!(state);
+ }
+
+ fn d_rounds(state: &mut State) {
+ compress!(state);
+ compress!(state);
+ compress!(state);
+ }
+}
diff --git a/src/symbols/exception.rs b/src/symbols/exception.rs
index cf0701ba..b8fe1b5d 100644
--- a/src/symbols/exception.rs
+++ b/src/symbols/exception.rs
@@ -1,10 +1,18 @@
+#![cfg(feature = "alloc")]
+
+use crate::result::PtrLen;
use alloc::boxed::Box;
use alloc::string::String;
+use core::ptr::NonNull;
use core::slice;
#[export_name = "cxxbridge1$exception"]
-unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> *const u8 {
+unsafe extern "C" fn exception(ptr: *const u8, len: usize) -> PtrLen {
let slice = unsafe { slice::from_raw_parts(ptr, len) };
- let boxed = String::from_utf8_lossy(slice).into_owned().into_boxed_str();
- Box::leak(boxed).as_ptr()
+ let string = String::from_utf8_lossy(slice);
+ let len = string.len();
+ let raw_str = Box::into_raw(string.into_owned().into_boxed_str());
+ let raw_u8 = raw_str.cast::<u8>();
+ let nonnull = unsafe { NonNull::new_unchecked(raw_u8) };
+ PtrLen { ptr: nonnull, len }
}
diff --git a/src/symbols/rust_str.rs b/src/symbols/rust_str.rs
index 3d5ec344..3b33bc4a 100644
--- a/src/symbols/rust_str.rs
+++ b/src/symbols/rust_str.rs
@@ -1,3 +1,4 @@
+#[cfg(feature = "alloc")]
use alloc::string::String;
use core::mem::MaybeUninit;
use core::ptr;
@@ -10,6 +11,7 @@ unsafe extern "C" fn str_new(this: &mut MaybeUninit<&str>) {
unsafe { ptr::write(this, "") }
}
+#[cfg(feature = "alloc")]
#[export_name = "cxxbridge1$str$ref"]
unsafe extern "C" fn str_ref<'a>(this: &mut MaybeUninit<&'a str>, string: &'a String) {
let this = this.as_mut_ptr();
diff --git a/src/symbols/rust_string.rs b/src/symbols/rust_string.rs
index 49d40697..8b7c8c48 100644
--- a/src/symbols/rust_string.rs
+++ b/src/symbols/rust_string.rs
@@ -1,3 +1,5 @@
+#![cfg(feature = "alloc")]
+
use alloc::borrow::ToOwned;
use alloc::string::String;
use core::mem::{ManuallyDrop, MaybeUninit};
@@ -37,6 +39,18 @@ unsafe extern "C" fn string_from_utf8(
}
}
+#[export_name = "cxxbridge1$string$from_utf8_lossy"]
+unsafe extern "C" fn string_from_utf8_lossy(
+ this: &mut MaybeUninit<String>,
+ ptr: *const u8,
+ len: usize,
+) {
+ let slice = unsafe { slice::from_raw_parts(ptr, len) };
+ let owned = String::from_utf8_lossy(slice).into_owned();
+ let this = this.as_mut_ptr();
+ unsafe { ptr::write(this, owned) }
+}
+
#[export_name = "cxxbridge1$string$from_utf16"]
unsafe extern "C" fn string_from_utf16(
this: &mut MaybeUninit<String>,
@@ -54,6 +68,18 @@ unsafe extern "C" fn string_from_utf16(
}
}
+#[export_name = "cxxbridge1$string$from_utf16_lossy"]
+unsafe extern "C" fn string_from_utf16_lossy(
+ this: &mut MaybeUninit<String>,
+ ptr: *const u16,
+ len: usize,
+) {
+ let slice = unsafe { slice::from_raw_parts(ptr, len) };
+ let owned = String::from_utf16_lossy(slice);
+ let this = this.as_mut_ptr();
+ unsafe { ptr::write(this, owned) }
+}
+
#[export_name = "cxxbridge1$string$drop"]
unsafe extern "C" fn string_drop(this: &mut ManuallyDrop<String>) {
unsafe { ManuallyDrop::drop(this) }
diff --git a/src/symbols/rust_vec.rs b/src/symbols/rust_vec.rs
index 6f2dab9d..89c7da44 100644
--- a/src/symbols/rust_vec.rs
+++ b/src/symbols/rust_vec.rs
@@ -1,9 +1,11 @@
+#![cfg(feature = "alloc")]
+
+use crate::c_char::c_char;
use crate::rust_string::RustString;
use crate::rust_vec::RustVec;
use alloc::vec::Vec;
use core::mem;
use core::ptr;
-use std::os::raw::c_char;
macro_rules! rust_vec_shims {
($segment:expr, $ty:ty) => {
@@ -54,6 +56,12 @@ macro_rules! rust_vec_shims {
unsafe { (*this).set_len(len) }
}
}
+ attr! {
+ #[export_name = concat!("cxxbridge1$rust_vec$", $segment, "$truncate")]
+ unsafe extern "C" fn __truncate(this: *mut RustVec<$ty>, len: usize) {
+ unsafe { (*this).truncate(len) }
+ }
+ }
};
};
}
diff --git a/src/unique_ptr.rs b/src/unique_ptr.rs
index 63a1ca78..33992059 100644
--- a/src/unique_ptr.rs
+++ b/src/unique_ptr.rs
@@ -112,6 +112,10 @@ where
unsafe impl<T> Send for UniquePtr<T> where T: Send + UniquePtrTarget {}
unsafe impl<T> Sync for UniquePtr<T> where T: Sync + UniquePtrTarget {}
+// UniquePtr is not a self-referential type and is safe to move out of a Pin,
+// regardless whether the pointer's target is Unpin.
+impl<T> Unpin for UniquePtr<T> where T: UniquePtrTarget {}
+
impl<T> Drop for UniquePtr<T>
where
T: UniquePtrTarget,
@@ -241,11 +245,9 @@ extern "C" {
}
unsafe impl UniquePtrTarget for CxxString {
- #[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
f.write_str("CxxString")
}
- #[doc(hidden)]
fn __null() -> MaybeUninit<*mut c_void> {
let mut repr = MaybeUninit::uninit();
unsafe {
@@ -253,21 +255,17 @@ unsafe impl UniquePtrTarget for CxxString {
}
repr
}
- #[doc(hidden)]
unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
let mut repr = MaybeUninit::uninit();
unsafe { unique_ptr_std_string_raw(&mut repr, raw) }
repr
}
- #[doc(hidden)]
unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
unsafe { unique_ptr_std_string_get(&repr) }
}
- #[doc(hidden)]
unsafe fn __release(mut repr: MaybeUninit<*mut c_void>) -> *mut Self {
unsafe { unique_ptr_std_string_release(&mut repr) }
}
- #[doc(hidden)]
unsafe fn __drop(mut repr: MaybeUninit<*mut c_void>) {
unsafe { unique_ptr_std_string_drop(&mut repr) }
}
@@ -277,27 +275,21 @@ unsafe impl<T> UniquePtrTarget for CxxVector<T>
where
T: VectorElement,
{
- #[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "CxxVector<{}>", display(T::__typename))
}
- #[doc(hidden)]
fn __null() -> MaybeUninit<*mut c_void> {
T::__unique_ptr_null()
}
- #[doc(hidden)]
unsafe fn __raw(raw: *mut Self) -> MaybeUninit<*mut c_void> {
unsafe { T::__unique_ptr_raw(raw) }
}
- #[doc(hidden)]
unsafe fn __get(repr: MaybeUninit<*mut c_void>) -> *const Self {
unsafe { T::__unique_ptr_get(repr) }
}
- #[doc(hidden)]
unsafe fn __release(repr: MaybeUninit<*mut c_void>) -> *mut Self {
unsafe { T::__unique_ptr_release(repr) }
}
- #[doc(hidden)]
unsafe fn __drop(repr: MaybeUninit<*mut c_void>) {
unsafe { T::__unique_ptr_drop(repr) }
}
diff --git a/src/unwind.rs b/src/unwind.rs
index 4967a219..18852da7 100644
--- a/src/unwind.rs
+++ b/src/unwind.rs
@@ -1,26 +1,39 @@
#![allow(missing_docs)]
-use std::io::{self, Write};
-use std::panic::{self, AssertUnwindSafe};
-use std::process;
+use core::mem;
-pub fn catch_unwind<F, R>(label: &'static str, foreign_call: F) -> R
+pub fn prevent_unwind<F, R>(label: &'static str, foreign_call: F) -> R
where
F: FnOnce() -> R,
{
- // Regarding the AssertUnwindSafe: we immediately abort on panic so it
- // doesn't matter whether the types involved are unwind-safe. The UnwindSafe
- // bound on catch_unwind is about ensuring nothing is in a broken state if
- // your program plans to continue after the panic.
- match panic::catch_unwind(AssertUnwindSafe(foreign_call)) {
- Ok(ret) => ret,
- Err(_) => abort(label),
- }
+ // Goal is to make it impossible to propagate a panic across the C interface
+ // of an extern "Rust" function, which would be Undefined Behavior. We
+ // transform such panicks into a deterministic abort instead. When cxx is
+ // built in an application using panic=abort, this guard object is compiled
+ // out because its destructor is statically unreachable. When built with
+ // panic=unwind, an unwind from the foreign call will attempt to drop the
+ // guard object leading to a double panic, which is defined by Rust to
+ // abort. In no_std programs, on most platforms the current mechanism for
+ // this is for core::intrinsics::abort to invoke an invalid instruction. On
+ // Unix, the process will probably terminate with a signal like SIGABRT,
+ // SIGILL, SIGTRAP, SIGSEGV or SIGBUS. The precise behaviour is not
+ // guaranteed and not stable, but is safe.
+ let guard = Guard { label };
+
+ let ret = foreign_call();
+
+ // If we made it here, no uncaught panic occurred during the foreign call.
+ mem::forget(guard);
+ ret
}
-#[cold]
-fn abort(label: &'static str) -> ! {
- let mut stderr = io::stderr();
- let _ = writeln!(stderr, "Error: panic in ffi function {}, aborting.", label);
- process::abort();
+struct Guard {
+ label: &'static str,
+}
+
+impl Drop for Guard {
+ #[cold]
+ fn drop(&mut self) {
+ panic!("panic in ffi function {}, aborting.", self.label);
+ }
}
diff --git a/src/weak_ptr.rs b/src/weak_ptr.rs
index 8a9f1a68..e9320f37 100644
--- a/src/weak_ptr.rs
+++ b/src/weak_ptr.rs
@@ -114,11 +114,9 @@ pub unsafe trait WeakPtrTarget {
macro_rules! impl_weak_ptr_target {
($segment:expr, $name:expr, $ty:ty) => {
unsafe impl WeakPtrTarget for $ty {
- #[doc(hidden)]
fn __typename(f: &mut fmt::Formatter) -> fmt::Result {
f.write_str($name)
}
- #[doc(hidden)]
unsafe fn __null(new: *mut c_void) {
extern "C" {
attr! {
@@ -128,7 +126,6 @@ macro_rules! impl_weak_ptr_target {
}
unsafe { __null(new) }
}
- #[doc(hidden)]
unsafe fn __clone(this: *const c_void, new: *mut c_void) {
extern "C" {
attr! {
@@ -138,7 +135,6 @@ macro_rules! impl_weak_ptr_target {
}
unsafe { __clone(this, new) }
}
- #[doc(hidden)]
unsafe fn __downgrade(shared: *const c_void, weak: *mut c_void) {
extern "C" {
attr! {
@@ -148,7 +144,6 @@ macro_rules! impl_weak_ptr_target {
}
unsafe { __downgrade(shared, weak) }
}
- #[doc(hidden)]
unsafe fn __upgrade(weak: *const c_void, shared: *mut c_void) {
extern "C" {
attr! {
@@ -158,7 +153,6 @@ macro_rules! impl_weak_ptr_target {
}
unsafe { __upgrade(weak, shared) }
}
- #[doc(hidden)]
unsafe fn __drop(this: *mut c_void) {
extern "C" {
attr! {