Rust类型推断错误

6

我正在做一个以TCP为基础的聊天服务器作为我的学习项目。今天我一直在调整 ws 的代码库,但是我遇到了一个问题。这是我修改过的他们的 服务器示例 的代码。

extern crate ws;
extern crate env_logger;

use ws::listen;

fn main() {
    // Setup logging
    env_logger::init().unwrap();

    // Listen on an address and call the closure for each connection
    if let Err(error) = listen("127.0.0.1:3012", |out| {
        let mut message: String;
        // The handler needs to take ownership of out, so we use move
        move |message| {
            message = message.trim();
            // Handle messages received on this connection
            println!("Server got message '{}'. ", message);

            // Use the out channel to send messages back
            out.send(message)
        }

    }) {
        // Inform the user of failure
        println!("Failed to create WebSocket due to {:?}", error);
    }
}

当我尝试编译时,出现了错误:
error: the type of this value must be known in this context
  --> src/main.rs:15:23
   |
15 |             message = message.trim();
   |                       ^^^^^^^^^^^^^^

为什么会发生这种情况?我该如何解决?

1
将来,打印变量的类型信息是非常有用的。(https://dev59.com/xGEi5IYBdhLWcg3wCYGY) - Shepmaster
1个回答

7

move |message|会遮盖在闭包外部声明的message变量。因此,在闭包内部,message被认为是ws::Message类型...除非你这样做:

message = message.trim();

编译器会报错:"哦,不!trim()ws::Message没有这个函数"。因此,现在它不太知道该怎么做了。

选项1

第一个修复方法是将trim()调用委托给发送消息的客户端。

修复方法是不要对此闭包中的消息做任何假设。如果保留此内容:

move |message|

去掉trim()调用后,编译器会自动推断它的类型为ws::Message并构建:

if let Err(error) = listen("127.0.0.1:3012", |out| {
    // The handler needs to take ownership of out, so we use move
    move |message| {
        // --- REMOVED trim() call ---

        // Handle messages received on this connection
        println!("Server got message '{}'. ", message);

        // Use the out channel to send messages back
        out.send(message)
    }
}

这样你就可以选择将trim()调用委托给客户端。
第二个选项涉及检查您收到的消息类型,并确保仅在其为文本时修剪它:
// The handler needs to take ownership of out, so we use move
move |mut message: ws::Message| {
    // Only do it if the Message is text
    if message.is_text() {
        message = ws::Message::Text(message.as_text().unwrap().trim().into());
    }

    // Handle messages received on this connection
    println!("Server got message '{}'. ", message);

    // Use the out channel to send messages back
    out.send(message)
}

这可能比必要的更冗长,但希望它能向您展示原始代码片段的实际问题。


1
太棒了!谢谢你! - Bernardo Meurer

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接