Skip to content

Commit 845f4a0

Browse files
committed
fix: move stored_procs slice under the feature stored_procs_slice
In picodata, we cannot guarantee that tarantool module will be linked exactly once due to possible stale versions from various dependencies. This whole feature is here to disable the distributed slice definition in all but one instance of this crate; otherwise we'll trigger linkme's "duplicate distributed slice" check introduced in 0.3.1.
1 parent 986c3ad commit 845f4a0

File tree

7 files changed

+52
-22
lines changed

7 files changed

+52
-22
lines changed

examples/all_procs/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ license = "BSD-2-Clause"
88

99
[dependencies.tarantool]
1010
path = "../../tarantool"
11+
features = ["stored_procs_slice"]
1112

1213
[lib]
1314
test = false

tarantool-proc/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,3 +20,6 @@ quote = "^1.0"
2020
proc-macro2 = "^1.0"
2121
darling = "0.14.2"
2222
proc-macro-error = "1"
23+
24+
[features]
25+
stored_procs_slice = []

tarantool-proc/src/lib.rs

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1186,9 +1186,20 @@ pub fn stored_proc(attr: TokenStream, item: TokenStream) -> TokenStream {
11861186
public = override_public;
11871187
}
11881188

1189+
// Only add tarantool::proc-annotated function to the distributed slice
1190+
// if the `stored_procs_slice` feature is active. We need this to combat
1191+
// the runtime panics introduced in linkme 0.3.1.
1192+
let attrs_distributed_slice = if cfg!(feature = "stored_procs_slice") {
1193+
quote! {
1194+
#[#linkme::distributed_slice(#section)]
1195+
#[linkme(crate = #linkme)]
1196+
}
1197+
} else {
1198+
quote! {}
1199+
};
1200+
11891201
quote! {
1190-
#[#linkme::distributed_slice(#section)]
1191-
#[linkme(crate = #linkme)]
1202+
#attrs_distributed_slice
11921203
#[cfg(not(test))]
11931204
static #desc_ident: #tarantool::proc::Proc = #tarantool::proc::Proc::new(
11941205
#desc_name,

tarantool/Cargo.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ md-5 = "0.10"
3939
tarantool-proc = { path = "../tarantool-proc", version = "3.1.1" }
4040
uuid = "0.8.2"
4141
futures = "0.3.25"
42-
linkme = "0.3.0"
42+
linkme = "0.3.29"
4343
async-trait = "0.1.64"
4444
tester = { version = "0.7.0", optional = true }
4545
time = ">=0.3.0, <0.3.18"
@@ -78,7 +78,7 @@ internal_test = ["test", "tlua/internal_test", "pretty_assertions", "tempfile"]
7878
# in use at the same time is problematic because libdecnumber versions used by both of the
7979
# options are not exactly the same. Thus deviations in behaviour between them are possible
8080
standalone_decimal = ["dec"]
81-
81+
stored_procs_slice = ["tarantool-proc/stored_procs_slice"]
8282

8383
[dev-dependencies]
8484
time-macros = "=0.2.6"

tarantool/src/lib.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,13 +115,15 @@ pub mod vclock;
115115
/// automatically added to a global array and can be accessed via
116116
/// `proc::all_procs` function.
117117
/// ```no_run
118+
/// # #[cfg(feature = "stored_procs_slice")] {
118119
/// use tarantool::proc::all_procs;
119120
///
120121
/// #[tarantool::proc]
121122
/// fn my_proc() -> i32 { 69 }
122123
///
123124
/// let procs = all_procs();
124125
/// assert_eq!(procs[0].name(), "my_proc");
126+
/// # }
125127
/// ```
126128
///
127129
/// This can be used to generate stored procedure defintions for tarantool's
@@ -154,6 +156,7 @@ pub mod vclock;
154156
/// you want to override it (e.g. your proc is pub, but you want the flag to be
155157
/// false) you can specify the `public` attribute.
156158
/// ```no_run
159+
/// # #[cfg(feature = "stored_procs_slice")] {
157160
/// use tarantool::proc::all_procs;
158161
///
159162
/// #[tarantool::proc]
@@ -174,6 +177,7 @@ pub mod vclock;
174177
/// if proc.name() == "also_public_proc" { assert!( proc.is_public()) }
175178
/// if proc.name() == "also_private_proc" { assert!(!proc.is_public()) }
176179
/// }
180+
/// # }
177181
/// ```
178182
///
179183
/// # Accepting borrowed arguments

tarantool/src/proc.rs

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,6 @@ macro_rules! unwrap_or_report_err {
2424
/// Description of a tarantool stored procedure defined using the
2525
/// `#[`[`tarantool::proc`]`]` macro attribute.
2626
///
27-
/// See also [`all_procs`].
28-
///
2927
/// [`tarantool::proc`]: macro@crate::proc
3028
#[derive(Debug, Clone, PartialEq, Eq)]
3129
pub struct Proc {
@@ -89,21 +87,33 @@ impl Proc {
8987
}
9088
}
9189

92-
// Linkme distributed_slice exports a symbol with the given name, so we must
93-
// make sure the name is unique, so as not to conflict with distributed slices
94-
// from other crates or any other global symbols.
95-
#[doc(hidden)]
96-
#[::linkme::distributed_slice]
97-
pub static TARANTOOL_MODULE_STORED_PROCS: [Proc] = [..];
98-
99-
/// Returns a slice of all stored procedures defined using the
100-
/// `#[`[`tarantool::proc`]`]` macro attribute.
101-
///
102-
/// The order of procs in the slice is undefined.
103-
///
104-
/// [`tarantool::proc`]: macro@crate::proc
105-
pub fn all_procs() -> &'static [Proc] {
106-
&TARANTOOL_MODULE_STORED_PROCS
90+
// In picodata, we cannot guarantee that tarantool module will be linked
91+
// exactly once due to possible stale versions from various dependencies.
92+
// This whole feature is here to disable the distributed slice definition
93+
// in all but one instance of this crate; otherwise we'll trigger linkme's
94+
// "duplicate distributed slice" check introduced in 0.3.1.
95+
#[cfg(feature = "stored_procs_slice")]
96+
pub use stored_procs_slice::*;
97+
#[cfg(feature = "stored_procs_slice")]
98+
mod stored_procs_slice {
99+
use super::*;
100+
101+
// Linkme distributed_slice exports a symbol with the given name, so we must
102+
// make sure the name is unique, so as not to conflict with distributed slices
103+
// from other crates or any other global symbols.
104+
#[doc(hidden)]
105+
#[::linkme::distributed_slice]
106+
pub static TARANTOOL_MODULE_STORED_PROCS: [Proc] = [..];
107+
108+
/// Returns a slice of all stored procedures defined using the
109+
/// `#[`[`tarantool::proc`]`]` macro attribute.
110+
///
111+
/// The order of procs in the slice is undefined.
112+
///
113+
/// [`tarantool::proc`]: macro@crate::proc
114+
pub fn all_procs() -> &'static [Proc] {
115+
&TARANTOOL_MODULE_STORED_PROCS
116+
}
107117
}
108118

109119
////////////////////////////////////////////////////////////////////////////////

tests/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,11 @@ time-macros = "=0.2.6"
3131

3232
[dependencies.tarantool]
3333
path = "../tarantool"
34-
features = ["all", "internal_test"]
34+
features = ["all", "internal_test", "stored_procs_slice"]
3535

3636
[dependencies.tarantool-proc]
3737
path = "../tarantool-proc"
38+
features = ["stored_procs_slice"]
3839

3940
[lib]
4041
test = false

0 commit comments

Comments
 (0)