mirror of
https://gitee.com/openharmony/third_party_rust_cxx
synced 2024-11-23 23:29:50 +00:00
Switch to build-time squashing of 'new' method.
This commit is contained in:
parent
117d3baac7
commit
9f7ff2e3a6
@ -1247,9 +1247,9 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
|
||||
let can_construct_from_value = match ty {
|
||||
// Some aliases are to opaque types; some are to trivial types.
|
||||
// We can't know at code generation time, so we generate both C++
|
||||
// and Rust side bindings for a "new" method anyway. But that
|
||||
// Rust code will explode at runtime if anyone tries to call it on
|
||||
// an opaque type.
|
||||
// and Rust side bindings for a "new" method anyway. But the Rust
|
||||
// code can't be called for Opaque types because the 'new'
|
||||
// method is not implemented.
|
||||
Type::Ident(ident) => types.structs.contains_key(ident) || types.aliases.contains_key(ident),
|
||||
_ => false,
|
||||
};
|
||||
|
@ -815,21 +815,12 @@ fn expand_unique_ptr(
|
||||
let link_drop = format!("{}drop", prefix);
|
||||
|
||||
let new_method = if types.structs.contains_key(ident) || types.aliases.contains_key(ident) {
|
||||
let trivial_assertion: Option<syn::Stmt> = if types.aliases.contains_key(ident) {
|
||||
Some(parse_quote! {
|
||||
< < #ident as :: cxx :: ExternType > :: Kind as :: cxx :: kind :: Kind > :: assert_trivial();
|
||||
})
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Some(quote! {
|
||||
fn __new(mut value: Self) -> *mut ::std::ffi::c_void {
|
||||
extern "C" {
|
||||
#[link_name = #link_new]
|
||||
fn __new(this: *mut *mut ::std::ffi::c_void, value: *mut #ident);
|
||||
}
|
||||
#trivial_assertion
|
||||
let mut repr = ::std::ptr::null_mut::<::std::ffi::c_void>();
|
||||
unsafe { __new(&mut repr, &mut value) }
|
||||
repr
|
||||
|
@ -165,17 +165,9 @@ pub mod kind {
|
||||
/// indirection.
|
||||
pub enum Trivial {}
|
||||
|
||||
pub trait Kind: private::Sealed {
|
||||
fn assert_trivial();
|
||||
}
|
||||
impl Kind for Opaque {
|
||||
fn assert_trivial() {
|
||||
panic!("Type not trivial");
|
||||
}
|
||||
}
|
||||
impl Kind for Trivial {
|
||||
fn assert_trivial() {}
|
||||
}
|
||||
pub trait Kind: private::Sealed {}
|
||||
impl Kind for Opaque {}
|
||||
impl Kind for Trivial {}
|
||||
}
|
||||
|
||||
mod private {
|
||||
|
@ -1,5 +1,7 @@
|
||||
use crate::cxx_string::CxxString;
|
||||
use crate::cxx_vector::{self, CxxVector, VectorElement};
|
||||
use crate::ExternType;
|
||||
use crate::kind::Trivial;
|
||||
use core::ffi::c_void;
|
||||
use core::fmt::{self, Debug, Display};
|
||||
use core::marker::PhantomData;
|
||||
@ -32,7 +34,9 @@ where
|
||||
}
|
||||
|
||||
/// Allocates memory on the heap and makes a UniquePtr pointing to it.
|
||||
pub fn new(value: T) -> Self {
|
||||
pub fn new(value: T) -> Self
|
||||
where
|
||||
T: ExternType<Kind = Trivial> {
|
||||
UniquePtr {
|
||||
repr: T::__new(value),
|
||||
ty: PhantomData,
|
||||
|
@ -12,14 +12,12 @@
|
||||
pub mod ffi2 {
|
||||
impl UniquePtr<D> {}
|
||||
impl UniquePtr<E> {}
|
||||
impl UniquePtr<F> {}
|
||||
|
||||
extern "C" {
|
||||
include!("tests/ffi/tests.h");
|
||||
|
||||
type D = crate::other::D;
|
||||
type E = crate::other::E;
|
||||
type F = crate::other::F;
|
||||
|
||||
fn c_take_trivial_ptr(d: UniquePtr<D>);
|
||||
fn c_take_trivial_ref(d: &D);
|
||||
|
@ -14,25 +14,17 @@ mod other {
|
||||
use cxx::kind::{Opaque, Trivial};
|
||||
use cxx::{type_id, CxxString, ExternType};
|
||||
|
||||
// Trivial.
|
||||
#[repr(C)]
|
||||
pub struct D {
|
||||
pub d: u64,
|
||||
}
|
||||
|
||||
// Opaque, and has realistic complexity.
|
||||
#[repr(C)]
|
||||
pub struct E {
|
||||
e_str: CxxString,
|
||||
e: u64,
|
||||
}
|
||||
|
||||
// Opaque, but simple enough that bad code can try to create it.
|
||||
#[repr(C)]
|
||||
pub struct F {
|
||||
pub f: u64,
|
||||
}
|
||||
|
||||
unsafe impl ExternType for D {
|
||||
type Id = type_id!("tests::D");
|
||||
type Kind = Trivial;
|
||||
@ -42,11 +34,6 @@ mod other {
|
||||
type Id = type_id!("tests::E");
|
||||
type Kind = Opaque;
|
||||
}
|
||||
|
||||
unsafe impl ExternType for F {
|
||||
type Id = type_id!("tests::F");
|
||||
type Kind = Opaque;
|
||||
}
|
||||
}
|
||||
|
||||
#[cxx::bridge(namespace = tests)]
|
||||
|
@ -37,10 +37,6 @@ struct E {
|
||||
std::string e_str;
|
||||
};
|
||||
|
||||
struct F {
|
||||
uint64_t f;
|
||||
};
|
||||
|
||||
enum COwnedEnum {
|
||||
CVal1,
|
||||
CVal2,
|
||||
|
@ -207,7 +207,4 @@ fn test_extern_opaque() {
|
||||
let e = ffi2::c_return_opaque_ptr();
|
||||
check!(ffi2::c_take_opaque_ref(e.as_ref().unwrap()));
|
||||
check!(ffi2::c_take_opaque_ptr(e));
|
||||
assert!(std::panic::catch_unwind(|| {
|
||||
cxx::UniquePtr::new(ffi2::F { f: 42 })
|
||||
}).is_err());
|
||||
}
|
||||
|
26
tests/ui/unique_ptr_to_opaque.rs
Normal file
26
tests/ui/unique_ptr_to_opaque.rs
Normal file
@ -0,0 +1,26 @@
|
||||
mod outside {
|
||||
#[repr(C)]
|
||||
pub struct C {
|
||||
pub a: u8,
|
||||
}
|
||||
unsafe impl cxx::ExternType for C {
|
||||
type Id = cxx::type_id!("C");
|
||||
type Kind = cxx::kind::Opaque;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cxx::bridge]
|
||||
mod ffi {
|
||||
impl UniquePtr<C> {}
|
||||
|
||||
extern "C" {
|
||||
type C = crate::outside::C;
|
||||
}
|
||||
|
||||
impl UniquePtr<C> {}
|
||||
}
|
||||
|
||||
fn main() {
|
||||
cxx::UniquePtr::new(outside::C { a: 4 } );
|
||||
}
|
7
tests/ui/unique_ptr_to_opaque.stderr
Normal file
7
tests/ui/unique_ptr_to_opaque.stderr
Normal file
@ -0,0 +1,7 @@
|
||||
error[E0271]: type mismatch resolving `<outside::C as ExternType>::Kind == Trivial`
|
||||
--> $DIR/unique_ptr_to_opaque.rs:25:5
|
||||
|
|
||||
25 | cxx::UniquePtr::new(outside::C { a: 4 } );
|
||||
| ^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
|
||||
|
|
||||
= note: required by `UniquePtr::<T>::new`
|
Loading…
Reference in New Issue
Block a user