Repository: dtolnay/cxx (language: rust)

Issue:
Use shared type from another bridge module
I tried to use a Shared type from one module inside another module, but have a quite strange error message:

```
error: `extern` block uses type `std::string::String`, which is not FFI-safe
  --> linkage-test/src/two.rs:12:31
   |
12 |     fn IClass2_create(params: &CommonParams) -> SharedPtr<IClass2>;
   |                               ^^^^^^^^^^^^^ not FFI-safe
   |
note: the lint level is defined here
  --> linkage-test/src/two.rs:1:1
   |
1  | #[cxx::bridge]
   | ^^^^^^^^^^^^^^
   = help: consider adding a `#[repr(C)]` or `#[repr(transparent)]` attribute to this struct
   = note: this struct has unspecified layout
   = note: this error originates in an attribute macro (in Nightly builds, run with -Z macro-backtrace for more info)

error: aborting due to previous error
```

Here an MVP for this bug. CXX version 1.0.34.

The `main.rs`
```
pub mod one;
pub mod two;

#[cxx::bridge]
mod ffi {}

fn main() {
    let a = one::ffi::CommonParams {
        count: 123,
        name: String::from("somename"),
    };

    let b = one::ffi::IClass1_create(&a);
    println!("B is not empty: {}", b.get_name());

    let c = two::ffi::IClass2_create(&a);
    println!("C is not empty: {}", c.get_name());
}

```

The `one.rs`
```
#[cxx::bridge]
pub mod ffi {

  #[derive(Debug, Default)]
  pub struct CommonParams {
    pub count: u32,
    pub name: String,
  }

  unsafe extern "C++" {
    include!("linkage-test/wrap/wrapper.hpp");
    type IClass1;
    fn IClass1_create(params: &CommonParams) -> SharedPtr<IClass1>;
    fn get_name(&self) -> String;
  }
}

```

The `two.rs`
```
#[cxx::bridge]
pub mod ffi {
  unsafe extern "C++" {
    include!("linkage-test/wrap/one.rs.hpp");
    type CommonParams = crate::one::ffi::CommonParams;
  }

  unsafe extern "C++" {
    include!("linkage-test/wrap/wrapper.hpp");

    type IClass2;
    fn IClass2_create(params: &CommonParams) -> SharedPtr<IClass2>;
    fn get_name(self: &IClass2) -> String;
  }
}

```

The `wrapper.hpp`
```
#pragma once

#include <rust/cxx.h>

#include <memory>

struct IClass1 {
  int64_t count;
  std::string name;

  rust::String get_name() const;
};

struct IClass2 {
  int64_t count;
  std::string name;

  rust::String get_name() const;
};

struct CommonParams;

std::shared_ptr<IClass1> IClass1_create(const CommonParams &params);

std::shared_ptr<IClass2> IClass2_create(const CommonParams &params);
```

I omit `wrapper.cpp` to simplify the example. Nothing interesting there.

The `build.rs`
```
fn main() {
  cxx_build::bridges(vec!["src/main.rs", "src/one.rs", "src/two.rs"])
    .file("wrap/wrapper.cpp")
    .flag_if_supported("-std=c++17")
    .compile("test-link");

  println!("cargo:rustc-link-lib=lprsdk");
  println!("cargo:rerun-if-changed=src/main.rs");
  println!("cargo:rerun-if-changed=wrap/wrapper.cpp");
  println!("cargo:rerun-if-changed=wrap/wrapper.hpp");
}

```

You can see, that I can use the `IClass1_create` function properly, but can't use `IClass2_create` with the same argument.
Also, as you know, I can't use `#[repr(...)]` for shared types inside the `#[cxx::bridge]`.

What should I do to prevent this error? Is it correct behavior? How can I fix or, maybe, workaround this?

P. S.

For now, I'm tried to defined the same Shared type `CommonParam` in the both modules, but it's cause compile failure, because he thinks, that there are two different types, and he can't handle the type as the argument of the function.



Discussion / hints:
You notified [here](https://github.com/dtolnay/cxx/issues/297) how to define the type from other module, but it doesn't work

Fix patch:
diff --git a/syntax/improper.rs b/syntax/improper.rs
index 6a9b5ac07..f19eb86a7 100644
--- a/syntax/improper.rs
+++ b/syntax/improper.rs
@@ -19,7 +19,7 @@ impl<'a> Types<'a> {
                 } else if let Some(strct) = self.structs.get(ident) {
                     Depends(&strct.name.rust) // iterate to fixed-point
                 } else {
-                    Definite(self.rust.contains(ident))
+                    Definite(self.rust.contains(ident) || self.aliases.contains_key(ident))
                 }
             }
             Type::RustBox(_)


Test patch: