rodrimati1992 / abi_stable_crates Goto Github PK
View Code? Open in Web Editor NEWRust-to-Rust ffi,ffi-safe equivalents of std types,and creating libraries loaded at startup.
License: Apache License 2.0
Rust-to-Rust ffi,ffi-safe equivalents of std types,and creating libraries loaded at startup.
License: Apache License 2.0
The documentation at https://doc.rust-lang.org/nightly/std/boxed/index.html#memory-layout says
So long as T: Sized, a Box is guaranteed to be represented as a single pointer and is also ABI-compatible with C pointers
So it can be implemented for some cases.
Right now 0.4 doesn't have online documentation in 'docs.rs' because of a bug in a markdown parser that hasn't been fixed in nightly.
If someone has a sugestion for how to fix this please comment on this issue.
First of all, thank you for your significant contribution to have a stable rust ABI. I found almost everything I needed except for working with futures. There is however another crate named asyncFfi, which provides #[repr(C)]
alternative to future-structs.
I tried to have a NewType MyFuture(async_ffi::FfiFuture)
which manually implements StableAbi, but I struggled to implement LAYOUT for it and I don't know if this is even possible. This leads to the following questions:
#[repr(C)]
structs?I'm in the process of writing various async primitives with a stable ABI and I would need the equivalent of parking_lot::RawMutex & parking_lot::RawRwLock.
I see that what I would need would basically be those two internal types:
abi_stable_crates/abi_stable/src/external_types/parking_lot/mutex.rs
Lines 30 to 31 in 510725a
However there is no (easy) way for me to replicate these types since UnsafeOveralignedField
is private.
Would you accept a PR if I turn these into fully fledged types with repr(C)
and expose them publicly? It would implement lock_api::RawMutex
.
As a side question, why are these fields overaligned over usize? Is it because we don't know the real size of the type ahead of time, but since it is a mutex we know that its size will never exceed a atomic usize?
I'm a bit new to rust, so maybe this isn't a great beginner project, but the examples don't compile, and they're a little complicated to understand, maybe some less-generic examples using "new" cargo workspaces would help.
I'm following working_with_abi_stable source which seems to compile and I mostly understand it.
I'm trying to expand my own project which interfaces with OSC to send and receive messages, and I want to send the received messages to all loaded plugins and allow plugins to send messages to the core application which will send them off via OSC.
This example tries to load libmin.so
but each plugin would be under a different name such as libspotify.so
or liblogger.so
for example, how would I load multiple plugins that have the exact same interface? The example interface being MinMod
and MinMod_Ref
I want to define a struct both serializable by rkyv and ffi safe by abi_stable
Is there a way to share thread-local variables?
I'm trying to build a plugin system for swc ( https://swc.rs ) using abi_stable.
I want to provide exactly same api for plugin as core transforms, but core transforms use thread locals.
There are two important thread locals and both of them lives in swc_common
.
I searched for thread local but failed to find one and thanks for a great library!
This would be really useful for implementing async primitives since they often hold wakers. Unsure if its actually possible though.
See #75 for an explanation as to why this issue needs to be resolved.
Here's an exhaustive list of the variance in std_types
:
BorrowOwned
should be removed (see #80)buffer: *mut T
should be changed to Unique<T>
vtable: VecVTable_Ref<T>
should be made opaquemap: RBox<ErasedMap<K, V, S>>
requires fixing RBox<T>
firstvtable: VTable_Ref<K, V, S>
should be made opaquedata: *mut T
should be changed to Unique<T>
vtable: BoxVtable_Ref<T>
should be made opaquevtable: ArcVtable_Ref<T>
should be made opaqueRBoxError_
, RIoError
, RIoErrorKind
, RString
, UTypeId
, RDuration
, RCmpOrdering
, RSeekFrom
: no generic parametersRSliceMut
: should be left as invariantRStr
, RSlice
, Tuple{1..4}
, ROption
, RResult
: already covariantAbout *mut T
:
Unique<T>
can work fine with NonNull<T>
as well. However, NonNull<T>
has weaker semantics than Unique<T>
, and we can actually guarantee that the pointer is owned by that struct.About the vtables:
mem::transmute
over the vtable itself, rather than over each individual function it has.ErasedType
instead of *const ()
for the opaque types, right?transmute
?Others:
unsafe
is documented properly.@rodrimati1992, we can split up the work however you like, and if you have any advice, please let me know. Specially regarding how to fix the vtables properly, which I'm not quite sure how to do best.
Hey there, I'm attempting to integrate your (awesome) layout checking with CGlue. It seems like core::ffi::c_void
does not have StableAbi
implemented, though, which causes some problems. I currently have it hackfixed by borrowing the ()
implementation, but it would be really cool to have it upstream. I can go ahead and submit a PR if you'd like, but am not exactly certain which fields need to be customized apart from name and module strings.
Hi, i'm trying to implement sdk for my plugin system. In an application side i'm define a function:
#[sabi_extern_fn]
pub fn info_version() -> RString {
VersionInfo::current().to_string().into()
}
In a plugin side i'm trying to use it like:
extern "C" {
fn info_version() -> RString;
}
There is warnings when compiling with rustc 1.78.0
:
warning: `extern` block uses type `NotCopyNotClone`, which is not FFI-safe
--> sdk/info.rs:4:26
|
4 | fn info_version() -> RString;
| ^^^^^^^ not FFI-safe
|
= help: consider adding a member to this struct
= note: this struct has no fields
= note: `#[warn(improper_ctypes)]` on by default
Dear,
Thanks for your works,
I am trying to understand how this crate works, thus I have some questions:
.so
file is loaded ?load_from_directory
function used into the example interface line 54 , what do this function. Does it try to load any .so
file from given directory ?Below my actual and fuzzy understanding
sequenceDiagram
participant App
participant MyPluginInterface
participant MyPlugin
participant RootModule as abi_stable::library::RootModule
App ->> MyPluginInterface : use specialized defined API
MyPluginInterface ->> MyPlugin : call load_from_directory
MyPlugin ->> RootModule : call load_from_directory
RootModule -> MysharedLib : load .so file
I would like to achieve something like:
An App which define various interfaces to let other dev extend the app via various plugins
So, the App do not know implementations (i.e the plugins) but know that plugins are all located into my/plugin/dir
The App loop over plugin into my/plugin/dir
and load them
What it is blocking while reading example ?
In readme_example The readme_user app use readme_interface
which implement RootModule
To my understanding at this step the interface define the plugin name that would mean into one directory only one plugin using this interface is possible, no ?
Edit: for the last part I think I understood, I should not create 1 interface by plugin but 1 interface for all kind of plugin and use the same way describe into 1_trait_objects
Thanks for your insight
When attempting to build for some PowerPC 32 bit platforms, I am running into issues with abi_stable/src/abi_stability/stable_abi_trait.rs lines 1198 and 1202 attempting to use 64-bit atomic types.
I think this is easily addressed once Rust compilers support target_has_atomic
, but that appears to be a month or two away. Below is a patch I am temporarily using. I am hoping abi_stable will be able to address this soon, possibly shortly after stabilization of target_has_atomic
.
--- a/vendor/abi_stable_crates/abi_stable/src/abi_stability/stable_abi_trait.rs
+++ b/vendor/abi_stable_crates/abi_stable/src/abi_stability/stable_abi_trait.rs
@@ -1195,10 +1195,31 @@ mod rust_1_34_impls {
(AtomicI8 ,"AtomicI8" ,i8,"std::sync::atomic"),
(AtomicI16,"AtomicI16",i16,"std::sync::atomic"),
(AtomicI32,"AtomicI32",i32,"std::sync::atomic"),
- (AtomicI64,"AtomicI64",i64,"std::sync::atomic"),
(AtomicU8 ,"AtomicU8" ,u8,"std::sync::atomic"),
(AtomicU16,"AtomicU16",u16,"std::sync::atomic"),
(AtomicU32,"AtomicU32",u32,"std::sync::atomic"),
+ ]
+ }
+
+ // This is similar to serde's build.rs, but uses target_arch.
+ // We don't use starts.with() because this isn't build.rs .
+ // We would prefer to use #[cfg(target_has_atomic = "64")], but
+ // that's not yet stable. (Perhaps with rustc v1.64.0.)
+ //
+ // See: https://docs.rs/platforms/latest/platforms/enum.Arch.html
+ // and https://github.com/serde-rs/serde/blob/master/serde/build.rs#L94-L103
+ #[cfg(any(
+ target_arch = "aarch64",
+ target_arch = "mips64",
+ target_arch = "powerpc64",
+ target_arch = "riscv64",
+ target_arch = "sparc64",
+ target_arch = "x86_64"
+ ))]
+ impl_for_concrete! {
+ type IsNonZeroType=False;
+ [
+ (AtomicI64,"AtomicI64",i64,"std::sync::atomic"),
(AtomicU64,"AtomicU64",u64,"std::sync::atomic"),
]
}
(I am also having a similar issue with crossbeam, but I am able to workaround that by removing the "channels" feature.)
We are planning an eventual implementation of the Pipeline IDE graph execution for Rust. (Now it is only for Solidity and JS.) Your work here could be helpful, but I do not know Rust enough to know clearly how to use abi_stable_crates and to interface it into our work.
I can envision this as the ability to weave new functions and dylibs by using funcs already deployed in dylibs. All without writing a line of code: just visually editing the graph. Interesting and doable?
https://www.youtube.com/watch?v=-LHvdZZUrss
https://github.com/pipeos-one/pipeline
Any guidance is appreciated.
After upgrading my rustc
to rustc 1.65.0-nightly (2befdefdd 2022-08-06)
, following warning appeared and I think it should be fixed.
|
60 | #[abi_stable::sabi_trait]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= note: `#[warn(repr_transparent_external_private_fields)]` on by default
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #78586 <https://github.com/rust-lang/rust/issues/78586>
= note: this struct contains `UnsafeIgnoredType<SyncSend>`, which contains private fields, and makes it not a breaking change to become non-zero-sized in the future.
= note: this warning originates in the attribute macro `abi_stable::sabi_trait` (in Nightly builds, run with -Z macro-backtrace for more info)
There are plans to change the rules for implicit promotion such that calls to const fn
are not implicitly promoted to 'static
lifetime any more. A crater experiment showed that only very few crates would be affected by this change, and this is one of them.
You can see an example of the relevant build failure here. Usually there is a way to work around this by explicitly putting the intermediate result into a const
, of which a reference is then taken. However, since this is macro-generated code, I was unable to find the right spot(s) in the code where this would have to be done.
I tried using RawMessageHook_TO<'static, abi_stable::std_types::RArc<()>>
where RawMessageHook_TO
is a sabi_trait
. But when I try to clone it, I can't!
The reason appears to be because impl<T> GetPointerKind for RArc<T>
specifies it as PK_SmartPointer
which only implements clone if the value type implements clone, but that is counter-productive to RArc
!
Is there some way I can access the RArc
to clone it? (unsafe
is fine)
I've noticed that there's an implementation of StableAbi
for most basic types, such as i32
, u64
, etc with the impl_for_primitive_ints
macro. However, f64
isn't in that list, and neither is f32
. In fact, f64
isn't mentioned once in the whole repository.
If it helps, their size is always known as per the reference: https://doc.rust-lang.org/stable/reference/type-layout.html#primitive-data-layout. But it's true that they don't have a known representation: https://doc.rust-lang.org/stable/reference/type-layout.html#primitive-representations.
I'm guessing I have to use std::os::raw::c_double
and std::os::raw::c_float
instead of f64
, but is there any way to make this easier to use? It seems to just be an alias to Rust's type (https://doc.rust-lang.org/std/os/raw/type.c_float.html), but I'm not sure if there are any guarantees.
Thanks!
This project needs a map type of some sort,and I can see some possibilities to how it could be implemented:
Just wrap the regular standard map types,using type erasure and passing them to a vtable to call any method that uses Hash (for the hash implementation has to be consistent,it has to be a dyamically dispatched function).
Implement a map type from scratch.
Port the standard library one,replacing every internal type with #[repr(C)]
and adding #[derive(StableAbi)]
.
Hi,
sorry for the bad title, I'm not sure how to phrase the issue in a concise one-line description.
It seems that something inside abi_stables R*
types breaks rusts lifetime tracking. We (@marioortizmanero and the rest of the tremor team) went through the attempt of using them for internal data as part of his PDK project and got to the point where a lot of lifetime errors (the nasty kind) were thrown up.
Initially, we suspected that we had done something wrong in the interpreter using the data so we tried to find the underlying cause and boiled it down to (hopefully) one initial issue that doesn't require to go through 1000s of lines of code :)
Basically, the following code
use abi_stable::std_types::RCow;
use std::borrow::Cow;
fn cmp_cow<'a, 'b>(left: &Cow<'a, ()>, right: &Cow<'b, ()>) -> bool {
left == right
}
fn cmp_rcow<'a, 'b>(left: &RCow<'a, ()>, right: &RCow<'b, ()>) -> bool {
left == right
}
fn main() {
println!("Hello, world!");
}
fails with the following error:
Checking repro v0.1.0 (/home/heinz/mario/repro)
error[E0623]: lifetime mismatch
--> src/main.rs:9:10
|
8 | fn cmp_rcow<'a, 'b>(left: &RCow<'a, ()>, right: &RCow<'b, ()>) -> bool {
| ------------ ------------
| |
| these two types are declared with different lifetimes...
9 | left == right
| ^^ ...but data from `left` flows into `right` here
For more information about this error, try `rustc --explain E0623`.
error: could not compile `repro` due to previous error
We could reproduce the same for RVec, and RHashMap as long they contained a lifetime.
Below a more extensive test with a number of other types:
use abi_stable::std_types::{RCow, RHashMap, RSlice, RStr, RString, RVec, Tuple2};
use std::{borrow::Cow, collections::HashMap};
fn cmp_string<'a, 'b>(left: &String, right: &String) -> bool {
left == right
}
fn cmp_rstring<'a, 'b>(left: &RString, right: &RString) -> bool {
left == right
}
fn cmp_str<'a, 'b>(left: &'a str, right: &'b str) -> bool {
left == right
}
fn cmp_rstr<'a, 'b>(left: &RStr<'a>, right: &RStr<'b>) -> bool {
left == right
}
fn cmp_vec<'a, 'b>(left: &Vec<&'a str>, right: &Vec<&'b str>) -> bool {
left == right
}
fn cmp_rvec<'a, 'b>(left: &RVec<&'a str>, right: &RVec<&'b str>) -> bool {
left == right
}
fn cmp_tpl<'a, 'b>(left: &(&'a str, u8), right: &(&'b str, u8)) -> bool {
left == right
}
fn cmp_rtpl<'a, 'b>(left: &Tuple2<&'a str, u8>, right: &Tuple2<&'b str, u8>) -> bool {
left == right
}
fn cmp_slice<'a, 'b>(left: &[&'a str], right: &[&'b str]) -> bool {
left == right
}
fn cmp_rslice<'a, 'b>(left: &RSlice<&'a str>, right: &RSlice<&'b str>) -> bool {
left == right
}
fn cmp_cow<'a, 'b>(left: &Cow<'a, ()>, right: &Cow<'b, ()>) -> bool {
left == right
}
fn cmp_rcow<'a, 'b>(left: &RCow<'a, ()>, right: &RCow<'b, ()>) -> bool {
left == right
}
fn cmp_hashmap<'a, 'b>(left: &HashMap<&'a str, ()>, right: &HashMap<&'a str, ()>) -> bool {
left == right
}
fn cmp_rhashmap<'a, 'b>(left: &RHashMap<u8, &'a str>, right: &RHashMap<u8, &'b str>) -> bool {
left == right
}
fn main() {
println!("Hello, world!");
}
Maybe it's not an intended usage, but I'm curious if you have a plan to support mutating fields of Prefix types.
It's required to preserve compatibility of rust-based swc plguins.
This is a known issue,and is caused by a bug in rustdoc.
doc.rs issue where I mention the build failure: rust-lang/docs.rs#506 (comment)
A Rust issue that seems to be the same error: rust-lang/rust#67006
If I have a String
and want to create an Arc
from it, there's not really a reason to create a new allocation, since String
already has its data allocated on the heap.
For this use case, std
has String::into_boxed_str
and From<Box<T>> for Arc<T>
. It would be nice if something similar would exist in abi_stable
since it's a bit wasteful to create a pointer to a pointer on the heap to data on the heap.
Hello, we (Rust group @sslab-gatech) found a memory-safety/soundness issue in this crate while scanning Rust code on crates.io for potential vulnerabilities.
abi_stable_crates/abi_stable/src/std_types/vec/iters.rs
Lines 292 to 320 in 2bff3b3
abi_stable_crates/abi_stable/src/std_types/string.rs
Lines 636 to 670 in 2bff3b3
These two implementations are copy-pasted from Rust's standard library, and unfortunately it turns out that std implementations were containing soundness bugs (rust-lang/rust#60977 and rust-lang/rust#78498, respectively). Could you check them and update the respective part of this crate?
I haven't added any examples to std_type types since most of them are identical to the std library ones.
If anyone wants to add examples,it should be easy enough to do for functions/methods that are identical to std library ones.
If you want to add examples please comment here before you do so.
Hey there, it seems like 0.10
build is broken on older versions of Rust. The issue stems from several const fns in nul_str.rs that do branching. 0.9 works fine. Seems like travis-ci does not do any builds.
Would it be possible to support std::rc::Rc
? (Since std::sync::Arc
is already supported)
I noticed a possible panics due to inconsistency between documentation and code implementation in abi_stable/src/type_layout/tl_functions.rs. The details can be found in the following code. The code does not check whether nth is out of bounds before using [nth].
/// # Panics
///
/// This function panics if `nth` is out of bounds
/// (when `nth` is greater than or equal to `self.len()`)
pub fn index(&'static self, nth: usize, shared_vars: &'static SharedVars) -> TLFunction {
self.functions()[nth].expand(shared_vars)
}
Unless I'm missing something, isn't it the case that RBox
should have IsNonZeroType
as True
rather than False
?
Hey there, using abi_stable I've noticed significant size requirements for performing layout checks. It appears to stem from indirection caused by accessing type IDs and layouts within TypeLayout
and SharedVars
through ctors. This leads to explosion of tiny functions bloating the binary/library size. If I am not mistaken, this was done due to self-referential structures and it being impossible for the compiler to deal with.
I tinkered a little bit, trying to see if one could come up with a way to support self-referential structures while staying completely in compile-time, and here is a little PoC:
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1e622b3aea8aa4437a25cae2646de820
The trick here is to have 2 type IDs, one that evaluates IDs within its type, and the other "shallow" one that skips the contents of the type. This way everything is evaluated until the last type, however, this still does not solve the self-referential cycles. The latter is solved by providing special implementations for all 4 types of indirection available in rust (mut/const references and pointers) that use only the shallow type ID. This works, because T: StableAbi
implies &T: StableAbi
. The example works with generating unique Type IDs, however, I think it would similarly be able to be extended over to TypeLayout
s as well. Finally, it may even be possible to reduce a lot of type checking into a single stable hash value.
The question is, would the implementation of this be in your interest? I believe this would lead to positive impact to all abi_stable users and am willing to implement it, however, it would be great to do it in cooperation, as I do not want to miss out on key details regarding prefix types, reflection, etc.
Perhaps I've missed an important part of the documentation, but it seems to me that using this crate with other crates that use std types in public api involves a lot of copying.
For example if I have a crate that manipulates Vec-s from the standard library and I then want to make those Vec-s accessible over ABI then I have no option other than to make a copy to RVec, which could be really bad for performance if the Vec-s are large.
Is this assessment accurate? Are the tradeoffs and recommendations for these kinds of situations documented somewhere? If not it would be useful if they were.
Hello,
Would it be possible to work on generating C bindings for this crate? Considering this is used for plugin systems, it could be handy to have a C header available for compatibility with other programming languages, as an extra for having a stable ABI.
I've tried using cbindgen
:
/tmp/abi_stable_crates/abi_stable master
❯ cbindgen --lang=C .
WARN: Skip abi_stable::LIB_HEADER - (not `no_mangle`).
WARN: Skip abi_stable::ABI_STABLE_VERSION - (Unsupported expression. Macro(ExprMacro { attrs: [], mac: Macro { path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(package_version_strings), arguments: None }] }, bang_token: Bang, delimiter: Paren(Paren), tokens: TokenStream [] } }))
WARN: Skip abi_stable::EXECUTABLE_IDENTITY - (not `pub`).
WARN: Skip abi_stable::EXECUTABLE_IDENTITY - (not `no_mangle`).
WARN: Skipping abi_stable::get_type_name - (not `no_mangle`, and has no `export_name` attribute)
WARN: Skip abi_stable::EMPTY - (not `pub`).
WARN: Skip abi_stable::BASE_NAME - (not `pub`).
WARN: Skipping abi_stable::check_layout_compatibility_for_ffi - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::exported_check_layout_compatibility - (not `no_mangle`, and has no `export_name` attribute)
WARN: Skip abi_stable::CHECKING_GLOBALS - (not `pub`).
WARN: Skip abi_stable::CHECKING_GLOBALS - (not `no_mangle`).
WARN: Skip abi_stable::_VTABLE_STATIC - (not `pub`).
WARN: Skipping abi_stable::get_type_layout - (not `no_mangle`, and has no `export_name` attribute)
WARN: Skipping abi_stable::get_prefix_field_type_layout - (not `no_mangle`, and has no `export_name` attribute)
WARN: Skip abi_stable::UNSAFE_EXTERN_FN_LAYOUT - (Unsupported path expression. [PathSegment { ident: Ident(GetTypeLayoutCtor), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: Some(Colon2), lt_token: Lt, args: [Type(BareFn(TypeBareFn { lifetimes: None, unsafety: Some(Unsafe), abi: Some(Abi { extern_token: Extern, name: Some(LitStr { token: "C" }) }), fn_token: Fn, paren_token: Paren, inputs: [], variadic: None, output: Default }))], gt_token: Gt }) }, Colon2, PathSegment { ident: Ident(STABLE_ABI), arguments: None }])
WARN: Skip abi_stable::EXTERN_FN_LAYOUT - (Unsupported path expression. [PathSegment { ident: Ident(GetTypeLayoutCtor), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: Some(Colon2), lt_token: Lt, args: [Type(BareFn(TypeBareFn { lifetimes: None, unsafety: None, abi: Some(Abi { extern_token: Extern, name: Some(LitStr { token: "C" }) }), fn_token: Fn, paren_token: Paren, inputs: [], variadic: None, output: Default }))], gt_token: Gt }) }, Colon2, PathSegment { ident: Ident(STABLE_ABI), arguments: None }])
WARN: Skip abi_stable::STABLE_ABI - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Constructor), arguments: None }] } }), paren_token: Paren, args: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(get_type_layout), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: Some(Colon2), lt_token: Lt, args: [Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(T), arguments: None }] } }))], gt_token: Gt }) }] } }), Comma] }))
WARN: Skip abi_stable::SABI_OPAQUE_FIELD - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Constructor), arguments: None }] } }), paren_token: Paren, args: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(get_type_layout), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: Some(Colon2), lt_token: Lt, args: [Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(UnsafeOpaqueField), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: None, lt_token: Lt, args: [Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(T), arguments: None }] } }))], gt_token: Gt }) }] } }))], gt_token: Gt }) }] } }), Comma] }))
WARN: Skip abi_stable::PREFIX_STABLE_ABI - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Constructor), arguments: None }] } }), paren_token: Paren, args: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(get_prefix_field_type_layout), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: Some(Colon2), lt_token: Lt, args: [Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(T), arguments: None }] } }))], gt_token: Gt }) }] } }), Comma] }))
WARN: Skip abi_stable::OPAQUE_FIELD - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Constructor), arguments: None }] } }), paren_token: Paren, args: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(get_type_layout), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: Some(Colon2), lt_token: Lt, args: [Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(UnsafeOpaqueField), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: None, lt_token: Lt, args: [Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(T), arguments: None }] } }))], gt_token: Gt }) }] } }))], gt_token: Gt }) }] } }), Comma] }))
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Couldn't find path for FuncPtr { ret: Primitive(Void), args: [], is_nullable: false }, skipping associated constants
WARN: Couldn't find path for FuncPtr { ret: Primitive(Void), args: [], is_nullable: false }, skipping associated constants
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skipping abi_stable::drop_pointer_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::clone_pointer_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::default_pointer_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::display_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::debug_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::serialize_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::partial_eq_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::cmp_ord - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::partial_cmp_ord - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::hash_Hash - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::hash_slice_Hasher - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::finish_Hasher - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::write_str_fmt_write - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::io_Write_write - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::io_Write_write_all - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::io_Write_flush - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::io_Read_read - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::io_Read_read_exact - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::io_BufRead_fill_buf - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::io_BufRead_consume - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::io_Seek_seek - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::NEW - (not `pub`).
WARN: Skip abi_stable::NEW - (not `pub`).
WARN: Skip abi_stable::NEW - (not `pub`).
WARN: Skip abi_stable::NEW - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Self), arguments: None }] } }), paren_token: Paren, args: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(PhantomData), arguments: None }] } })] }))
WARN: Skip abi_stable::NEW - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Self), arguments: None }] } }), paren_token: Paren, args: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(PhantomData), arguments: None }] } })] }))
WARN: Skipping abi_stable::next - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::extending_rvec - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::size_hint - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::count - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::last - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::nth - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::skip_eager - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::next_back - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::extending_rvec_back - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::nth_back - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::ITER - (not `pub`).
WARN: Skip abi_stable::ITER - (not `pub`).
WARN: Skip abi_stable::JSON_0 - (Unsupported literal expression. Str(LitStr { token: r#"
{
"l":1000,
"r":10,
"name":"what the hell"
}
"# }))
WARN: Skip abi_stable::INFO - (not `pub`).
WARN: Skip abi_stable::INFO - (not `pub`).
WARN: Skip abi_stable::GET - (Unsupported path expression. [PathSegment { ident: Ident(GetVtable), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: None, lt_token: Lt, args: [Lifetime(Lifetime { apostrophe: Span, ident: Ident(borr) }), Comma, Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(T), arguments: None }] } })), Comma, Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ErasedPtr), arguments: None }] } })), Comma, Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(OrigPtr), arguments: None }] } })), Comma, Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(I), arguments: None }] } }))], gt_token: Gt }) }, Colon2, PathSegment { ident: Ident(_GET_INNER_VTABLE), arguments: None }])
WARN: Skip abi_stable::INFO - (not `pub`).
WARN: Skip abi_stable::VALUE - (not `pub`).
WARN: Skip abi_stable::MS - (not `pub`).
WARN: Skip abi_stable::RAW_LOCK_SIZE - (not `pub`).
WARN: Skip abi_stable::OM_PADDING - (not `pub`).
WARN: Skip abi_stable::OPAQUE_ONCE - (not `pub`).
WARN: Skipping abi_stable::state - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::call_once - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::call_once_force - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::NEW - (Unsupported path expression. [PathSegment { ident: Ident(VTable), arguments: None }, Colon2, PathSegment { ident: Ident(VTABLE), arguments: None }])
WARN: Skip abi_stable::VTABLE - (not `pub`).
WARN: Skip abi_stable::OM_PADDING - (not `pub`).
WARN: Skip abi_stable::OPAQUE_MUTEX - (not `pub`).
WARN: Skipping abi_stable::lock - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::try_lock - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::unlock - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::try_lock_for - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::_TMP0 - (not `pub`).
WARN: Skip abi_stable::ITERS - (not `pub`).
WARN: Skip abi_stable::ITERS - (not `pub`).
WARN: Skip abi_stable::OM_PADDING - (not `pub`).
WARN: Skip abi_stable::OPAQUE_LOCK - (not `pub`).
WARN: Skipping abi_stable::lock_shared - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::try_lock_shared - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::try_lock_shared_for - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::unlock_shared - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::lock_exclusive - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::try_lock_exclusive - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::try_lock_exclusive_for - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::unlock_exclusive - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::_TMP0 - (not `pub`).
WARN: Skip abi_stable::EXPECTED - (not `pub`).
WARN: Skip abi_stable::C_ABI_TESTING_FNS - (Unsupported expression. Reference(ExprReference { attrs: [], and_token: And, raw: Reserved, mutability: None, expr: Struct(ExprStruct { attrs: [], path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(CAbiTestingFns), arguments: None }] }, brace_token: Brace, fields: [FieldValue { attrs: [], member: Named(Ident(take_pair_a)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(take_pair_a), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(take_pair_b)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(take_pair_b), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(ret_pair_a)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ret_pair_a), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(ret_pair_b)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ret_pair_b), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(take_triple_a)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(take_triple_a), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(take_triple_b)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(take_triple_b), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(take_triple_c)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(take_triple_c), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(ret_triple_a)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ret_triple_a), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(ret_triple_b)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ret_triple_b), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(ret_triple_c)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ret_triple_c), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(take_2_pairs_a)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(take_2_pairs_a), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(take_2_pairs_b)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(take_2_pairs_b), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(ret_2_pairs_a)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ret_2_pairs_a), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(ret_2_pairs_b)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ret_2_pairs_b), arguments: None }] } }) }, Comma, FieldValue { attrs: [], member: Named(Ident(mixed_units)), colon_token: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(mixed_units), arguments: None }] } }) }, Comma], dot2_token: None, rest: None }) }))
WARN: Skipping abi_stable::take_pair_a - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::take_pair_b - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::ret_pair_a - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::ret_pair_b - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::take_triple_a - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::take_triple_b - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::take_triple_c - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::ret_triple_a - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::ret_triple_b - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::ret_triple_c - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::take_2_pairs_a - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::take_2_pairs_b - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::ret_2_pairs_a - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::ret_2_pairs_b - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::mixed_units - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::INIT_GLOBALS_WITH - (not `pub`).
WARN: Skip abi_stable::ABORTING_CONSTRUCTOR - (not `pub`).
WARN: Skip abi_stable::VALUE - (Unsupported expression. Block(ExprBlock { attrs: [], label: None, block: Block { brace_token: Brace, stmts: [Item(Mod(ItemMod { attrs: [], vis: Inherited, mod_token: Mod, ident: Ident(value), content: Some((Brace, [Use(ItemUse { attrs: [], vis: Inherited, use_token: Use, leading_colon: None, tree: Path(UsePath { ident: Ident(super), colon2_token: Colon2, tree: Glob(UseGlob { star_token: Star }) }), semi_token: Semi }), Macro(ItemMacro { attrs: [], ident: None, mac: Macro { path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(abi_stable_derive), arguments: None }, Colon2, PathSegment { ident: Ident(construct_abi_header), arguments: None }] }, bang_token: Bang, delimiter: Brace(Brace), tokens: TokenStream [] }, semi_token: None })])), semi: None })), Expr(Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(value), arguments: None }, Colon2, PathSegment { ident: Ident(ABI_HEADER), arguments: None }] } }))] } }))
WARN: Skip abi_stable::NEW - (Unsupported path expression. [PathSegment { ident: Ident(UnsafeIgnoredType), arguments: None }, Colon2, PathSegment { ident: Ident(NEW), arguments: None }])
WARN: Skip abi_stable::NEW - (Unsupported path expression. [PathSegment { ident: Ident(UnsafeIgnoredType), arguments: None }, Colon2, PathSegment { ident: Ident(NEW), arguments: None }])
WARN: Skip abi_stable::NEW - (Unsupported path expression. [PathSegment { ident: Ident(UnsyncUnsend), arguments: None }, Colon2, PathSegment { ident: Ident(NEW), arguments: None }])
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::DEFAULT - (Unsupported expression. Array(ExprArray { attrs: [], bracket_token: Bracket, elems: [] }))
WARN: Skip abi_stable::NEW - (Unsupported expression. Array(ExprArray { attrs: [], bracket_token: Bracket, elems: [] }))
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::DEFAULT - (Unsupported expression. Array(ExprArray { attrs: [], bracket_token: Bracket, elems: [] }))
WARN: Skip abi_stable::NEW - (Unsupported expression. Array(ExprArray { attrs: [], bracket_token: Bracket, elems: [] }))
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::VTABLE_VAL - (not `pub`).
WARN: Skipping abi_stable::drop_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::clone_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::partial_eq_impl - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::cmp_ord - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::partial_cmp_ord - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::serialize_impl - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::VALUE - (not `pub`).
WARN: Skip abi_stable::VALUE - (not `pub`).
WARN: Skip abi_stable::VALUE - (not `pub`).
WARN: Skip abi_stable::NEW - (Unsupported path expression. [PathSegment { ident: Ident(PrefixTypeTrait), arguments: None }, Colon2, PathSegment { ident: Ident(METADATA), arguments: None }])
WARN: Skip abi_stable::NAME - (not `pub`).
WARN: Skip abi_stable::NAME - (not `pub`).
WARN: Skip abi_stable::LAYOUT - (not `pub`).
WARN: Skip abi_stable::EMPTY - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Self), arguments: None }, Colon2, PathSegment { ident: Ident(new), arguments: None }] } }), paren_token: Paren, args: [Lit(ExprLit { attrs: [], lit: Int(LitInt { token: 0 }) }), Comma, Lit(ExprLit { attrs: [], lit: Int(LitInt { token: 0 }) })] }))
WARN: Skip abi_stable::None - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(OptionU16), arguments: None }] } }), paren_token: Paren, args: [Unary(ExprUnary { attrs: [], op: Not(Bang), expr: Lit(ExprLit { attrs: [], lit: Int(LitInt { token: 0 }) }) })] }))
WARN: Skip abi_stable::MAX_VAL - (not `pub`).
WARN: Skip abi_stable::None - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(OptionU8), arguments: None }] } }), paren_token: Paren, args: [Unary(ExprUnary { attrs: [], op: Not(Bang), expr: Lit(ExprLit { attrs: [], lit: Int(LitInt { token: 0 }) }) })] }))
WARN: Skip abi_stable::MAX_VAL - (not `pub`).
WARN: Skip abi_stable::GET_ERR - (not `pub`).
WARN: Skip abi_stable::RECURSIVE_INDICATOR - (not `pub`).
WARN: Skip abi_stable::NULL - (Unsupported expression. Reference(ExprReference { attrs: [], and_token: And, raw: Reserved, mutability: None, expr: Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Tag), arguments: None }, Colon2, PathSegment { ident: Ident(null), arguments: None }] } }), paren_token: Paren, args: [] }) }))
WARN: Skip abi_stable::TAG_SET_EMPTY - (not `pub`).
WARN: Skip abi_stable::TAG_ARR_EMPTY - (not `pub`).
WARN: Skip abi_stable::TAG_SET_0 - (not `pub`).
WARN: Skip abi_stable::TAG_ARR_0 - (not `pub`).
WARN: Skip abi_stable::TAG_1_ORDER_0_VALUE - (not `pub`).
WARN: Skip abi_stable::TAG_SET_1_ORDER_0 - (not `pub`).
WARN: Skip abi_stable::TAG_ARR_1_ORDER_0 - (not `pub`).
WARN: Skip abi_stable::TAG_1_ORDER_1_VALUE - (not `pub`).
WARN: Skip abi_stable::TAG_SET_1_ORDER_1 - (not `pub`).
WARN: Skip abi_stable::TAG_ARR_1_ORDER_1 - (not `pub`).
WARN: Skip abi_stable::TAG_2_VALUE - (not `pub`).
WARN: Skip abi_stable::TAG_SET_2 - (not `pub`).
WARN: Skip abi_stable::TAG_ARR_2 - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_EMPTY - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_0A - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_0B - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_0E - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_0F - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_0G - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_1A - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_1B - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_2A - (not `pub`).
WARN: Skip abi_stable::TAG_MAP_2B - (not `pub`).
WARN: Skip abi_stable::TAG_BOOLS - (not `pub`).
WARN: Skip abi_stable::TAG_UINTS - (not `pub`).
WARN: Skip abi_stable::TAG_INTS - (not `pub`).
WARN: Skip abi_stable::TAG_STRS - (not `pub`).
WARN: Skip abi_stable::EMPTY - (Unsupported path expression. [PathSegment { ident: Ident(CompTLFields), arguments: None }, Colon2, PathSegment { ident: Ident(EMPTY), arguments: None }])
WARN: Skip abi_stable::VARIANT_INDEX - (not `pub`).
WARN: Skip abi_stable::VARIANT_INDEX - (not `no_mangle`).
WARN: Skip abi_stable::NEW - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(TLNonExhaustive), arguments: None }, Colon2, PathSegment { ident: Ident(new), arguments: AngleBracketed(AngleBracketedGenericArguments { colon2_token: Some(Colon2), lt_token: Lt, args: [Type(Path(TypePath { qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(T), arguments: None }] } }))], gt_token: Gt }) }] } }), paren_token: Paren, args: [] }))
WARN: Skip abi_stable::EMPTY - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Self), arguments: None }, Colon2, PathSegment { ident: Ident(from_fields), arguments: None }] } }), paren_token: Paren, args: [Macro(ExprMacro { attrs: [], mac: Macro { path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(rslice), arguments: None }] }, bang_token: Bang, delimiter: Bracket(Bracket), tokens: TokenStream [] } })] }))
WARN: Skip abi_stable::PARAM_INDEX - (not `pub`).
WARN: Skip abi_stable::PARAM_INDEX - (not `no_mangle`).
WARN: Skip abi_stable::EMPTY - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(LifetimeArrayOrSlice), arguments: None }, Colon2, PathSegment { ident: Ident(Array), arguments: None }] } }), paren_token: Paren, args: [Struct(ExprStruct { attrs: [], path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ArrayLen), arguments: None }] }, brace_token: Brace, fields: [FieldValue { attrs: [], member: Named(Ident(len)), colon_token: Some(Colon), expr: Lit(ExprLit { attrs: [], lit: Int(LitInt { token: 0 }) }) }, Comma, FieldValue { attrs: [], member: Named(Ident(array)), colon_token: Some(Colon), expr: Array(ExprArray { attrs: [], bracket_token: Bracket, elems: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(LifetimeIndexPair), arguments: None }, Colon2, PathSegment { ident: Ident(NONE), arguments: None }] } }), Comma, Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(LifetimeIndexPair), arguments: None }, Colon2, PathSegment { ident: Ident(NONE), arguments: None }] } }), Comma, Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(LifetimeIndexPair), arguments: None }, Colon2, PathSegment { ident: Ident(NONE), arguments: None }] } })] }) }], dot2_token: None, rest: None })] }))
WARN: Skip abi_stable::NO_PATH - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ModPath), arguments: None }] } }), paren_token: Paren, args: [Macro(ExprMacro { attrs: [], mac: Macro { path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(nul_str), arguments: None }] }, bang_token: Bang, delimiter: Paren(Paren), tokens: TokenStream [Literal { lit: "<no path>" }] } })] }))
WARN: Skip abi_stable::PRELUDE - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ModPath), arguments: None }] } }), paren_token: Paren, args: [Macro(ExprMacro { attrs: [], mac: Macro { path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(nul_str), arguments: None }] }, bang_token: Bang, delimiter: Paren(Paren), tokens: TokenStream [Literal { lit: "<prelude>" }] } })] }))
WARN: Skipping abi_stable::destructor_arc - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::clone_arc - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::get_mut_arc - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::try_unwrap_arc - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::strong_count_arc - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::weak_count_arc - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::DEFAULT_VTABLE - (not `pub`).
WARN: Skipping abi_stable::destroy_box - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::DEFAULT_VTABLE - (not `pub`).
WARN: Skip abi_stable::VTABLE_VAL - (not `pub`).
WARN: Skip abi_stable::VTABLE_REF - (not `pub`).
WARN: Skip abi_stable::VTABLE_REF - (not `pub`).
WARN: Skipping abi_stable::is_equal - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::hash - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::_EMPTY_SLICE - (not `pub`).
WARN: Skipping abi_stable::as_debug_display - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::not_as_debug_display - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::VALUE - (not `pub`).
WARN: Skip abi_stable::WM_DEBUG_DISPLAY - (not `pub`).
WARN: Skip abi_stable::VALUE - (not `pub`).
WARN: Skip abi_stable::EMPTY - (Unsupported path expression. [PathSegment { ident: Ident(RSlice), arguments: None }, Colon2, PathSegment { ident: Ident(EMPTY), arguments: None }])
WARN: Skip abi_stable::NEW - (not `pub`).
WARN: Skipping abi_stable::new_utypeid - (not `no_mangle`, and has no `export_name` attribute)
WARN: Skipping abi_stable::some_utypeid - (not `no_mangle`, and has no `export_name` attribute)
WARN: Skipping abi_stable::no_utypeid - (not `no_mangle`, and has no `export_name` attribute)
WARN: Skip abi_stable::MAX_TYPE_ID_SIZE - (not `pub`).
WARN: Skipping abi_stable::destructor_vec - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::grow_capacity_to_vec - (not `pub` but is `extern "C"`)
WARN: Skipping abi_stable::shrink_to_fit_vec - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::DEFAULT_VTABLE - (not `pub`).
WARN: Skip abi_stable::NEW - (not `pub`).
WARN: Skip abi_stable::LOCK - (not `pub`).
WARN: Skip abi_stable::N_100 - (not `pub`).
WARN: Skip abi_stable::N_100 - (not `no_mangle`).
WARN: Skip abi_stable::N_277 - (not `pub`).
WARN: Skip abi_stable::N_277 - (not `no_mangle`).
WARN: Skip abi_stable::EMPTY - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(ref_as_nonnull), arguments: None }] } }), paren_token: Paren, args: [Reference(ExprReference { attrs: [], and_token: And, raw: Reserved, mutability: None, expr: Lit(ExprLit { attrs: [], lit: Int(LitInt { token: 0 }) }) })] }))
WARN: Skipping abi_stable::destroy - (not `pub` but is `extern "C"`)
WARN: Skip abi_stable::UID - (not `pub`).
WARN: Skip abi_stable::UID - (not `pub`).
WARN: Skip abi_stable::IMPL - (not `pub`).
WARN: Skip abi_stable::IMPL - (not `pub`).
WARN: Skip abi_stable::IMPL - (not `pub`).
WARN: Skip abi_stable::IMPL - (not `pub`).
WARN: Skip abi_stable::NEW - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Implemented), arguments: None }] } }), paren_token: Paren, args: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(NonOwningPhantom), arguments: None }, Colon2, PathSegment { ident: Ident(NEW), arguments: None }] } })] }))
WARN: Skip abi_stable::VALUE - (not `pub`).
WARN: Skip abi_stable::NEW - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Unimplemented), arguments: None }] } }), paren_token: Paren, args: [Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(NonOwningPhantom), arguments: None }, Colon2, PathSegment { ident: Ident(NEW), arguments: None }] } })] }))
WARN: Skip abi_stable::VALUE - (not `pub`).
WARN: Skip abi_stable::ROBJECT_VTABLE - (not `pub`).
WARN: Skip abi_stable::VTABLE_VAL - (not `pub`).
WARN: Skip abi_stable::TMP_VTABLE - (not `pub`).
WARN: Skip abi_stable::CONST - (Unsupported expression. Call(ExprCall { attrs: [], func: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Trait_CTO), arguments: None }, Colon2, PathSegment { ident: Ident(from_const), arguments: None }] } }), paren_token: Paren, args: [Reference(ExprReference { attrs: [], and_token: And, raw: Reserved, mutability: None, expr: Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Self), arguments: None }, Colon2, PathSegment { ident: Ident(NONE), arguments: None }] } }) }), Comma, Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(TU_Opaque), arguments: None }] } }), Comma, Path(ExprPath { attrs: [], qself: None, path: Path { leading_colon: None, segments: [PathSegment { ident: Ident(Trait_MV), arguments: None }, Colon2, PathSegment { ident: Ident(VTABLE), arguments: None }] } }), Comma] }))
WARN: Skip abi_stable::CONST_A - (not `pub`).
WARN: Skip abi_stable::GLOBALS - (not `pub`).
WARN: Skip abi_stable::GLOBALS - (not `no_mangle`).
WARN: Skipping abi_stable::initialize_globals_with - (not `no_mangle`, and has no `export_name` attribute)
thread 'main' panicked at 'RResult has 2 params but is being instantiated with 1 values', src/bindgen/ir/enumeration.rs:596:9
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
But it fails. This is probably because of this warning in the official docs:
NOTE: A major limitation of cbindgen is that it does not understand Rust's module system or namespacing. This means that if cbindgen sees that it needs the definition for MyType and there exists two things in your project with the type name MyType, it won't know what to do. Currently, cbindgen's behaviour is unspecified if this happens. However this may be ok if they have different cfgs.
Are there any plans on generating C bindings? Is it feasible/of interest for this library?
I have been banging my head against the wall trying to make #83 work, and I have finally concluded that MapKey
/MapQuery
are at fault. I have been trying to understand it and I will eventually do, but it would have been a much nicer experience if they were documented in the first place. Currently, the only comment is this, for MapQuery
, but I personally find it a bit lacking if you aren't familiar with the code:
/// A trait object used in method that access map entries without replacing them.
After reading it, I still have a few more questions after reading it: why the NotCopyNotClone
marker? Why both MapKey
and MapQuery
? Why is this needed? Why is as_mapkey
unsafe
if we know that self
is never going to be null? Shouldn't the MapQuery
be Pinned
?
The alternative is to remove them altogether, since they just seem to be a hack, though not sure if that would be possible. Any ideas regarding that? I wouldn't like to have someone go through this again.
It would also be nice to have some tests, like this one:
#[test]
fn map_key() {
let test_key = "abc";
let builder = DefaultHashBuilder::new();
let query = MapQuery::<'_, &'static str>::new(&test_key);
let mut hasher = builder.build_hasher();
query.hash(&mut hasher);
let query_hash1 = hasher.finish();
let map_query = unsafe { &query.as_mapkey() };
let mut hasher = builder.build_hasher();
map_query.hash(&mut hasher);
let query_hash2 = hasher.finish();
assert_eq!(query_hash1, query_hash2);
let map_value = MapKey::Value(test_key);
let mut hasher = builder.build_hasher();
map_value.hash(&mut hasher);
let value_hash = hasher.finish();
assert_eq!(value_hash, query_hash2);
}
I'm a newcomer to this crate. I noticed that the documentation mentioned that the interface and implementation generally reside in separate crates, so I was trying to get the example working in that fashion. I commented out the single-crate version of load_root_module_in_directory
and uncommented the 3-crate version. However, cargo build -p implementation
then results in:
error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate
--> implementation/src/lib.rs:112:1
|
112 | impl<T> Appender for RVec<T> {
| ^^^^^^^^^^^^^^^^^^^^^-------
| | |
| | `RVec` is not defined in the current crate
| impl doesn't use only types from inside the current crate
|
= note: define and implement a trait or new type instead
What would be the recommended solution? I don't have enough knowledge of abi_stable to answer that myself.
My example repository, if helpful: https://github.com/Neightro/abi_stable_readme_example
Wasn't sure if there was a specific reason why RBox<T>
doesn't loosen the Sized
constraint on T
. If there is a reason I'd be interested to understand it, and I think it'd be good to include it in the documentation.
From what I can tell, there's nothing preventing this.
Since this method may move the inner value, it must be Unpin.
These are some usecases for this library:
- Creating a plugin system (without support for unloading).
Does this mean using this crate when my plugins should support unloading would be unsafe?
In my use case I'm using this crate to auto-reload recompiled plugins:
https://crates.io/crates/dynamic_reload
My DLL entry point returns a Plugin
trait object that the host takes ownership of.
And yes, I drop this trait object before unloading the DLL.
My question is, can I still use this crate?
Do I even need to, when host and plugin are always compiled with the same nightly?
(Does it make a difference if the DLL is a dylib
or cdylib
regarding ABI stability guarantee?)
Everything seems to work fine when using cdylib
and compiling with the same nightly, even without marshalling my types across the DLL boundary, but people told me the ABI could change even between different invocations of the same rustc.
I am currently working on making the size of type layout constants smaller for the 0.7 release.
I'll commit the work on this next week in the 0.7 branch(which is for developing the 0.7 version before releasing it).
Here are some things I am going to do to make the type layout constants smaller:
Clippy recently(-ish) stabilised a new lint, and code generated by #[sabi_trait]
seems to fail it.
From recursive macro expansion:
#[doc = r""]
pub obj: Broker_Backend<_ErasedPtr>,
I'm currently missing a stable_abi alternative for Fn, FnMut and FnOnce. I'm planning to implement those in the following style:
#[repr(C)]
#[derive(StableAbi)]
pub struct RBoxFnOnce<TParam, TResult> {
caller: extern "C" fn(usize, TParam) -> TResult,
remover: extern "C" fn(usize),
inner: usize,
}
impl<T, TParam, TResult> From<T> for RBoxFnOnce<TParam, TResult> where T: FnOnce(TParam) ->TResult {
fn from(inner: T) -> Self {
let box_inner = Box::new(inner);
let inner : usize = Box::into_raw(box_inner) as usize;
extern "C" fn caller<T, TParam, TResult>(that: usize, param: TParam) -> TResult where T: FnOnce(TParam) -> TResult {
let function = unsafe { Box::from_raw(that as *mut T) };
(function)(param)
}
extern "C" fn dropper<T, TParam, TResult>(that: usize) where T: FnOnce(TParam) -> TResult {
drop(unsafe { Box::from_raw(that as *mut T) });
}
Self {
caller: caller::<T, TParam, TResult>,
remover: dropper::<T, TParam, TResult>,
inner
}
}
}
impl<TParam, TResult> Drop for RBoxFnOnce<TParam, TResult> {
fn drop(&mut self) {
if self.inner != 0 {
(self.remover)(self.inner);
}
}
}
impl<TParam, TResult> RBoxFnOnce<TParam, TResult> {
fn call(mut self, p: TParam) -> TResult {
let inner = self.inner;
self.inner = 0;
(self.caller)(inner, p)
}
}
Usage looks like:
fn api(f: impl Into<RBoxFnOnce<usize, usize>>) {
assert_eq!(5, f.into().call(1));
}
#[test]
fn test () {
let ctx = "Test".to_string();
api(move |x| {
let a = ctx;
x + a.len()
})
}
I'm not very experienced, but IMO this shouldn't have undefined behavior. If you are interested to integrate such functionality into stable_abi, I'm happy to fork your repo and push everything upstream eventually. Otherwise, I'll just create my own repo. Please let me know about your preferences.
At first sight this crate does many things I've tried to accomplish in the past 2 years in my free time, so thank you for that.
Before I dig in further, I wanted to ask if, in a plugin system, any if the plugins can get as dependency any other plugins?
Of course:
If not currently possible, do you see this as a possible feature which can be planned in? Would it be before 1.0.0 or after that?
abi_stable_crates/abi_stable/Cargo.toml
Line 54 in c52b078
Should be 0.2.2.
This causes problems because repr_offset 0.2.1 had the silly bug on line 131 of having a semi colon in the code. Can you push a fix please :-)
Is it possible to support "C-unwind" ABI? Is there a temporary workaround to change the generated extern "C" to extern "C-unwind"?
Hello, first of all, thanks for this amazing crate.
In my project, I find your #[repr(C)]
equivalents of common types from std
and such (RVec
, RString
, etc) very useful, however - everything else on this crate - not so much.
I was wondering if it would be possible to separate the abi_stable::std_types
module to a separate crate, that would just provide #[repr(C)]
types and a simple numerical ABI_VERSION
constant. That would make things much simpler for my project (and others, my case is definitely not the only one), help compilation times and so on. Making modular libraries is always a good practice.
I've been developing something using abi_stable for a while now, and the biggest pain point is that, because it ideally stays open at all times, it's not possible for me to swap out the dlls as I develop them without fully shutting down and re-opening my application. Is there any way to fully unload and release the lock on the files? I'm dropping the instances and they're getting cleaned up, but the files stay open.
Recently I am developing for a massive embedded chip debugger software. I uses abi_stable
to design its plugin system, because this software may allow users to install plugins for backends, interface adapters and chip targets. I could design one interface crate, but here are still two (or maybe three) types of plugin crates that I need to implement:
trait
s) in interface crate;To make things clear I have an example. Users may plug a JTAG dongle onto USB slot, then connect target MCU board with this dongle. So here I need three plugins. First one wraps WinUSB or other operating system specific functions to provide universal USB structures in interface crate. Second one wraps dongle protocol support that requires USB traits and provides JTAG traits. Third one requires JTAG and provides a universal chip target flash trait. Finally the application may enumerate all flash traits using all three plugins and pick one flash trait to perform the flash write command.
Here I need to implement all three plugins. The first could be easy as it could be implemented as a trait object that could provide to interface crate, as examples in abi_stable
project have done. But the second and third ones are somehow tricky (I haven't find a way) to write, because they not only provides interfaces like usual plugins, but also requires one interface from the crate thus somehow performs just like an application.
Is there existing solutions to my problem? Or how should I design a system that allows plugin to provide interface implementations as well as requires some interfaces? Please provide with useful suggestions or example code, thanks!
This is a help-wanted issue. I don't know if it's proper to post it here; if not, please let me know. Thanks!
When trying to use char
as an FFI type, the error below is thrown. According to the documentation, a char
is always four bytes in size, so this should not be hard to support.
the trait bound `char: abi_stable::StableAbi` is not satisfied
the following other types implement trait `abi_stable::StableAbi`:
&'a T
&'a mut T
()
*const T
*mut T
[T; N]
abi_stable::DynTrait<'borr, P, I, EV>
abi_stable::RMut<'a, T>
and 315 others
required for `[char; 2]` to implement `abi_stable::StableAbi`
2 redundant requirements hidden
required for `abi_stable::std_types::ROption<abi_stable::std_types::RVec<[char; 2]>>` to implement `abi_stable::StableAbi`
Hello, I found a soundness issue in this crate.
abi_stable_crates/abi_stable/src/utils.rs
Lines 75 to 77 in 5661b01
The glossary section in docs.rs index mentions:
user crate
:A crate that depends on an interface crate and loads 1 or more implementation crates for it.
But calling RootModule::load_from_file
twice with different implementation DLL files returns a reference to the implementation from the first DLL on both occurrences.
Delving into its source code, it seems to keep a single static reference per interface type, which is initialized on the first call to RootModule::load_from_file
and all subsequent calls to RootModule::load_from_file
returns a copy of it irrespective of the parameter it has been called with.
Now, how multiple implementation DLLs of some interface can be loaded? If it needs some change in the abi_stable
crate, I would be happy to help.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.