如何避免`#[global_allocator]`冲突?

tok*_*a-n 5 rust

假设我有三个箱子:foobarbaz

Cargo.toml

[workspace]
members = [
    "foo",
    "bar",
    "baz",
]

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"
Run Code Online (Sandbox Code Playgroud)

foo/Cargo.toml

[package]
name = "foo"
version = "0.1.0"
edition = "2018"

[lib]
name = "foo"
crate-type = ["staticlib"]

[dependencies]
bar = { path = "../bar", default-features = false }
Run Code Online (Sandbox Code Playgroud)

foo/src/lib.rs

[workspace]
members = [
    "foo",
    "bar",
    "baz",
]

[profile.dev]
panic = "abort"

[profile.release]
panic = "abort"
Run Code Online (Sandbox Code Playgroud)

bar/Cargo.toml

[package]
name = "bar"
version = "0.1.0"
edition = "2018"

[lib]
name = "bar"

[features]
default = ["heap"]
heap = []
Run Code Online (Sandbox Code Playgroud)

bar/src/lib.rs

[package]
name = "foo"
version = "0.1.0"
edition = "2018"

[lib]
name = "foo"
crate-type = ["staticlib"]

[dependencies]
bar = { path = "../bar", default-features = false }
Run Code Online (Sandbox Code Playgroud)

baz/Cargo.toml

[package]
name = "baz"
version = "0.1.0"
edition = "2018"

[lib]
name = "baz"
crate-type = ["staticlib"]

[dependencies]
bar = { path = "../bar" }
Run Code Online (Sandbox Code Playgroud)

baz/src/lib.rs

#![no_std]

extern crate bar as _;

use core::alloc::{GlobalAlloc, Layout};

#[global_allocator]
static ALLOCATOR: Allocator = Allocator;

struct Allocator;
unsafe impl GlobalAlloc for Allocator {
    unsafe fn alloc(&self, _: Layout) -> *mut u8 {
        todo!()
    }

    unsafe fn dealloc(&self, _: *mut u8, _: Layout) {
        todo!()
    }
}
Run Code Online (Sandbox Code Playgroud)

这里,bar提供了全局分配器,并且 和 都foo依赖bazbar。但是,foo不会使bar的全局分配器使用其原始分配器,因此foo依赖于bar没有默认功能。

cargo clippy在每个目录(foo/bar/和)上运行baz/都会成功。但是,在项目根目录上运行该命令会导致错误:

%cargo clippy
    Checking bar v0.1.0 (/tmp/tmp.wlBjM4wNFx/bar)
    Checking baz v0.1.0 (/tmp/tmp.wlBjM4wNFx/baz)
    Checking foo v0.1.0 (/tmp/tmp.wlBjM4wNFx/foo)
error: the `#[global_allocator]` in this crate conflicts with global allocator in: bar

error: could not compile `foo` due to previous error
Run Code Online (Sandbox Code Playgroud)

foo实际上,当使用其原始全局分配器并禁用 的bar分配器时,不存在全局分配器冲突。如何避免这个错误?

版本

rustup 1.24.3 (ce5817a94 2021-05-31)
cargo 1.56.0-nightly (b51439fd8 2021-08-09)
rustc 1.56.0-nightly (0035d9dce 2021-08-16)
Run Code Online (Sandbox Code Playgroud)

tok*_*a-n 3

这是工作区的属性。bjorn3在 Zulip 上说:

如果 foo、bar 和 baz 全部编译在一起,则当 foo 或 baz 依赖于 bar 时,将为 bar 全局启用堆功能。Cargo 将合并每个依赖包所需的所有功能,并使用这些功能编译一次依赖项。

因此,由于需要它bar而编译了该功能,因此在编译时也会启用其功能。因此,和的全局分配器同时启用,从而导致错误。heapbazfoofoobar