簡體   English   中英

為什么“ impl Trait”返回值實現“ Box時發送” <dyn Trait> `不是嗎?

[英]Why does an `impl Trait` return value implement Send while `Box<dyn Trait>` does not?

我如何在結構中存儲`impl Trait`類型變量的解決方案 建議創建一個Future trait對象。 在我的真實代碼中這樣做會產生一個錯誤,即類型不是Send ,但是工作版本和非工作版本之間的唯一區別是是否存在dyn Futuredyn Future

為什么編譯器將它們視為不同的,我該如何解決該問題?

這是問題的簡化版本:

use std::future::Future;

fn uses_impl_trait() -> impl Future<Output = i32> {
    async { 42 }
}

fn uses_trait_object() -> Box<dyn Future<Output = i32>> {
    Box::new(async { 42 })
}

fn requires_send<T: Send>(_: T) {}

fn example() {
    requires_send(uses_impl_trait()); // Works
    requires_send(uses_trait_object()); // Fails
}
error[E0277]: `dyn std::future::Future<Output = i32>` cannot be sent between threads safely
  --> src/lib.rs:15:19
   |
11 | fn requires_send<T: Send>(_: T) {}
   |    -------------    ---- required by this bound in `requires_send`
...
15 |     requires_send(uses_trait_object());
   |                   ^^^^^^^^^^^^^^^^^^^ `dyn std::future::Future<Output = i32>` cannot be sent between threads safely
   |
   = help: the trait `std::marker::Send` is not implemented for `dyn std::future::Future<Output = i32>`
   = note: required because of the requirements on the impl of `std::marker::Send` for `std::ptr::Unique<dyn std::future::Future<Output = i32>>`
   = note: required because it appears within the type `std::boxed::Box<dyn std::future::Future<Output = i32>>`

通過在Rust中的線程之間發送特征對象 ,我已經知道可以將特征對象更改為Box<dyn Future<Output = i32> + Send> ,但是為什么存在這種區別?

出於人體工程學的原因。 RFC 1522,保守的隱含特性 ,專門討論了此設計決策:

OIBIT通過抽象返回類型泄漏。 這可能會引起爭議,因為它有效地打開了一個通道,在該通道中,函數局部類型推斷的結果會影響項目級API,但由於以下原因,它被認為是值得的:

  • 人機工程學:特性對象已經存在明確需要聲明“ Send / Sync問題,並且不希望將此問題擴展到抽象返回類型。 在實踐中,如果希望最大程度地使用此功能,則大多數使用都必須為OIBITS添加顯式邊界。

  • 實際變化不大,因為這種情況在帶有私有字段的結構上已經有些存在:

    • 在這兩種情況下,對私有實施的更改都可能會更改是否實施OIBIT。
    • 在這兩種情況下,如果沒有文檔工具,OIBIT impls的存在是不可見的
    • 在這兩種情況下,您只能通過在API或板條箱的測試套件中添加顯式特征范圍來斷言OIBIT impls的存在。

實際上,首先,OIBIT的主要目的是跨越抽象障礙並提供有關類型的信息,而類型的作者不必明確選擇加入。

但是,這意味着必須以消除OIBIT impls的方式來更改具有抽象返回類型的函數,才能將其視為沉默的突破性更改,這可能是一個問題。 (如上所述, struct定義已經是這種情況。)

但是,由於使用的OIBIT的數量相對較少,因此在函數體中推斷出返回類型並推理是否會發生這種中斷已被認為是可管理的工作量。

也可以看看:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM