Skip to content

Commit 75f435e

Browse files
committed
Include namespace in all identifiers.
This change is the first step towards including a namespace into all(*) C++ identifiers. In this commit, there is no intentional functional difference: a single namespace continues to apply to the entire #[cxx::bridge]; it just happens to be stored differently. (*) = This change aims to include a namespace for: * C++ types * C++ functions but not for: * C++ fields * C++ enum variants * Rust types/functions/anything. A 'QualifiedIdent' struct is used for the first category of things; plain old proc_macro2::Ident for the latter. It may be that methods are being treated incorrectly, because they're functions yet should not have a globally-scoped name. A subsequent commit may need to fix that. At the moment, the Namespace (included in each QualifiedIdent) is ruthlessly cloned all over the place. As a given namespace is likely to be applicable to many types and functions, it may save significant memory in future to use Rc<> here. But let's not optimise too early. This commit does not currently output the namespace name in any different ways or different places (intentionally). syntax/mod.rs has a Boolean constant USE_FULLY_QUALIFIED_NAMES which will enable that, and it completely breaks everything. Substantial changes to both Rust and C++ code generation will be required to use this. It may be desirable to move the QualifiedIdent code out of mod.rs. The rough sequence of commits in mind are: 1) This commit (just stores the namespaces) 2) Use them when writing Rust and C++ code as necessary 3) Allow the current namespace attribute to be overridden by finer-grained namespace attributes on individual functions 4) Consider allowing sub-mods which can also have a namespace attribute. 5) Future: Introduce a resolution pass which tries to resolve a given identifier to a target symbol, after all symbols have been read. Support 'use' statements.
1 parent cca5215 commit 75f435e

File tree

12 files changed

+330
-167
lines changed

12 files changed

+330
-167
lines changed

gen/src/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ pub(super) fn generate(syntax: File, opt: &Opt) -> Result<GeneratedCode> {
109109
.ok_or(Error::NoBridgeMod)?;
110110
let ref namespace = bridge.namespace;
111111
let trusted = bridge.unsafety.is_some();
112-
let ref apis = syntax::parse_items(errors, bridge.content, trusted);
112+
let ref apis = syntax::parse_items(errors, bridge.content, trusted, namespace);
113113
let ref types = Types::collect(errors, apis);
114114
errors.propagate()?;
115-
check::typecheck(errors, namespace, apis, types);
115+
check::typecheck(errors, apis, types);
116116
errors.propagate()?;
117117
// Some callers may wish to generate both header and C++
118118
// from the same token stream to avoid parsing twice. But others

gen/src/write.rs

Lines changed: 23 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@ use crate::gen::{include, Opt};
33
use crate::syntax::atom::Atom::{self, *};
44
use crate::syntax::namespace::Namespace;
55
use crate::syntax::symbol::Symbol;
6-
use crate::syntax::{mangle, Api, Enum, ExternFn, ExternType, Signature, Struct, Type, Types, Var};
6+
use crate::syntax::{
7+
mangle, Api, Enum, ExternFn, ExternType, QualifiedIdent, Signature, Struct, Type, Types, Var,
8+
};
79
use proc_macro2::Ident;
810
use std::collections::HashMap;
911

@@ -133,7 +135,7 @@ pub(super) fn gen(
133135
fn write_includes(out: &mut OutFile, types: &Types) {
134136
for ty in types {
135137
match ty {
136-
Type::Ident(ident) => match Atom::from(ident) {
138+
Type::Ident(ident) => match Atom::from_qualified_ident(ident) {
137139
Some(U8) | Some(U16) | Some(U32) | Some(U64) | Some(I8) | Some(I16) | Some(I32)
138140
| Some(I64) => out.include.cstdint = true,
139141
Some(Usize) => out.include.cstddef = true,
@@ -349,11 +351,11 @@ fn write_struct(out: &mut OutFile, strct: &Struct) {
349351
writeln!(out, "#endif // {}", guard);
350352
}
351353

352-
fn write_struct_decl(out: &mut OutFile, ident: &Ident) {
354+
fn write_struct_decl(out: &mut OutFile, ident: &QualifiedIdent) {
353355
writeln!(out, "struct {};", ident);
354356
}
355357

356-
fn write_struct_using(out: &mut OutFile, ident: &Ident) {
358+
fn write_struct_using(out: &mut OutFile, ident: &QualifiedIdent) {
357359
writeln!(out, "using {} = {};", ident, ident);
358360
}
359361

@@ -410,7 +412,7 @@ fn check_enum(out: &mut OutFile, enm: &Enum) {
410412
}
411413
}
412414

413-
fn check_trivial_extern_type(out: &mut OutFile, id: &Ident) {
415+
fn check_trivial_extern_type(out: &mut OutFile, id: &QualifiedIdent) {
414416
// NOTE: The following two static assertions are just nice-to-have and not
415417
// necessary for soundness. That's because triviality is always declared by
416418
// the user in the form of an unsafe impl of cxx::ExternType:
@@ -486,7 +488,7 @@ fn write_cxx_function_shim(
486488
} else {
487489
write_extern_return_type_space(out, &efn.ret, types);
488490
}
489-
let mangled = mangle::extern_fn(&out.namespace, efn);
491+
let mangled = mangle::extern_fn(efn);
490492
write!(out, "{}(", mangled);
491493
if let Some(receiver) = &efn.receiver {
492494
if receiver.mutability.is_none() {
@@ -632,17 +634,17 @@ fn write_function_pointer_trampoline(
632634
types: &Types,
633635
) {
634636
out.next_section();
635-
let r_trampoline = mangle::r_trampoline(&out.namespace, efn, var);
637+
let r_trampoline = mangle::r_trampoline(efn, var);
636638
let indirect_call = true;
637639
write_rust_function_decl_impl(out, &r_trampoline, f, types, indirect_call);
638640

639641
out.next_section();
640-
let c_trampoline = mangle::c_trampoline(&out.namespace, efn, var).to_string();
642+
let c_trampoline = mangle::c_trampoline(efn, var).to_string();
641643
write_rust_function_shim_impl(out, &c_trampoline, f, types, &r_trampoline, indirect_call);
642644
}
643645

644646
fn write_rust_function_decl(out: &mut OutFile, efn: &ExternFn, types: &Types, _: &Option<String>) {
645-
let link_name = mangle::extern_fn(&out.namespace, efn);
647+
let link_name = mangle::extern_fn(efn);
646648
let indirect_call = false;
647649
write_rust_function_decl_impl(out, &link_name, efn, types, indirect_call);
648650
}
@@ -700,7 +702,7 @@ fn write_rust_function_shim(out: &mut OutFile, efn: &ExternFn, types: &Types) {
700702
None => efn.ident.cxx.to_string(),
701703
Some(receiver) => format!("{}::{}", receiver.ty, efn.ident.cxx),
702704
};
703-
let invoke = mangle::extern_fn(&out.namespace, efn);
705+
let invoke = mangle::extern_fn(efn);
704706
let indirect_call = false;
705707
write_rust_function_shim_impl(out, &local_name, efn, types, &invoke, indirect_call);
706708
}
@@ -923,7 +925,7 @@ fn write_extern_arg(out: &mut OutFile, arg: &Var, types: &Types) {
923925

924926
fn write_type(out: &mut OutFile, ty: &Type) {
925927
match ty {
926-
Type::Ident(ident) => match Atom::from(ident) {
928+
Type::Ident(ident) => match Atom::from_qualified_ident(ident) {
927929
Some(atom) => write_atom(out, atom),
928930
None => write!(out, "{}", ident),
929931
},
@@ -1061,14 +1063,14 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
10611063
}
10621064
} else if let Type::RustVec(ty) = ty {
10631065
if let Type::Ident(inner) = &ty.inner {
1064-
if Atom::from(inner).is_none() {
1066+
if Atom::from_qualified_ident(inner).is_none() {
10651067
out.next_section();
10661068
write_rust_vec_extern(out, inner);
10671069
}
10681070
}
10691071
} else if let Type::UniquePtr(ptr) = ty {
10701072
if let Type::Ident(inner) = &ptr.inner {
1071-
if Atom::from(inner).is_none()
1073+
if Atom::from_qualified_ident(inner).is_none()
10721074
&& (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
10731075
{
10741076
out.next_section();
@@ -1077,7 +1079,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
10771079
}
10781080
} else if let Type::CxxVector(ptr) = ty {
10791081
if let Type::Ident(inner) = &ptr.inner {
1080-
if Atom::from(inner).is_none()
1082+
if Atom::from_qualified_ident(inner).is_none()
10811083
&& (!types.aliases.contains_key(inner) || types.explicit_impls.contains(ty))
10821084
{
10831085
out.next_section();
@@ -1097,7 +1099,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
10971099
}
10981100
} else if let Type::RustVec(ty) = ty {
10991101
if let Type::Ident(inner) = &ty.inner {
1100-
if Atom::from(inner).is_none() {
1102+
if Atom::from_qualified_ident(inner).is_none() {
11011103
write_rust_vec_impl(out, inner);
11021104
}
11031105
}
@@ -1107,7 +1109,7 @@ fn write_generic_instantiations(out: &mut OutFile, types: &Types) {
11071109
out.end_block("namespace rust");
11081110
}
11091111

1110-
fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
1112+
fn write_rust_box_extern(out: &mut OutFile, ident: &QualifiedIdent) {
11111113
let mut inner = String::new();
11121114
for name in &out.namespace {
11131115
inner += &name.to_string();
@@ -1131,7 +1133,7 @@ fn write_rust_box_extern(out: &mut OutFile, ident: &Ident) {
11311133
writeln!(out, "#endif // CXXBRIDGE05_RUST_BOX_{}", instance);
11321134
}
11331135

1134-
fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
1136+
fn write_rust_vec_extern(out: &mut OutFile, element: &QualifiedIdent) {
11351137
let element = Type::Ident(element.clone());
11361138
let inner = to_typename(&out.namespace, &element);
11371139
let instance = to_mangled(&out.namespace, &element);
@@ -1166,7 +1168,7 @@ fn write_rust_vec_extern(out: &mut OutFile, element: &Ident) {
11661168
writeln!(out, "#endif // CXXBRIDGE05_RUST_VEC_{}", instance);
11671169
}
11681170

1169-
fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
1171+
fn write_rust_box_impl(out: &mut OutFile, ident: &QualifiedIdent) {
11701172
let mut inner = String::new();
11711173
for name in &out.namespace {
11721174
inner += &name.to_string();
@@ -1186,7 +1188,7 @@ fn write_rust_box_impl(out: &mut OutFile, ident: &Ident) {
11861188
writeln!(out, "}}");
11871189
}
11881190

1189-
fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
1191+
fn write_rust_vec_impl(out: &mut OutFile, element: &QualifiedIdent) {
11901192
let element = Type::Ident(element.clone());
11911193
let inner = to_typename(&out.namespace, &element);
11921194
let instance = to_mangled(&out.namespace, &element);
@@ -1225,7 +1227,7 @@ fn write_rust_vec_impl(out: &mut OutFile, element: &Ident) {
12251227
writeln!(out, "}}");
12261228
}
12271229

1228-
fn write_unique_ptr(out: &mut OutFile, ident: &Ident, types: &Types) {
1230+
fn write_unique_ptr(out: &mut OutFile, ident: &QualifiedIdent, types: &Types) {
12291231
let ty = Type::Ident(ident.clone());
12301232
let instance = to_mangled(&out.namespace, &ty);
12311233

@@ -1315,7 +1317,7 @@ fn write_unique_ptr_common(out: &mut OutFile, ty: &Type, types: &Types) {
13151317
writeln!(out, "}}");
13161318
}
13171319

1318-
fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &Ident, types: &Types) {
1320+
fn write_cxx_vector(out: &mut OutFile, vector_ty: &Type, element: &QualifiedIdent, types: &Types) {
13191321
let element = Type::Ident(element.clone());
13201322
let inner = to_typename(&out.namespace, &element);
13211323
let instance = to_mangled(&out.namespace, &element);

macro/src/expand.rs

Lines changed: 25 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use crate::syntax::namespace::Namespace;
55
use crate::syntax::report::Errors;
66
use crate::syntax::symbol::Symbol;
77
use crate::syntax::{
8-
self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, Signature, Struct, Type, TypeAlias,
9-
Types,
8+
self, check, mangle, Api, Enum, ExternFn, ExternType, Impl, QualifiedIdent, Signature, Struct,
9+
Type, TypeAlias, Types,
1010
};
1111
use proc_macro2::{Ident, Span, TokenStream};
1212
use quote::{format_ident, quote, quote_spanned, ToTokens};
@@ -17,11 +17,11 @@ pub fn bridge(mut ffi: Module) -> Result<TokenStream> {
1717
let ref mut errors = Errors::new();
1818
let content = mem::take(&mut ffi.content);
1919
let trusted = ffi.unsafety.is_some();
20-
let ref apis = syntax::parse_items(errors, content, trusted);
20+
let namespace = &ffi.namespace;
21+
let ref apis = syntax::parse_items(errors, content, trusted, namespace);
2122
let ref types = Types::collect(errors, apis);
2223
errors.propagate()?;
23-
let namespace = &ffi.namespace;
24-
check::typecheck(errors, namespace, apis, types);
24+
check::typecheck(errors, apis, types);
2525
errors.propagate()?;
2626

2727
Ok(expand(ffi, apis, types))
@@ -51,11 +51,9 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
5151
}
5252
}
5353
Api::CxxFunction(efn) => {
54-
expanded.extend(expand_cxx_function_shim(namespace, efn, types));
55-
}
56-
Api::RustFunction(efn) => {
57-
hidden.extend(expand_rust_function_shim(namespace, efn, types))
54+
expanded.extend(expand_cxx_function_shim(efn, types));
5855
}
56+
Api::RustFunction(efn) => hidden.extend(expand_rust_function_shim(efn, types)),
5957
Api::TypeAlias(alias) => {
6058
expanded.extend(expand_type_alias(alias));
6159
hidden.extend(expand_type_alias_verify(namespace, alias, types));
@@ -67,27 +65,27 @@ fn expand(ffi: Module, apis: &[Api], types: &Types) -> TokenStream {
6765
let explicit_impl = types.explicit_impls.get(ty);
6866
if let Type::RustBox(ty) = ty {
6967
if let Type::Ident(ident) = &ty.inner {
70-
if Atom::from(ident).is_none() {
68+
if Atom::from_qualified_ident(ident).is_none() {
7169
hidden.extend(expand_rust_box(namespace, ident));
7270
}
7371
}
7472
} else if let Type::RustVec(ty) = ty {
7573
if let Type::Ident(ident) = &ty.inner {
76-
if Atom::from(ident).is_none() {
74+
if Atom::from_qualified_ident(ident).is_none() {
7775
hidden.extend(expand_rust_vec(namespace, ident));
7876
}
7977
}
8078
} else if let Type::UniquePtr(ptr) = ty {
8179
if let Type::Ident(ident) = &ptr.inner {
82-
if Atom::from(ident).is_none()
80+
if Atom::from_qualified_ident(ident).is_none()
8381
&& (explicit_impl.is_some() || !types.aliases.contains_key(ident))
8482
{
8583
expanded.extend(expand_unique_ptr(namespace, ident, types, explicit_impl));
8684
}
8785
}
8886
} else if let Type::CxxVector(ptr) = ty {
8987
if let Type::Ident(ident) = &ptr.inner {
90-
if Atom::from(ident).is_none()
88+
if Atom::from_qualified_ident(ident).is_none()
9189
&& (explicit_impl.is_some() || !types.aliases.contains_key(ident))
9290
{
9391
// Generate impl for CxxVector<T> if T is a struct or opaque
@@ -205,7 +203,7 @@ fn expand_cxx_type(namespace: &Namespace, ety: &ExternType) -> TokenStream {
205203
}
206204
}
207205

208-
fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
206+
fn expand_cxx_function_decl(efn: &ExternFn, types: &Types) -> TokenStream {
209207
let receiver = efn.receiver.iter().map(|receiver| {
210208
let receiver_type = receiver.ty();
211209
quote!(_: #receiver_type)
@@ -236,17 +234,17 @@ fn expand_cxx_function_decl(namespace: &Namespace, efn: &ExternFn, types: &Types
236234
let ret = expand_extern_type(efn.ret.as_ref().unwrap());
237235
outparam = Some(quote!(__return: *mut #ret));
238236
}
239-
let link_name = mangle::extern_fn(namespace, efn);
237+
let link_name = mangle::extern_fn(efn);
240238
let local_name = format_ident!("__{}", efn.ident.rust);
241239
quote! {
242240
#[link_name = #link_name]
243241
fn #local_name(#(#all_args,)* #outparam) #ret;
244242
}
245243
}
246244

247-
fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
245+
fn expand_cxx_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
248246
let doc = &efn.doc;
249-
let decl = expand_cxx_function_decl(namespace, efn, types);
247+
let decl = expand_cxx_function_decl(efn, types);
250248
let receiver = efn.receiver.iter().map(|receiver| {
251249
let ampersand = receiver.ampersand;
252250
let mutability = receiver.mutability;
@@ -306,9 +304,7 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
306304
.filter_map(|arg| {
307305
if let Type::Fn(f) = &arg.ty {
308306
let var = &arg.ident;
309-
Some(expand_function_pointer_trampoline(
310-
namespace, efn, var, f, types,
311-
))
307+
Some(expand_function_pointer_trampoline(efn, var, f, types))
312308
} else {
313309
None
314310
}
@@ -445,14 +441,13 @@ fn expand_cxx_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types
445441
}
446442

447443
fn expand_function_pointer_trampoline(
448-
namespace: &Namespace,
449444
efn: &ExternFn,
450445
var: &Ident,
451446
sig: &Signature,
452447
types: &Types,
453448
) -> TokenStream {
454-
let c_trampoline = mangle::c_trampoline(namespace, efn, var);
455-
let r_trampoline = mangle::r_trampoline(namespace, efn, var);
449+
let c_trampoline = mangle::c_trampoline(efn, var);
450+
let r_trampoline = mangle::r_trampoline(efn, var);
456451
let local_name = parse_quote!(__);
457452
let catch_unwind_label = format!("::{}::{}", efn.ident.rust, var);
458453
let shim = expand_rust_function_shim_impl(
@@ -508,8 +503,8 @@ fn expand_rust_type_assert_sized(ety: &ExternType) -> TokenStream {
508503
}
509504
}
510505

511-
fn expand_rust_function_shim(namespace: &Namespace, efn: &ExternFn, types: &Types) -> TokenStream {
512-
let link_name = mangle::extern_fn(namespace, efn);
506+
fn expand_rust_function_shim(efn: &ExternFn, types: &Types) -> TokenStream {
507+
let link_name = mangle::extern_fn(efn);
513508
let local_name = format_ident!("__{}", efn.ident.rust);
514509
let catch_unwind_label = format!("::{}", efn.ident.rust);
515510
let invoke = Some(&efn.ident.rust);
@@ -712,7 +707,7 @@ fn expand_type_alias_verify(
712707
verify
713708
}
714709

715-
fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
710+
fn type_id(namespace: &Namespace, ident: &QualifiedIdent) -> TokenStream {
716711
let mut path = String::new();
717712
for name in namespace {
718713
path += &name.to_string();
@@ -725,7 +720,7 @@ fn type_id(namespace: &Namespace, ident: &Ident) -> TokenStream {
725720
}
726721
}
727722

728-
fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
723+
fn expand_rust_box(namespace: &Namespace, ident: &QualifiedIdent) -> TokenStream {
729724
let link_prefix = format!("cxxbridge05$box${}{}$", namespace, ident);
730725
let link_uninit = format!("{}uninit", link_prefix);
731726
let link_drop = format!("{}drop", link_prefix);
@@ -754,7 +749,7 @@ fn expand_rust_box(namespace: &Namespace, ident: &Ident) -> TokenStream {
754749
}
755750
}
756751

757-
fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
752+
fn expand_rust_vec(namespace: &Namespace, elem: &QualifiedIdent) -> TokenStream {
758753
let link_prefix = format!("cxxbridge05$rust_vec${}{}$", namespace, elem);
759754
let link_new = format!("{}new", link_prefix);
760755
let link_drop = format!("{}drop", link_prefix);
@@ -801,7 +796,7 @@ fn expand_rust_vec(namespace: &Namespace, elem: &Ident) -> TokenStream {
801796

802797
fn expand_unique_ptr(
803798
namespace: &Namespace,
804-
ident: &Ident,
799+
ident: &QualifiedIdent,
805800
types: &Types,
806801
explicit_impl: Option<&Impl>,
807802
) -> TokenStream {
@@ -884,7 +879,7 @@ fn expand_unique_ptr(
884879

885880
fn expand_cxx_vector(
886881
namespace: &Namespace,
887-
elem: &Ident,
882+
elem: &QualifiedIdent,
888883
explicit_impl: Option<&Impl>,
889884
) -> TokenStream {
890885
let _ = explicit_impl;

0 commit comments

Comments
 (0)