Skip to content

Commit b110dfb

Browse files
authored
Merge pull request #541 from dtolnay/vec-extern
Fix Vec containing shared type from other module
2 parents 56f78f3 + a7c8007 commit b110dfb

File tree

8 files changed

+79
-0
lines changed

8 files changed

+79
-0
lines changed

syntax/check.rs

+2
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,7 @@ fn check_type_box(cx: &mut Check, ptr: &Ty1) {
9393
fn check_type_rust_vec(cx: &mut Check, ty: &Ty1) {
9494
if let Type::Ident(ident) = &ty.inner {
9595
if cx.types.cxx.contains(&ident.rust)
96+
&& !cx.types.aliases.contains_key(&ident.rust)
9697
&& !cx.types.structs.contains_key(&ident.rust)
9798
&& !cx.types.enums.contains_key(&ident.rust)
9899
{
@@ -328,6 +329,7 @@ fn check_api_type(cx: &mut Check, ety: &ExternType) {
328329
TrivialReason::StructField(strct) => format!("a field of `{}`", strct.name.rust),
329330
TrivialReason::FunctionArgument(efn) => format!("an argument of `{}`", efn.name.rust),
330331
TrivialReason::FunctionReturn(efn) => format!("a return value of `{}`", efn.name.rust),
332+
TrivialReason::VecElement => format!("a vector element in Vec<{}>", ety.name.rust),
331333
};
332334
let msg = format!(
333335
"needs a cxx::ExternType impl in order to be used as {}",

syntax/types.rs

+7
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,12 @@ impl<'a> Types<'a> {
201201
_ => {}
202202
}
203203
}
204+
for ty in &all {
205+
if let Type::RustVec(ty) = ty {
206+
let reason = TrivialReason::VecElement;
207+
insist_alias_types_are_trivial(&ty.inner, reason);
208+
}
209+
}
204210

205211
let mut types = Types {
206212
all,
@@ -297,6 +303,7 @@ pub enum TrivialReason<'a> {
297303
StructField(&'a Struct),
298304
FunctionArgument(&'a ExternFn),
299305
FunctionReturn(&'a ExternFn),
306+
VecElement,
300307
}
301308

302309
fn duplicate_name(cx: &mut Errors, sp: impl ToTokens, ident: &Ident) {

tests/BUCK

+1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ cxx_library(
3232
],
3333
headers = {
3434
"ffi/lib.rs.h": ":bridge/header",
35+
"ffi/module.rs.h": ":module/header",
3536
"ffi/tests.h": "ffi/tests.h",
3637
},
3738
deps = ["//:core"],

tests/BUILD

+1
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ cc_library(
3535
hdrs = ["ffi/tests.h"],
3636
deps = [
3737
":bridge/include",
38+
":module/include",
3839
"//:core",
3940
],
4041
)

tests/ffi/lib.rs

+8
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,10 @@ pub mod ffi {
184184
}
185185

186186
extern "C++" {
187+
include!("tests/ffi/module.rs.h");
188+
187189
type COwnedEnum;
190+
type Job = crate::module::ffi::Job;
188191
}
189192

190193
#[repr(u32)]
@@ -211,6 +214,7 @@ pub mod ffi {
211214
fn r_return_unique_ptr_string() -> UniquePtr<CxxString>;
212215
fn r_return_rust_vec() -> Vec<u8>;
213216
fn r_return_rust_vec_string() -> Vec<String>;
217+
fn r_return_rust_vec_extern_struct() -> Vec<Job>;
214218
fn r_return_ref_rust_vec(shared: &Shared) -> &Vec<u8>;
215219
fn r_return_mut_rust_vec(shared: &mut Shared) -> &mut Vec<u8>;
216220
fn r_return_identity(_: usize) -> usize;
@@ -435,6 +439,10 @@ fn r_return_rust_vec_string() -> Vec<String> {
435439
Vec::new()
436440
}
437441

442+
fn r_return_rust_vec_extern_struct() -> Vec<ffi::Job> {
443+
Vec::new()
444+
}
445+
438446
fn r_return_ref_rust_vec(shared: &ffi::Shared) -> &Vec<u8> {
439447
let _ = shared;
440448
unimplemented!()

tests/ffi/module.rs

+4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
#[cxx::bridge(namespace = "tests")]
22
pub mod ffi {
3+
struct Job {
4+
raw: u32,
5+
}
6+
37
unsafe extern "C++" {
48
include!("tests/ffi/tests.h");
59

tests/ui/vec_opaque.rs

+34
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
#[cxx::bridge]
2+
mod handle {
3+
extern "C++" {
4+
type Job;
5+
}
6+
}
7+
8+
#[cxx::bridge]
9+
mod ffi1 {
10+
extern "C++" {
11+
type Job;
12+
}
13+
14+
extern "Rust" {
15+
fn f() -> Vec<Job>;
16+
}
17+
}
18+
19+
#[cxx::bridge]
20+
mod ffi2 {
21+
extern "C++" {
22+
type Job = crate::handle::Job;
23+
}
24+
25+
extern "Rust" {
26+
fn f() -> Vec<Job>;
27+
}
28+
}
29+
30+
fn f() -> Vec<handle::Job> {
31+
unimplemented!()
32+
}
33+
34+
fn main() {}

tests/ui/vec_opaque.stderr

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error: Rust Vec containing C++ type is not supported yet
2+
--> $DIR/vec_opaque.rs:15:19
3+
|
4+
15 | fn f() -> Vec<Job>;
5+
| ^^^^^^^^
6+
7+
error: needs a cxx::ExternType impl in order to be used as a vector element in Vec<Job>
8+
--> $DIR/vec_opaque.rs:11:9
9+
|
10+
11 | type Job;
11+
| ^^^^^^^^
12+
13+
error[E0271]: type mismatch resolving `<handle::Job as ExternType>::Kind == Trivial`
14+
--> $DIR/vec_opaque.rs:22:9
15+
|
16+
22 | type Job = crate::handle::Job;
17+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `Trivial`, found enum `cxx::kind::Opaque`
18+
|
19+
::: $WORKSPACE/src/extern_type.rs
20+
|
21+
| pub fn verify_extern_kind<T: ExternType<Kind = Kind>, Kind: self::Kind>() {}
22+
| ----------- required by this bound in `verify_extern_kind`

0 commit comments

Comments
 (0)