简体   繁体   English

Rust类型推断错误

[英]Rust Type Inference Error

I'm writing a chat server over TCP as a learning project. 我正在通过TCP编写聊天服务器作为学习项目。 I've been tinkering with the ws crate today, but I've come across an issue. 我受够了被修补WS箱子今天,但我遇到的一个问题。 This is the code I wrote, modifying their server example . 这是我编写的代码,修改了他们的服务器示例

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);
    }
}

When I try compiling it I get an error: 当我尝试编译它时,我收到一个错误:

error: the type of this value must be known in this context
  --> src/main.rs:15:23
   |
15 |             message = message.trim();
   |                       ^^^^^^^^^^^^^^

Why is this happening? 为什么会这样? How may I fix this? 我该如何解决这个问题?

move |message| shadows the message variable you've declared outside the closure. 隐藏您在闭包之外声明的message变量。 So within the closure.. message is said to be a ws::Message ... except you've done this: 所以在封闭.. message据说是一个ws::Message ...除了你这样做:

message = message.trim();

The compiler goes "oh no! trim() ? That doesn't exist for ws::Message ".. and so now it doesn't quite know what to do. 编译器会“哦不! trim() ?这对于ws::Message ”来说是不存在的......所以现在它不知道该怎么做。

Option 1 选项1

The first fix involves delegating the trim() call to the client who sends the message. 第一个修复涉及将trim()调用委托给发送消息的客户端。

The fix is to not make any assumptions about what the message is inside this closure. 修复是不对此闭包内的消息做出任何假设。 If you keep this: 如果你保留这个:

move |message|

..but remove the trim() call, the compiler happily infers its type as ws::Message and will build: ..但删除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)
    }
}

This gives you the option of delegating the trim() call to the client instead. 这使您可以选择将trim()调用委托给客户端。

Option 2 选项2

Option 2 involves inspecting the type of message you've received, and making sure you trim it only if it is text: 选项2涉及检查您收到的消息类型,并确保仅在文本时修剪它:

// 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)
}

This is perhaps a little more verbose than it needs to be.. but hopefully it shows you what the actual issue is with your original snippet of code. 这可能比它需要的更冗长......但希望它能告诉你原始代码片段的实际问题。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM