Skip to content

Commit c434dc2

Browse files
authored
Merge pull request #1665 from anforowicz/encode-patch-version-in-prefix-of-cxx-generated-symbols
Encode patch-version in the prefix of cxx-generated symbols.
2 parents 071a560 + cb395ca commit c434dc2

File tree

2 files changed

+34
-16
lines changed

2 files changed

+34
-16
lines changed

syntax/mangle.rs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
// defining characteristics:
88
// - 2 segments
99
// - starts with cxxbridge
10+
// TODO: should these also include {CXXVERSION}?
1011
//
1112
// (b) Behavior on a builtin binding without generic parameter.
1213
// pattern: {CXXBRIDGE} $ {TYPE} $ {NAME}
@@ -15,6 +16,7 @@
1516
// defining characteristics:
1617
// - 3 segments
1718
// - starts with cxxbridge
19+
// TODO: should these also include {CXXVERSION}?
1820
//
1921
// (c) Behavior on a builtin binding with generic parameter.
2022
// pattern: {CXXBRIDGE} $ {TYPE} $ {PARAM...} $ {NAME}
@@ -24,33 +26,35 @@
2426
// defining characteristics:
2527
// - 4+ segments
2628
// - starts with cxxbridge
29+
// TODO: should these also include {CXXVERSION}? (always? or only for
30+
// ones implicitly or explicitly `impl`-ed by the user?)
2731
//
2832
// (d) User-defined extern function.
29-
// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {NAME}
33+
// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {CXXVERSION} $ {NAME}
3034
// examples:
31-
// - cxxbridge1$new_client
32-
// - org$rust$cxxbridge1$new_client
35+
// - cxxbridge1$v187$new_client
36+
// - org$rust$cxxbridge1$v187$new_client
3337
// defining characteristics:
34-
// - cxxbridge is second from end
38+
// - cxxbridge is third from end
3539
// FIXME: conflict with (a) if they collide with one of our one-off symbol names in the global namespace
3640
//
3741
// (e) User-defined extern member function.
38-
// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ {NAME}
42+
// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {CXXVERSION} $ {TYPE} $ {NAME}
3943
// examples:
40-
// - org$cxxbridge1$Struct$get
44+
// - org$cxxbridge1$v187$Struct$get
4145
// defining characteristics:
42-
// - cxxbridge is third from end
46+
// - cxxbridge is fourth from end
4347
// FIXME: conflict with (b) if e.g. user binds a type in global namespace that collides with our builtin type names
4448
//
4549
// (f) Operator overload.
46-
// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE} $ operator $ {NAME}
50+
// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {CXXVERSION} $ {TYPE} $ operator $ {NAME}
4751
// examples:
48-
// - org$rust$cxxbridge1$Struct$operator$eq
52+
// - org$rust$cxxbridge1$v187$Struct$operator$eq
4953
// defining characteristics:
5054
// - second segment from end is `operator` (not possible in type or namespace names)
5155
//
5256
// (g) Closure trampoline.
53-
// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {TYPE?} $ {NAME} $ {ARGUMENT} $ {DIRECTION}
57+
// pattern: {NAMESPACE...} $ {CXXBRIDGE} $ {CXXVERSION} $ {TYPE?} $ {NAME} $ {ARGUMENT} $ {DIRECTION}
5458
// examples:
5559
// - org$rust$cxxbridge1$Struct$invoke$f$0
5660
// defining characteristics:
@@ -81,6 +85,11 @@ use proc_macro2::Ident;
8185

8286
const CXXBRIDGE: &str = "cxxbridge1";
8387

88+
// Ignoring `CARGO_PKG_VERSION_MAJOR` and `...MINOR`, because they don't agree across
89+
// all the crates. For example `gen/lib/Cargo.toml` says `version = "0.7.xxx"`, but
90+
// `macro/Cargo.toml` says `version = "1.0.xxx"`.
91+
const CXXVERSION: &str = concat!("v", env!("CARGO_PKG_VERSION_PATCH"));
92+
8493
macro_rules! join {
8594
($($segment:expr),+ $(,)?) => {
8695
symbol::join(&[$(&$segment),+])
@@ -94,18 +103,20 @@ pub(crate) fn extern_fn(efn: &ExternFn, types: &Types) -> Symbol {
94103
join!(
95104
efn.name.namespace,
96105
CXXBRIDGE,
106+
CXXVERSION,
97107
self_type_ident.name.cxx,
98108
efn.name.rust,
99109
)
100110
}
101-
None => join!(efn.name.namespace, CXXBRIDGE, efn.name.rust),
111+
None => join!(efn.name.namespace, CXXBRIDGE, CXXVERSION, efn.name.rust),
102112
}
103113
}
104114

105115
pub(crate) fn operator(receiver: &Pair, operator: &'static str) -> Symbol {
106116
join!(
107117
receiver.namespace,
108118
CXXBRIDGE,
119+
CXXVERSION,
109120
receiver.cxx,
110121
"operator",
111122
operator,

tests/cxx_gen.rs

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ fn test_extern_c_function() {
1818
let output = str::from_utf8(&generated.implementation).unwrap();
1919
// To avoid continual breakage we won't test every byte.
2020
// Let's look for the major features.
21-
assert!(output.contains("void cxxbridge1$do_cpp_thing(::rust::Str foo)"));
21+
assert!(output.contains(&format!("void {CXXPREFIX}$do_cpp_thing(::rust::Str foo)")));
2222
}
2323

2424
#[test]
@@ -28,9 +28,13 @@ fn test_impl_annotation() {
2828
let source = BRIDGE0.parse().unwrap();
2929
let generated = generate_header_and_cc(source, &opt).unwrap();
3030
let output = str::from_utf8(&generated.implementation).unwrap();
31-
assert!(output.contains("ANNOTATION void cxxbridge1$do_cpp_thing(::rust::Str foo)"));
31+
assert!(output.contains(&format!(
32+
"ANNOTATION void {CXXPREFIX}$do_cpp_thing(::rust::Str foo)"
33+
)));
3234
}
3335

36+
const CXXPREFIX: &'static str = concat!("cxxbridge1$v", env!("CARGO_PKG_VERSION_PATCH"));
37+
3438
const BRIDGE1: &str = r#"
3539
#[cxx::bridge]
3640
mod ffi {
@@ -66,10 +70,13 @@ fn test_extern_rust_method_on_c_type() {
6670
assert!(!header.contains("rust_method_cpp_receiver"));
6771

6872
// Check that there is a generated C signature bridging to the Rust method.
69-
assert!(implementation
70-
.contains("void cxxbridge1$CppType$rust_method_cpp_receiver(::CppType &self) noexcept;"));
73+
assert!(implementation.contains(&format!(
74+
"void {CXXPREFIX}$CppType$rust_method_cpp_receiver(::CppType &self) noexcept;"
75+
)));
7176

7277
// Check that there is an implementation on the C++ class calling the Rust method.
7378
assert!(implementation.contains("void CppType::rust_method_cpp_receiver() noexcept {"));
74-
assert!(implementation.contains("cxxbridge1$CppType$rust_method_cpp_receiver(*this);"));
79+
assert!(implementation.contains(&format!(
80+
"{CXXPREFIX}$CppType$rust_method_cpp_receiver(*this);"
81+
)));
7582
}

0 commit comments

Comments
 (0)