Support slice of trivial extern type alias

This commit is contained in:
David Tolnay 2021-07-23 14:09:33 -07:00
parent 17d3878b8b
commit 20cb73ae6f
No known key found for this signature in database
GPG Key ID: F9BA143B95FF6D82
5 changed files with 105 additions and 2 deletions

View File

@ -266,7 +266,9 @@ fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
let supported = !is_unsized(cx, &ty.inner)
|| match &ty.inner {
Type::Ident(ident) => cx.types.rust.contains(&ident.rust),
Type::Ident(ident) => {
cx.types.rust.contains(&ident.rust) || cx.types.aliases.contains_key(&ident.rust)
}
_ => false,
};

View File

@ -11,6 +11,7 @@ pub enum TrivialReason<'a> {
FunctionReturn(&'a ExternFn),
BoxTarget,
VecElement,
SliceElement { mutable: bool },
UnpinnedMut(&'a ExternFn),
}
@ -105,6 +106,14 @@ pub fn required_trivial_reasons<'a>(
insist_extern_types_are_trivial(ident, reason);
}
}
Type::SliceRef(ty) => {
if let Type::Ident(ident) = &ty.inner {
let reason = TrivialReason::SliceElement {
mutable: ty.mutable,
};
insist_extern_types_are_trivial(ident, reason);
}
}
_ => {}
}
}
@ -128,6 +137,8 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
let mut return_of = Set::new();
let mut box_target = false;
let mut vec_element = false;
let mut slice_shared_element = false;
let mut slice_mut_element = false;
let mut unpinned_mut = Set::new();
for reason in self.reasons {
@ -143,6 +154,13 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
}
TrivialReason::BoxTarget => box_target = true,
TrivialReason::VecElement => vec_element = true,
TrivialReason::SliceElement { mutable } => {
if *mutable {
slice_mut_element = true;
} else {
slice_shared_element = true;
}
}
TrivialReason::UnpinnedMut(efn) => {
unpinned_mut.insert(&efn.name.rust);
}
@ -185,6 +203,15 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
param: self.name,
});
}
if slice_shared_element || slice_mut_element {
clauses.push(Clause::Slice {
article: "a",
desc: "slice element in",
shared: slice_shared_element,
mutable: slice_mut_element,
param: self.name,
});
}
if !unpinned_mut.is_empty() {
clauses.push(Clause::Set {
article: "a",
@ -219,12 +246,21 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
desc: &'a str,
param: &'a Pair,
},
Slice {
article: &'a str,
desc: &'a str,
shared: bool,
mutable: bool,
param: &'a Pair,
},
}
impl<'a> Clause<'a> {
fn article(&self) -> &'a str {
match self {
Clause::Set { article, .. } | Clause::Ty1 { article, .. } => article,
Clause::Set { article, .. }
| Clause::Ty1 { article, .. }
| Clause::Slice { article, .. } => article,
}
}
@ -249,6 +285,25 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
desc,
param,
} => write!(f, "{}<{}>", desc, param.rust),
Clause::Slice {
article: _,
desc,
shared,
mutable,
param,
} => {
write!(f, "{} ", desc)?;
if *shared {
write!(f, "&[{}]", param.rust)?;
}
if *shared && *mutable {
write!(f, " and ")?;
}
if *mutable {
write!(f, "&mut [{}]", param.rust)?;
}
Ok(())
}
}
}
}

View File

@ -0,0 +1,30 @@
use cxx::{type_id, ExternType};
#[repr(C)]
struct ElementTrivial(usize);
#[repr(C)]
struct ElementOpaque(usize);
#[cxx::bridge]
mod ffi {
unsafe extern "C++" {
type ElementTrivial = crate::ElementTrivial;
type ElementOpaque = crate::ElementOpaque;
fn f(slice: &mut [ElementTrivial]);
fn g(slice: &[ElementOpaque]);
}
}
unsafe impl ExternType for ElementTrivial {
type Id = type_id!("ElementTrivial");
type Kind = cxx::kind::Trivial;
}
unsafe impl ExternType for ElementOpaque {
type Id = type_id!("ElementOpaque");
type Kind = cxx::kind::Opaque;
}
fn main() {}

View File

@ -0,0 +1,10 @@
error[E0271]: type mismatch resolving `<ElementOpaque as ExternType>::Kind == Trivial`
--> $DIR/slice_of_type_alias.rs:13:9
|
13 | type ElementOpaque = crate::ElementOpaque;
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
|
::: $WORKSPACE/src/extern_type.rs
|
| pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
| ----------- required by this bound in `verify_extern_kind`

View File

@ -3,3 +3,9 @@ error: unsupported &mut [T] element type: opaque C++ type is not supported yet
|
6 | fn f(_: &mut [Opaque]);
| ^^^^^^^^^^^^^
error: needs a cxx::ExternType impl in order to be used as a slice element in &mut [Opaque]
--> $DIR/slice_unsupported.rs:4:9
|
4 | type Opaque;
| ^^^^^^^^^^^