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) { fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
let supported = !is_unsized(cx, &ty.inner) let supported = !is_unsized(cx, &ty.inner)
|| match &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, _ => false,
}; };

View File

@ -11,6 +11,7 @@ pub enum TrivialReason<'a> {
FunctionReturn(&'a ExternFn), FunctionReturn(&'a ExternFn),
BoxTarget, BoxTarget,
VecElement, VecElement,
SliceElement { mutable: bool },
UnpinnedMut(&'a ExternFn), UnpinnedMut(&'a ExternFn),
} }
@ -105,6 +106,14 @@ pub fn required_trivial_reasons<'a>(
insist_extern_types_are_trivial(ident, reason); 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 return_of = Set::new();
let mut box_target = false; let mut box_target = false;
let mut vec_element = false; let mut vec_element = false;
let mut slice_shared_element = false;
let mut slice_mut_element = false;
let mut unpinned_mut = Set::new(); let mut unpinned_mut = Set::new();
for reason in self.reasons { 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::BoxTarget => box_target = true,
TrivialReason::VecElement => vec_element = true, TrivialReason::VecElement => vec_element = true,
TrivialReason::SliceElement { mutable } => {
if *mutable {
slice_mut_element = true;
} else {
slice_shared_element = true;
}
}
TrivialReason::UnpinnedMut(efn) => { TrivialReason::UnpinnedMut(efn) => {
unpinned_mut.insert(&efn.name.rust); 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, 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() { if !unpinned_mut.is_empty() {
clauses.push(Clause::Set { clauses.push(Clause::Set {
article: "a", article: "a",
@ -219,12 +246,21 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
desc: &'a str, desc: &'a str,
param: &'a Pair, param: &'a Pair,
}, },
Slice {
article: &'a str,
desc: &'a str,
shared: bool,
mutable: bool,
param: &'a Pair,
},
} }
impl<'a> Clause<'a> { impl<'a> Clause<'a> {
fn article(&self) -> &'a str { fn article(&self) -> &'a str {
match self { 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, desc,
param, param,
} => write!(f, "{}<{}>", desc, param.rust), } => 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]); 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;
| ^^^^^^^^^^^