为什么在每晚Rust 1.29中运行的发电机在每晚1.34.0中给出错误?

时间:2019-06-18 22:32:09

标签: rust generator

我正在使用Rust生成器,并且在每晚1.29.0下运行良好:

common_types.go:21:5: cannot use "cloud.google.com/go/pubsub".Client literal (type "cloud.google.com/go/pubsub".Client) as type SubscriptionMaker in assignment:
    "cloud.google.com/go/pubsub".Client does not implement SubscriptionMaker (wrong type for Subscription method)
        have Subscription(string) *"cloud.google.com/go/pubsub".Subscription
        want Subscription(string) Receiver

但是,每晚版本1.34.0要求将#![feature(generators, generator_trait)] use std::ops::{Generator, GeneratorState}; fn main() { let mut generator: Box<dyn Generator<Yield = u64, Return = &str>> = Box::new(move || { yield 1; return "foo"; }); unsafe { match generator.resume() { GeneratorState::Yielded(1) => { println!("Yielded"); } _ => panic!("unexpected return from resume"), } match generator.resume() { GeneratorState::Complete("foo") => { println!("Completed"); } _ => panic!("unexpected return from resume"), } } } 包装在Generator中,但是当我将Pin包装到Generator中时,该代码不再起作用

Pin

并且代码给出以下错误。

#![feature(generators, generator_trait)]

use std::ops::{Generator, GeneratorState};
use std::pin::Pin;

fn main() {
    let mut generator: Box<dyn Generator<Yield = u64, Return = &str>> = Box::new(move || {
        yield 1;
        return "foo";
    });

    match Pin::new(&mut generator).resume() {
        GeneratorState::Yielded(1) => {
            println!("Yielded");
        }
        _ => panic!("unexpected return from resume"),
    }
    match Pin::new(&mut generator).resume() {
        GeneratorState::Complete("foo") => {
            println!("Completed");
        }
        _ => panic!("unexpected return from resume"),
    }
}

当我删除生成器的类型时,它可以正常工作:

error[E0599]: no method named `resume` found for type `std::pin::Pin<&mut std::boxed::Box<dyn std::ops::Generator<Yield = u64, Return = &str>>>` in the current scope
  --> src/main.rs:12:36
   |
12 |     match Pin::new(&mut generator).resume() {
   |                                    ^^^^^^
   |
   = note: the method `resume` exists but the following trait bounds were not satisfied:
           `std::boxed::Box<dyn std::ops::Generator<Yield = u64, Return = &str>> : std::ops::Generator`

我有几个问题:

  • 为什么在最新版本中将let mut generator = Box::new(move || { yield 1; return "foo" }); 包裹在Generator中会导致错误?
  • Pin用于生成器有什么用(因为它防止指针的值被移动),我不理解PinPin之间的关系?
  • 为什么我们删除Generator变量的类型时代码为什么起作用?
  • 为什么generator方法不再resume

1 个答案:

答案 0 :(得分:4)

  

为什么在每晚Rust 1.29中运行的生成器代码在每晚1.34.0中给出错误?

因为这是一个每晚不稳定功能,随时可能会更改,因此也会更改。

另请参阅:

  

为什么在最新版本中将Generator包裹在Pin中会导致错误?

错误消息指出,Box<dyn Generator<Yield = u64, Return = &str>>没有实现Generator

另请参阅:

  

为生成器使用Pin有什么用?

     

为什么resume方法不再不安全?

resume方法是不安全的,因为如果生成器具有自引用变量并且在两次调用resume之间移动了它,则可能会引入内存不安全性。 Pin阻止移动,从而消除了不安全因素。这是将不安全逻辑包装在仅公开安全接口的API中的经典示例。

另请参阅:

  

当我们删除生成器变量的类型时,为什么代码会起作用?

因为它不再是特征对象(Box<dyn Generator>),而只是装箱的混凝土生成器。

另请参阅:


我会这样写

#![feature(generators, generator_trait)]

use std::ops::{Generator, GeneratorState};

fn main() {
    let mut generator = Box::pin(move || {
        yield 1;
        "foo"
    });

    match generator.as_mut().resume() {
        GeneratorState::Yielded(1) => println!("Yielded"),
        _ => panic!("unexpected return from resume"),
    }
    match generator.as_mut().resume() {
        GeneratorState::Complete("foo") => println!("Completed"),
        _ => panic!("unexpected return from resume"),
    }
}