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

Rust Compatibility Issues #7

Open
Eliah-Lakhin opened this issue Dec 22, 2024 · 5 comments
Open

Rust Compatibility Issues #7

Eliah-Lakhin opened this issue Dec 22, 2024 · 5 comments
Assignees
Labels
enhancement New feature proposal minor No critical impact

Comments

@Eliah-Lakhin
Copy link
Owner

Even though Ad Astra 1.x targets Rust MSRV 1.79 with the 2021 edition, and I don't plan to raise the minimum requirements in the foreseeable future to comply with backward compatibility policies, the project's crates should remain compatible with the latest stable releases of Rust, including the 2024 edition.

This issue serves as an ongoing tracker for bugs and warnings arising from the latest Rust releases.

@DhruvDh
Copy link
Contributor

DhruvDh commented Dec 23, 2024

Hi, from yesterdays' fixes I am able to compile the exporting example in WSL but not on windows. For whatever reason the issue persists when compiling (running cargo check on https://github.com/DhruvDh/umm-next/tree/25c78bd4202a156515e172d9b75e1ca355cdbb5f) on windows with the following toolchain:

active toolchain
----------------

nightly-x86_64-pc-windows-msvc (overridden by 'C:\Users\dhruv\repositories\umm-next\rust-toolchain.toml')
rustc 1.85.0-nightly (426d17342 2024-12-21)
cargo check output on windows
Compiling ad-astra-export v1.0.0 (https://github.com/Eliah-Lakhin/ad-astra?rev=ab7fbad5077fd1529266031aae336e2d9145f35e#ab7fbad5)
    Checking ad-astra v1.0.0 (https://github.com/Eliah-Lakhin/ad-astra?rev=ab7fbad5077fd1529266031aae336e2d9145f35e#ab7fbad5)
    Checking umm-next v0.1.0 (C:\Users\dhruv\repositories\umm-next)
error: unsafe attribute used without unsafe
  --> src\lib.rs:17:10
   |
17 |   #[export(package)]
   |  __________^
18 | | #[derive(Default)]
19 | | struct Package;
   | |______________^ usage of unsafe attribute
   |
help: wrap the attribute in `unsafe(...)`
   |
17 ~ #[export(unsafe(package)]
18 | #[derive(Default)]
19 ~ struct Package);
   |

error: unsafe attribute used without unsafe
  --> src\lib.rs:23:8
   |
23 | pub fn deg(degrees: f64) -> f64 {
   |        ^^^ usage of unsafe attribute
   |
help: wrap the attribute in `unsafe(...)`
   |
23 | pub fn unsafe(deg)(degrees: f64) -> f64 {
   |        +++++++   +

error: unsafe attribute used without unsafe
  --> src\lib.rs:29:8
   |
29 | pub fn rad(radians: f64) -> f64 {
   |        ^^^ usage of unsafe attribute
   |
help: wrap the attribute in `unsafe(...)`
   |
29 | pub fn unsafe(rad)(radians: f64) -> f64 {
   |        +++++++   +

error: unsafe attribute used without unsafe
  --> src\lib.rs:35:8
   |
35 | pub fn round(value: f64) -> i64 {
   |        ^^^^^ usage of unsafe attribute
   |
help: wrap the attribute in `unsafe(...)`
   |
35 | pub fn unsafe(round)(value: f64) -> i64 {
   |        +++++++     +

error: unsafe attribute used without unsafe
  --> src\lib.rs:42:12
   |
42 |   pub struct Vector {
   |  ____________^
43 | |     /// The x-coordinate of the vector.
44 | |     pub x: f64,
...  |
47 | |     pub y: f64,
   | |______________^ usage of unsafe attribute
   |
help: wrap the attribute in `unsafe(...)`
   |
42 ~ pub struct unsafe(Vector {
43 |     /// The x-coordinate of the vector.
...
46 |     /// The y-coordinate of the vector.
47 ~     pub y: f64),
   |

error: unsafe attribute used without unsafe
  --> src\lib.rs:51:14
   |
51 | impl Neg for Vector {
   |              ^^^^^^ usage of unsafe attribute
   |
help: wrap the attribute in `unsafe(...)`
   |
51 | impl Neg for unsafe(Vector) {
   |              +++++++      +

error: unsafe attribute used without unsafe
  --> src\lib.rs:63:14
   |
63 | impl Add for Vector {
   |              ^^^^^^ usage of unsafe attribute
   |
help: wrap the attribute in `unsafe(...)`
   |
63 | impl Add for unsafe(Vector) {
   |              +++++++      +

error: unsafe attribute used without unsafe
  --> src\lib.rs:75:18
   |
75 | impl Display for Vector {
   |                  ^^^^^^ usage of unsafe attribute
   |
help: wrap the attribute in `unsafe(...)`
   |
75 | impl Display for unsafe(Vector) {
   |                  +++++++      +

error: unsafe attribute used without unsafe
   --> src\lib.rs:82:6
    |
82  |   impl Vector {
    |  ______^
83  | |     /// Constructs a new 2D vector.
84  | |     #[export(name "vec")]
85  | |     pub fn new(x: f64, y: f64) -> Self {
...   |
113 | |     /// Transforms this vector using the provided transformation matrix.
114 | |     pub fn transform(&mut self, matrix: &Matrix) -> &mut Self {
    | |______________________________________^ usage of unsafe attribute
    |
help: wrap the attribute in `unsafe(...)`
    |
82  ~ impl unsafe(Vector {
83  |     /// Constructs a new 2D vector.
...
113 |     /// Transforms this vector using the provided transformation matrix.
114 ~     pub fn transform(&mut self, matrix): &Matrix) -> &mut Self {
    |

error: unsafe attribute used without unsafe
   --> src\lib.rs:127:30
    |
127 |   #[derive(Debug, Clone, Copy, PartialEq)]
    |  ______________________________^
128 | | pub struct Matrix {
    | |_________________^ usage of unsafe attribute
    |
help: wrap the attribute in `unsafe(...)`
    |
127 ~ #[derive(Debug, Clone, Copy, unsafe(PartialEq)]
128 ~ pub struct Matrix) {
    |

error: unsafe attribute used without unsafe
   --> src\lib.rs:134:14
    |
134 | impl Mul for Matrix {
    |              ^^^^^^ usage of unsafe attribute
    |
help: wrap the attribute in `unsafe(...)`
    |
134 | impl Mul for unsafe(Matrix) {
    |              +++++++      +

error: unsafe attribute used without unsafe
   --> src\lib.rs:152:6
    |
152 |   impl Matrix {
    |  ______^
153 | |     /// Creates a 2x2 transformation matrix that rotates the coordinate system
154 | |     /// by the specified angle in radians.
155 | |     pub fn rotation(angle: f64) -> Self {
...   |
173 | |     /// Constructs a new matrix that is the inverse of this one.
174 | |     pub fn invert(&self) -> Self {
    | |_________________^ usage of unsafe attribute
    |
help: wrap the attribute in `unsafe(...)`
    |
152 ~ impl unsafe(Matrix {
153 |     /// Creates a 2x2 transformation matrix that rotates the coordinate system
...
173 |     /// Constructs a new matrix that is the inverse of this one.
174 ~     pub fn invert)(&self) -> Self {
    |

error: could not compile `umm-next` (lib) due to 12 previous errors

@Eliah-Lakhin
Copy link
Owner Author

@DhruvDh Thank you for your reply! There was something I forgot to push yesterday. The latest commit to the master branch should bring everything in sync. This time, I manually tested cargo build on my Windows machine using your repository with the latest Ad Astra revision for both nightly-x86_64-pc-windows-gnu and nightly-x86_64-pc-windows-msvc targets.

Everything seems to be working as expected now. Please note that for some nightly targets, we currently need to disable Rust LLD due to known issues in its implementation. This is not specific to Ad Astra but affects some other crates on crates.io as well. These issues do not occur with the Stable Rust toolchain.

@Kobzol
Copy link

Kobzol commented Mar 9, 2025

Hi, could you please specify which specific known issues regarding Rust's LLD are you talking about? I'm currently trying to categorize such issues for LLD stabilization. Thank you!

@Eliah-Lakhin
Copy link
Owner Author

@Kobzol

Hi Jakub,

Ad Astra uses the same approach for linking sections as the well-known linkme crate. I'm not an expert in linkers, but I'll try to explain in simple terms what my crate and linkme actually do.

Both crates aim to automatically enumerate function pointers specified in special static fields across the Cargo dependency tree of the current project and collect these pointers into a single array located in a linker section, making them available for iteration. Ad Astra leverages this mechanism for Rust-code introspection metadata, while linkme uses it to gather custom pointers to user-defined values. Essentially, both crates attempt to implement a plugin-like system by utilizing linker features to consolidate "plugin" entry points in one place.

The way my crate works (and linkme follows a similar approach under the hood) is by defining three static values that determine the start and end of the concatenated linker section, along with a static slice representing the collected functions:

fn exporters() -> &'static [ExporterFn] {
    unsafe extern "Rust" {
        #[link_name = "__start_adastrexpr"]
        static START: ExporterFn;
        #[link_name = "__stop_adastrexpr"]
        static STOP: ExporterFn;
    }

    #[used]
    #[unsafe(link_section = "adastrexpr")]
    static mut EMPTY: [ExporterFn; 0] = [];

    let start = unsafe { addr_of!(START) };
    let stop = unsafe { addr_of!(STOP) };

    let len = ((stop as usize) - (start as usize)) / size_of::<ExporterFn>();

    unsafe { slice::from_raw_parts::<'static, ExporterFn>(start, len) }
}

Source Reference

To add a function to this list, the user defines (via a procedural macro) special static variables within the project's dependency tree:

#[used]
#[cfg_attr(
    any(
        target_os = "none",
        target_os = "linux",
        target_os = "android",
        target_os = "fuchsia",
        target_os = "psp",
        target_os = "freebsd",
    ),
    unsafe(link_section = "adastrexpr"),
)]
static __LINKED: extern "C" fn() = /* a pointer to a Rust function */;

Source Reference

In my experience, this setup works flawlessly with the default LLD linker. However, when using Rust-LLD, users often encounter errors like the following:

rust-lld: error: undefined symbol: __start_adastrexpr
>>> referenced by __intrinsics.rs:172 (crates/main/src/runtime/__intrinsics.rs:172)
>>>               ad_astra-47c284d300b603d4.3lrwimok51l5fmgudr8tidovt.rcgu.o:(ad_astra::runtime::__intrinsics::DeclarationGroup::exporters::h4d8c5c60fac83fee) in archive /home/eliah/Documents/projects/ad-astra/work/target/debug/deps/libad_astra-47c284d300b603d4.rlib
>>> referenced by __intrinsics.rs:175 (crates/main/src/runtime/__intrinsics.rs:175)
>>>               ad_astra-47c284d300b603d4.3lrwimok51l5fmgudr8tidovt.rcgu.o:(ad_astra::runtime::__intrinsics::DeclarationGroup::exporters::h4d8c5c60fac83fee) in archive /home/eliah/Documents/projects/ad-astra/work/target/debug/deps/libad_astra-47c284d300b603d4.rlib
>>> referenced by __intrinsics.rs:175 (crates/main/src/runtime/__intrinsics.rs:175)
>>>               ad_astra-47c284d300b603d4.3lrwimok51l5fmgudr8tidovt.rcgu.o:(ad_astra::runtime::__intrinsics::DeclarationGroup::exporters::h4d8c5c60fac83fee) in archive /home/eliah/Documents/projects/ad-astra/work/target/debug/deps/libad_astra-47c284d300b603d4.rlib
>>> the encapsulation symbol needs to be retained under --gc-sections properly; consider -z nostart-stop-gc (see https://lld.llvm.org/ELF/start-stop-gc)

rust-lld: error: undefined symbol: __stop_adastrexpr
>>> referenced by __intrinsics.rs:173 (crates/main/src/runtime/__intrinsics.rs:173)
>>>               ad_astra-47c284d300b603d4.3lrwimok51l5fmgudr8tidovt.rcgu.o:(ad_astra::runtime::__intrinsics::DeclarationGroup::exporters::h4d8c5c60fac83fee) in archive /home/eliah/Documents/projects/ad-astra/work/target/debug/deps/libad_astra-47c284d300b603d4.rlib
>>> referenced by __intrinsics.rs:175 (crates/main/src/runtime/__intrinsics.rs:175)
>>>               ad_astra-47c284d300b603d4.3lrwimok51l5fmgudr8tidovt.rcgu.o:(ad_astra::runtime::__intrinsics::DeclarationGroup::exporters::h4d8c5c60fac83fee) in archive /home/eliah/Documents/projects/ad-astra/work/target/debug/deps/libad_astra-47c284d300b603d4.rlib
>>> referenced by __intrinsics.rs:175 (crates/main/src/runtime/__intrinsics.rs:175)
>>>               ad_astra-47c284d300b603d4.3lrwimok51l5fmgudr8tidovt.rcgu.o:(ad_astra::runtime::__intrinsics::DeclarationGroup::exporters::h4d8c5c60fac83fee) in archive /home/eliah/Documents/projects/ad-astra/work/target/debug/deps/libad_astra-47c284d300b603d4.rlib
collect2: error: ld returned 1 exit status

I tested this on rustc 1.85.0-nightly (d49be02cf 2024-12-02), in dev mode. Users of the linkme crate have reported similar issues with Rust 1.85: dtolnay/linkme#111.

David addressed this issue by modifying the build scripts to revert to the standard LLD linker in nightly: dtolnay/linkme#88.

I applied the same workaround-fix in my .cargo/config.toml file:

[target.x86_64-unknown-linux-gnu]
rustflags=["-Zlinker-features=-lld"]
rustdocflags=["-Zlinker-features=-lld"]

I can confirm that this issue is not reproducible in rustc 1.87.0-nightly (3ea711f17 2025-03-09). However, I'm not certain whether this is due to a fix in Rust-LLD or a change in the default linker used in the nightly version.

I haven't conducted extensive testing outside the Linux environment, but from brief checks, this issue does not seem to affect Windows.

I'm happy to provide more details if needed, and I hope that Rust-LLD will address this issue before stabilization.

Regards,
Ilya

@Kobzol
Copy link

Kobzol commented Mar 10, 2025

Ah, it's linkme. Yeah, this should work now, it's not a concidence: rust-lang/rust#137685.

It's arguably a problem on the linkme side (or whatever else crate that uses the same start/stop section approach), rather than LLD's side, but we decided to stay conservative and support this use-case for now.

Great, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature proposal minor No critical impact
Projects
Status: In Progress
Development

No branches or pull requests

3 participants