Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

error: the type of this value must be known in this context

Tags:

rust

I'm writing a simple TCP chat engine to learn Rust.

use std::io::{TcpListener, TcpStream};
use std::io::{Acceptor, Listener};

enum StreamOrSlice {
     Strm(TcpStream),
     Slc(uint, [u8, ..1024])
}

fn main() {
    let listener = TcpListener::bind("127.0.0.1", 5555);

    // bind the listener to the specified address
    let mut acceptor = listener.listen();

    let (tx, rx) = channel();

    spawn(proc() {
        let mut streams: Vec<TcpStream> = Vec::new();
        match rx.recv() {
            Strm(mut stream) => {
                streams.push(stream);
            }
            Slc(len, buf) => {
                for stream in streams.iter() {
                    stream.write(buf.slice(0, len));
                }
            }
        }
    });

    // accept connections and process them, spawning a new tasks for each one
    for stream in acceptor.incoming() {
        match stream {
            Err(e) => { /* connection failed */ }
            Ok(mut stream) => {
                // connection succeeded
                tx.send(Strm(stream.clone()));
                let tx2 = tx.clone();
                spawn(proc() {
                    let mut buf: [u8, ..1024] = [0, ..1024];
                    loop {
                        let len = stream.read(buf);
                        tx2.send(Slc(len.unwrap(), buf));
                    }
                })
            }
        }
    }
}

The above code fails to compile with:

   Compiling chat v0.1.0 (file:///home/chris/rust/chat)
src/chat.rs:20:13: 20:29 error: the type of this value must be known in this context
src/chat.rs:20             Strm(mut stream) => {
                           ^~~~~~~~~~~~~~~~
error: aborting due to previous error
Could not compile `chat`.

What is the reason for this?

The type of the value is known, it's declared in the enum as TcpStream.

How can I fix this code?

like image 816
fadedbee Avatar asked Oct 08 '14 20:10

fadedbee


2 Answers

The problem is, when you try to match against rx.recv(), the compiler doesn't know the type of this expression, as you declared using the generic

let (tx, rx) = channel();

and it didn't have the possibility to infer the generic type yet.

Plus, because it has to check that you properly cover the patterns, it cannot use the pattern itself to infer the type. You thus need to declare it explicitly, like this:

let (tx, rx) = channel::<StreamOrSlice>();
like image 153
Levans Avatar answered Oct 06 '22 17:10

Levans


Fixed this by changing:

        match rx.recv() {

to:

        let rxd: StreamOrSlice = rx.recv();
        match rxd {

It looks like it's just a failure of type inference.

like image 20
fadedbee Avatar answered Oct 06 '22 16:10

fadedbee