Clippy 冗余分配 lint
Clippy redundant allocation lint
所以我有这个特征和一个实现它的结构:
trait Trait {
fn foo(&self) -> u64;
}
/// No Copy trait supported because it's expensive
struct Expensive {
id: u64,
}
impl Trait for Expensive {
fn foo(&self) -> u64 {
self.id
}
}
我有另一个我希望成为全局的结构,它包含特征:
struct Cheap {
pub item: Box<dyn Trait>,
}
thread_local! {
static CHEAP: Cheap = Cheap {
item: Box::new(Expensive {
id: 4
})
}
}
fn trait_item() -> Box<dyn Trait> {
CHEAP.with(|c| c.item)
}
失败是因为
error[E0507]: cannot move out of `c.item` which is behind a shared reference
--> src/main.rs:35:20
|
35 | CHEAP.with(|c| c.item)
| ^^^^^^ move occurs because `c.item` has type `std::boxed::Box<dyn Trait>`, which does not implement the `Copy` trait
总是在 .with(...)
部分进行处理并不可行,因为一些接受 Trait
的函数并不关心它来自哪里。所以我尝试 return 引用它:
fn trait_item<'a>() -> &'a Box<dyn Trait> {
CHEAP.with(|c| &c.item)
}
这也失败了,因为我无法在 with
:
之外发送引用
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:33:20
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 33:16...
--> src/main.rs:33:16
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:33:20
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 32:15...
--> src/main.rs:32:15
|
32 | fn trait_item<'a>() -> &'a Box<dyn Trait> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:33:5
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^^^^^^^^^^^^^^^^^
因此,我将整个内容包装在一个 Rc
中,如下所示:
struct Cheap {
pub item: Rc<Box<dyn Trait>>,
}
thread_local! {
static CHEAP: Cheap = Cheap {
item: Rc::new(Box::new(Expensive {
id: 4
}))
}
}
fn trait_item() -> Rc<Box<dyn Trait>> {
CHEAP.with(|c| c.item.clone())
}
但现在 clippy 抱怨:
warning: usage of `Rc<Box<T>>`
--> src/main.rs:41:15
|
41 | pub item: Rc<Box<dyn Trait>>,
| ^^^^^^^^^^^^^^^^^^ help: try: `Box<dyn Trait>`
|
= note: `#[warn(clippy::redundant_allocation)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
warning: usage of `Rc<Box<T>>`
--> src/main.rs:53:20
|
53 | fn trait_item() -> Rc<Box<dyn Trait>> {
| ^^^^^^^^^^^^^^^^^^ help: try: `Box<dyn Trait>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
warning: 2 warnings emitted
我是不是遗漏了什么,或者实际上不可能按照 clippy 的建议去做?
您也可以将特征对象包装在 Rc
中,因为 Rc
也是一个指针。
因此,如果你有 Rc<Box<T>>
,你有两个分配:一个用于 T
,一个用于 Box
(另一个指针,现在在堆上)。相反,使用 Rc<dyn MyTrait>
只有一个分配。
所以我有这个特征和一个实现它的结构:
trait Trait {
fn foo(&self) -> u64;
}
/// No Copy trait supported because it's expensive
struct Expensive {
id: u64,
}
impl Trait for Expensive {
fn foo(&self) -> u64 {
self.id
}
}
我有另一个我希望成为全局的结构,它包含特征:
struct Cheap {
pub item: Box<dyn Trait>,
}
thread_local! {
static CHEAP: Cheap = Cheap {
item: Box::new(Expensive {
id: 4
})
}
}
fn trait_item() -> Box<dyn Trait> {
CHEAP.with(|c| c.item)
}
失败是因为
error[E0507]: cannot move out of `c.item` which is behind a shared reference
--> src/main.rs:35:20
|
35 | CHEAP.with(|c| c.item)
| ^^^^^^ move occurs because `c.item` has type `std::boxed::Box<dyn Trait>`, which does not implement the `Copy` trait
总是在 .with(...)
部分进行处理并不可行,因为一些接受 Trait
的函数并不关心它来自哪里。所以我尝试 return 引用它:
fn trait_item<'a>() -> &'a Box<dyn Trait> {
CHEAP.with(|c| &c.item)
}
这也失败了,因为我无法在 with
:
error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
--> src/main.rs:33:20
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^
|
note: first, the lifetime cannot outlive the anonymous lifetime #2 defined on the body at 33:16...
--> src/main.rs:33:16
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^^^^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:33:20
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^
note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 32:15...
--> src/main.rs:32:15
|
32 | fn trait_item<'a>() -> &'a Box<dyn Trait> {
| ^^
note: ...so that reference does not outlive borrowed content
--> src/main.rs:33:5
|
33 | CHEAP.with(|c| &c.item)
| ^^^^^^^^^^^^^^^^^^^^^^^
因此,我将整个内容包装在一个 Rc
中,如下所示:
struct Cheap {
pub item: Rc<Box<dyn Trait>>,
}
thread_local! {
static CHEAP: Cheap = Cheap {
item: Rc::new(Box::new(Expensive {
id: 4
}))
}
}
fn trait_item() -> Rc<Box<dyn Trait>> {
CHEAP.with(|c| c.item.clone())
}
但现在 clippy 抱怨:
warning: usage of `Rc<Box<T>>`
--> src/main.rs:41:15
|
41 | pub item: Rc<Box<dyn Trait>>,
| ^^^^^^^^^^^^^^^^^^ help: try: `Box<dyn Trait>`
|
= note: `#[warn(clippy::redundant_allocation)]` on by default
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
warning: usage of `Rc<Box<T>>`
--> src/main.rs:53:20
|
53 | fn trait_item() -> Rc<Box<dyn Trait>> {
| ^^^^^^^^^^^^^^^^^^ help: try: `Box<dyn Trait>`
|
= help: for further information visit https://rust-lang.github.io/rust-clippy/master/index.html#redundant_allocation
warning: 2 warnings emitted
我是不是遗漏了什么,或者实际上不可能按照 clippy 的建议去做?
您也可以将特征对象包装在 Rc
中,因为 Rc
也是一个指针。
因此,如果你有 Rc<Box<T>>
,你有两个分配:一个用于 T
,一个用于 Box
(另一个指针,现在在堆上)。相反,使用 Rc<dyn MyTrait>
只有一个分配。