Search code examples
rustrust-obsolete

Type information of a proc() cannot be inferred if not passed into spawn()


This compiles:

use std::num::pow;

pub fn main() {
    let (tx, rx): (Sender<u64>, Receiver<u64>) = channel();
    let square_tx = tx.clone();

    let square = proc() {
        let mut x = 1u;
        loop {
            square_tx.send(pow(2u64, x));
            x += 1;
        }
    };

    let printer = proc() {
        loop { println!("Received: {}", rx.recv()); }
    };

    spawn(square);
    spawn(printer);
}

But if I comment out spawn(square), the following error is raised:

error: unable to infer enough type information about `_`; type annotations required
let square = proc() {
                    ^

What is special about spawn() such that the type information of a proc() cannot be inferred without spawning?


Solution

  • spawn takes a proc() i.e. a procedure with no arguments and return value (), so the compiler can infer that square must have that type for the program to be valid.

    The last expression in the proc is loop {}, without a break or return, so the compiler can see that the closure never returns properly. That is, it can pretend to have a return value of any type. Since the return type is unrestricted, the compiler has no way to tell which one is wanted and so complains.

    It is possible to see similar behaviour with just a plain loop {}.

    fn main() {
        let x = loop {};
    
        // code never reaches here, but these provide type inference hints
        // let y: int = x;
        // let y: () = x;
        // let y: Vec<String> = x;
    }
    
    <anon>:2:9: 2:10 error: unable to infer enough type information about `_`; type annotations required
    <anon>:2     let x = loop {};
                     ^
    

    playpen

    (The same thing happens with anything that the compiler can tell doesn't let control flow continue, e.g. let x = panic!();, let x = return;.)

    Uncommenting one of the y lines will let the program compile.