rust - win10關閉更新 - winupdatesdisabler



強制/強制結束簽名評估 (1)

以下是我正在嘗試做的一個人為的例子:

use std::boxed::Box;

#[derive(Debug)]
pub struct Foo<'a>(pub &'a str);

pub trait IntoBox {
    fn into_box<'a>(self) -> Box<Fn(Foo) -> String>;
}

impl<B> IntoBox for B where B: Fn(Foo) -> String + 'static {
    fn into_box(self) -> Box<Fn(Foo) -> String> { Box::new(self) }
}

fn direct_into_box<B: Fn(Foo) -> String + 'static>(b: B) -> Box<Fn(Foo) -> String> {
    Box::new(b)
}

fn main() {
    // Doesn't work
    let x = IntoBox::into_box(|i| format!("{:?}", i) );

    // Works
    let y = IntoBox::into_box(|i: Foo| format!("{:?}", i) );

    // Also works
    let z = direct_into_box(|i| format!("{:?}", i) );
}

如何讓我的特質impl像我的direct_into_box一樣對閉包進行相同的評估? 我會期望direct_into_box和我的特質impl以相同的方式表現。

x上的錯誤:

error[E0271]: type mismatch resolving `for<'r> <[[email protected]<anon>:20:31: 20:53] as std::ops::FnOnce<(Foo<'r>,)>>::Output == std::string::String`
  --> <anon>:20:13
   |
20 |     let x = IntoBox::into_box(|i| format!("{:?}", i) );
   |             ^^^^^^^^^^^^^^^^^ expected bound lifetime parameter , found concrete lifetime
   |
   = note: concrete lifetime that was found is lifetime '_#29r
   = note: required because of the requirements on the impl of `IntoBox` for `[[email protected]<anon>:20:31: 20:53]`
   = note: required by `IntoBox::into_box`

error[E0281]: type mismatch: the type `[[email protected]<anon>:20:31: 20:53]` implements the trait `std::ops::Fn<(_,)>`, but the trait `for<'r> std::ops::Fn<(Foo<'r>,)>` is required (expected concrete lifetime, found bound lifetime parameter )
  --> <anon>:20:13
   |
20 |     let x = IntoBox::into_box(|i| format!("{:?}", i) );
   |             ^^^^^^^^^^^^^^^^^
   |
   = note: required because of the requirements on the impl of `IntoBox` for `[[email protected]<anon>:20:31: 20:53]`
   = note: required by `IntoBox::into_box`

https://src-bin.com


Answer #1

聽起來像編譯器中的推理錯誤 。 看起來會發生的事情是編譯器你的閉包實現了一個特定的生命週期'x Fn(Foo<'x>)而不是Fn(Foo<'a>)

我們來看看是否可以通過手動定義一個結構來複製錯誤(這需要一個夜間編譯器),這樣我們可以更好地理解發生了什麼。 首先,讓我們以正確的方式定義結構:

#![feature(fn_traits)]
#![feature(unboxed_closures)]

// Foo and IntoBox unchanged

struct Func;

impl<'a> FnOnce<(Foo<'a>,)> for Func {
    type Output = String;

    extern "rust-call" fn call_once(self, args: (Foo<'a>,)) -> String {
        self.call(args)
    }
}

impl<'a> FnMut<(Foo<'a>,)> for Func {
    extern "rust-call" fn call_mut(&mut self, args: (Foo<'a>,)) -> String {
        self.call(args)
    }
}

impl<'a> Fn<(Foo<'a>,)> for Func {
    extern "rust-call" fn call(&self, (i,): (Foo<'a>,)) -> String {
        format!("{:?}", i)
    }
}

fn main() {
    let x = IntoBox::into_box(Func);
}

這個Func結構編譯得很好,就像你原來的閉包一樣。

現在,讓我們打破它:

impl FnOnce<(Foo<'static>,)> for Func {
    type Output = String;

    extern "rust-call" fn call_once(self, args: (Foo<'static>,)) -> String {
        self.call(args)
    }
}

impl FnMut<(Foo<'static>,)> for Func {
    extern "rust-call" fn call_mut(&mut self, args: (Foo<'static>,)) -> String {
        self.call(args)
    }
}

impl Fn<(Foo<'static>,)> for Func {
    extern "rust-call" fn call(&self, (i,): (Foo<'static>,)) -> String {
        format!("{:?}", i)
    }
}

我在這裡所做的是,我已經刪除了每個impl上的<'a> ,所以impls在一生中不再是泛型的,我用Foo<'static>取代了Foo<'a> <a>。 這意味著現在,只有在“閉包”的參數是Foo<'static>時才能實現這些特徵。

這無法編譯,但出現以下錯誤:

error[E0271]: type mismatch resolving `for<'r> <Func as std::ops::FnOnce<(Foo<'r>,)>>::Output == std::string::String`
  --> <anon>:51:13
   |
51 |     let x = IntoBox::into_box(Func);
   |             ^^^^^^^^^^^^^^^^^ expected bound lifetime parameter , found concrete lifetime
   |
   = note: concrete lifetime that was found is the static lifetime
   = note: required because of the requirements on the impl of `IntoBox` for `Func`
   = note: required by `IntoBox::into_box`

error[E0277]: the trait bound `for<'r> Func: std::ops::Fn<(Foo<'r>,)>` is not satisfied
  --> <anon>:51:13
   |
51 |     let x = IntoBox::into_box(Func);
   |             ^^^^^^^^^^^^^^^^^ the trait `for<'r> std::ops::Fn<(Foo<'r>,)>` is not implemented for `Func`
   |
   = help: the following implementations were found:
   = help:   <Func as std::ops::Fn<(Foo<'static>,)>>
   = note: required because of the requirements on the impl of `IntoBox` for `Func`
   = note: required by `IntoBox::into_box`

第一個錯誤是相同的,但是不像'_#29r這樣的內部名字,編譯器提到了靜態生命週期,因為這是我在這裡使用的。 我懷疑編譯器在代碼中沒有編譯的閉包的做法與我的第二套impls類似,只是不是'static ,而是一些其他具體的生命週期,我們不能在Rust中命名。 第二個錯誤是不同的,但意味著幾乎相同的事情。





rust