Skip to content

Commit 20cb73a

Browse files
committed
Support slice of trivial extern type alias
1 parent 17d3878 commit 20cb73a

File tree

5 files changed

+105
-2
lines changed

5 files changed

+105
-2
lines changed

syntax/check.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,9 @@ fn check_type_ptr(cx: &mut Check, ty: &Ptr) {
266266
fn check_type_slice_ref(cx: &mut Check, ty: &SliceRef) {
267267
let supported = !is_unsized(cx, &ty.inner)
268268
|| match &ty.inner {
269-
Type::Ident(ident) => cx.types.rust.contains(&ident.rust),
269+
Type::Ident(ident) => {
270+
cx.types.rust.contains(&ident.rust) || cx.types.aliases.contains_key(&ident.rust)
271+
}
270272
_ => false,
271273
};
272274

syntax/trivial.rs

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ pub enum TrivialReason<'a> {
1111
FunctionReturn(&'a ExternFn),
1212
BoxTarget,
1313
VecElement,
14+
SliceElement { mutable: bool },
1415
UnpinnedMut(&'a ExternFn),
1516
}
1617

@@ -105,6 +106,14 @@ pub fn required_trivial_reasons<'a>(
105106
insist_extern_types_are_trivial(ident, reason);
106107
}
107108
}
109+
Type::SliceRef(ty) => {
110+
if let Type::Ident(ident) = &ty.inner {
111+
let reason = TrivialReason::SliceElement {
112+
mutable: ty.mutable,
113+
};
114+
insist_extern_types_are_trivial(ident, reason);
115+
}
116+
}
108117
_ => {}
109118
}
110119
}
@@ -128,6 +137,8 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
128137
let mut return_of = Set::new();
129138
let mut box_target = false;
130139
let mut vec_element = false;
140+
let mut slice_shared_element = false;
141+
let mut slice_mut_element = false;
131142
let mut unpinned_mut = Set::new();
132143

133144
for reason in self.reasons {
@@ -143,6 +154,13 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
143154
}
144155
TrivialReason::BoxTarget => box_target = true,
145156
TrivialReason::VecElement => vec_element = true,
157+
TrivialReason::SliceElement { mutable } => {
158+
if *mutable {
159+
slice_mut_element = true;
160+
} else {
161+
slice_shared_element = true;
162+
}
163+
}
146164
TrivialReason::UnpinnedMut(efn) => {
147165
unpinned_mut.insert(&efn.name.rust);
148166
}
@@ -185,6 +203,15 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
185203
param: self.name,
186204
});
187205
}
206+
if slice_shared_element || slice_mut_element {
207+
clauses.push(Clause::Slice {
208+
article: "a",
209+
desc: "slice element in",
210+
shared: slice_shared_element,
211+
mutable: slice_mut_element,
212+
param: self.name,
213+
});
214+
}
188215
if !unpinned_mut.is_empty() {
189216
clauses.push(Clause::Set {
190217
article: "a",
@@ -219,12 +246,21 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
219246
desc: &'a str,
220247
param: &'a Pair,
221248
},
249+
Slice {
250+
article: &'a str,
251+
desc: &'a str,
252+
shared: bool,
253+
mutable: bool,
254+
param: &'a Pair,
255+
},
222256
}
223257

224258
impl<'a> Clause<'a> {
225259
fn article(&self) -> &'a str {
226260
match self {
227-
Clause::Set { article, .. } | Clause::Ty1 { article, .. } => article,
261+
Clause::Set { article, .. }
262+
| Clause::Ty1 { article, .. }
263+
| Clause::Slice { article, .. } => article,
228264
}
229265
}
230266

@@ -249,6 +285,25 @@ pub fn as_what<'a>(name: &'a Pair, reasons: &'a [TrivialReason]) -> impl Display
249285
desc,
250286
param,
251287
} => write!(f, "{}<{}>", desc, param.rust),
288+
Clause::Slice {
289+
article: _,
290+
desc,
291+
shared,
292+
mutable,
293+
param,
294+
} => {
295+
write!(f, "{} ", desc)?;
296+
if *shared {
297+
write!(f, "&[{}]", param.rust)?;
298+
}
299+
if *shared && *mutable {
300+
write!(f, " and ")?;
301+
}
302+
if *mutable {
303+
write!(f, "&mut [{}]", param.rust)?;
304+
}
305+
Ok(())
306+
}
252307
}
253308
}
254309
}

tests/ui/slice_of_type_alias.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use cxx::{type_id, ExternType};
2+
3+
#[repr(C)]
4+
struct ElementTrivial(usize);
5+
6+
#[repr(C)]
7+
struct ElementOpaque(usize);
8+
9+
#[cxx::bridge]
10+
mod ffi {
11+
unsafe extern "C++" {
12+
type ElementTrivial = crate::ElementTrivial;
13+
type ElementOpaque = crate::ElementOpaque;
14+
15+
fn f(slice: &mut [ElementTrivial]);
16+
fn g(slice: &[ElementOpaque]);
17+
}
18+
}
19+
20+
unsafe impl ExternType for ElementTrivial {
21+
type Id = type_id!("ElementTrivial");
22+
type Kind = cxx::kind::Trivial;
23+
}
24+
25+
unsafe impl ExternType for ElementOpaque {
26+
type Id = type_id!("ElementOpaque");
27+
type Kind = cxx::kind::Opaque;
28+
}
29+
30+
fn main() {}

tests/ui/slice_of_type_alias.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error[E0271]: type mismatch resolving `<ElementOpaque as ExternType>::Kind == Trivial`
2+
--> $DIR/slice_of_type_alias.rs:13:9
3+
|
4+
13 | type ElementOpaque = crate::ElementOpaque;
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
6+
|
7+
::: $WORKSPACE/src/extern_type.rs
8+
|
9+
| pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
10+
| ----------- required by this bound in `verify_extern_kind`

tests/ui/slice_unsupported.stderr

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,9 @@ error: unsupported &mut [T] element type: opaque C++ type is not supported yet
33
|
44
6 | fn f(_: &mut [Opaque]);
55
| ^^^^^^^^^^^^^
6+
7+
error: needs a cxx::ExternType impl in order to be used as a slice element in &mut [Opaque]
8+
--> $DIR/slice_unsupported.rs:4:9
9+
|
10+
4 | type Opaque;
11+
| ^^^^^^^^^^^

0 commit comments

Comments
 (0)