Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#[swift_bridge::bridge] macro forces module to be private #252

Open
gabbifish opened this issue Feb 7, 2024 · 2 comments
Open

#[swift_bridge::bridge] macro forces module to be private #252

gabbifish opened this issue Feb 7, 2024 · 2 comments
Labels
good first issue Good for newcomers

Comments

@gabbifish
Copy link
Contributor

I defined a transparent type in one ffi submodule:

// error.rs
#[swift_bridge::bridge]
pub mod ffi {
    #[swift_bridge(swift_repr="struct")]
    pub struct RuntimeError {
        pub error: String
    }
}

and tried to import it in another module:

// lib.rs
mod error

use error:ffi:RuntimeError;

but saw the following error for this line: use error:ffi:RuntimeError:

module `ffi` is private

It seems the #[swift_bridge::bridge] macro forces its module to be private--is this intentional, or can its private/public status be passed through?

@chinedufn
Copy link
Owner

chinedufn commented Feb 7, 2024

Not intentional, we've just been adding things as we need them and you're the first to make note of this.

One workaround is to use pub use self::ffi::Foo from outside of mod foo to expose Foo to other module.


Supporting this should be easy though if you're interested. Roughly two lines of implementation code + a couple of tests.

Here's how one might add support for preserving the module's visibility, in case you or any future person wants to tackle this:

Potential Solution

Add a parsing test where we verify that we can store the module's visibility

#[cfg(test)]
mod tests {
use super::*;
use crate::test_utils::{parse_errors, parse_ok};
/// Verify that we can parse a cfg feature from a module.
#[test]
fn parse_module_cfg_feature() {
let tokens = quote! {
#[swift_bridge::bridge]
#[cfg(feature = "some-feature")]
mod foo {}
};
let module = parse_ok(tokens);
assert_eq!(module.cfg_attrs.len(), 1);
match &module.cfg_attrs[0] {
CfgAttr::Feature(feature) => {
assert_eq!(feature.value(), "some-feature")
}
};
}
/// Verify that we get an error when parsing an unsupported module item, such as a
/// `use` statement.
#[test]
fn invalid_module_item() {
let tokens = quote! {
#[swift_bridge::bridge]
mod foo {
use std;
}
};
let errors = parse_errors(tokens);
assert_eq!(errors.len(), 1);
match &errors[0] {
ParseError::InvalidModuleItem { item } => {
assert!(matches!(item, Item::Use(_)))
}
_ => panic!(),
}
}
}


Add a codegen test where we confirm that the module's visibility is preserved in the generated Rust tokens:

Perhaps in a mod module_visibility_tests in here

mod already_declared_attribute_codegen_tests;
mod argument_label_codegen_tests;
mod async_function_codegen_tests;
mod boxed_fnonce_codegen_tests;
mod built_in_tuple_codegen_tests;
mod c_header_declaration_order_codegen_tests;
mod conditional_compilation_codegen_tests;
mod derive_attribute_codegen_tests;
mod derive_struct_attribute_codegen_tests;
mod extern_rust_function_opaque_rust_type_argument_codegen_tests;
mod extern_rust_function_opaque_rust_type_return_codegen_tests;
mod extern_rust_method_swift_class_placement_codegen_tests;
mod extern_swift_function_opaque_swift_type_return_codegen_tests;
mod function_attribute_codegen_tests;
mod generic_opaque_rust_type_codegen_tests;
mod opaque_rust_type_codegen_tests;
mod opaque_swift_type_codegen_tests;
mod option_codegen_tests;
mod result_codegen_tests;
mod return_into_attribute_codegen_tests;
mod single_representation_type_elision_codegen_tests;
mod string_codegen_tests;
mod transparent_enum_codegen_tests;
mod transparent_struct_codegen_tests;
mod vec_codegen_tests;


Add a field SwiftBridgeModule.visibility: syn::Visibility

pub struct SwiftBridgeModule {
name: Ident,


Then set the field during parsing visibility: item_mod.visibility

let module = SwiftBridgeModule {
name: module_name,


Interpolate the visibility here #visibility #mod_name


Verify that tests pass using cargo test -p swift-bridge-ir

@chinedufn chinedufn added the good first issue Good for newcomers label Feb 7, 2024
@gabbifish
Copy link
Contributor Author

Awesome! I'll try and get a PR open for this soon :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
good first issue Good for newcomers
Projects
None yet
Development

No branches or pull requests

2 participants