2014-10-08 7 views
6

Sto scrivendo un semplice motore di chat TCP per imparare Rust.errore: il tipo di questo valore deve essere noto in questo contesto

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

Il codice di cui sopra non riesce a compilare con:

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`. 

Qual è la ragione di questo?

Il tipo del valore è noto, è dichiarato nel enum come TcpStream.

Come posso risolvere questo codice?

risposta

8

Il problema è, quando si tenta di abbinare contro rx.recv(), il compilatore non conoscere il tipo di questa espressione, come si dichiarate utilizzando il generico

let (tx, rx) = channel(); 

e non ha avuto la possibilità di dedurre il tipo generico ancora.

Inoltre, poiché deve verificare che copi correttamente i motivi, non è possibile utilizzare il modello stesso per inferirne il tipo. È quindi necessario dichiararlo esplicitamente, in questo modo:

let (tx, rx) = channel::<StreamOrSlice>(); 
1

risolto questo modificando:

 match rx.recv() { 

a:

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

Sembra come se fosse solo un fallimento di inferenza di tipo.

Problemi correlati