Rustc leads me down wrong path

So, I am writing the simplest function you can imagine. And hey, there's an error in it:

enum Stack<T> {
    Nil,
    Cons(T, Box<Stack<T>>)
}

fn isEmpty<T>(s: Stack<T>) -> bool {
    match s {
        Nil => true,
        _   => false,
    }    
}

Excitingly rustc tells me:

$ cargo build --verbose
Compiling stack v0.1.0 (file:///home/pmatos/Projects/okasaki-rust/chp2-persistence/stack)
Running rustc src/lib.rs --crate-name stack --crate-type lib -g --out-dir /home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug --emit=dep-info,link -L dependency=/home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug -L dependency=/home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug/deps
src/lib.rs:10:9: 10:12 warning: pattern binding Nil is named the same as one of the variants of the type Stack<T> [E0170]
src/lib.rs:10 Nil => true,
^~~
src/lib.rs:10:9: 10:12 help: run rustc --explain E0170 to see a detailed explanation
src/lib.rs:10:9: 10:12 help: if you meant to match on a variant, consider making the path in the pattern qualified: Stack<T>::Nil
src/lib.rs:11:9: 11:10 error: unreachable pattern [E0001]
src/lib.rs:11 _ => false,
^
src/lib.rs:11:9: 11:10 help: run rustc --explain E0001 to see a detailed explanation
error: aborting due to previous error
Could not compile stack.

Caused by:
Process didn't exit successfully: rustc src/lib.rs --crate-name stack --crate-type lib -g --out-dir /home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug --emit=dep-info,link -L dependency=/home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug -L dependency=/home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug/deps (exit code: 101)

So now I follow rustc advice:

enum Stack<T> {
    Nil,
    Cons(T, Box<Stack<T>>)
}

fn isEmpty<T>(s: Stack<T>) -> bool {
    match s {
        Stack<T>::Nil => true,
        _   => false,
    }    
}

But this is wrong again and now rust helps you no further. Any hints?

$ cargo build --verbose
Compiling stack v0.1.0 (file:///home/pmatos/Projects/okasaki-rust/chp2-persistence/stack)
Running rustc src/lib.rs --crate-name stack --crate-type lib -g --out-dir /home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug --emit=dep-info,link -L dependency=/home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug -L dependency=/home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug/deps
src/lib.rs:10:14: 10:15 error: expected one of =>, @, if, or |, found <
src/lib.rs:10 Stack::Nil => true,
^
Could not compile stack.

Caused by:
Process didn't exit successfully: rustc src/lib.rs --crate-name stack --crate-type lib -g --out-dir /home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug --emit=dep-info,link -L dependency=/home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug -L dependency=/home/pmatos/Projects/okasaki-rust/chp2-persistence/stack/target/debug/deps (exit code: 101)

I am a relative newbie when it comes to rust, so unfortunately I'm not sure of the underlying reasons for why this is an issue. However, the following change fixes the problem:

fn isEmpty<T>(s: Stack<T>) -> bool {
    match s {
        Stack::Nil => true,
        _ => false,
    }
}    

I assume that it doesn't like the argument type definition being part of the pattern match.

I am using rust 1.4 and got slightly different compilation errors than you (including the ones you listed). Hopefully this fixes the issue for you as well.

You don't have to add the <T> part when referring to Nil, as long as T can be inferred. Otherwise, the correct syntax is Stack::<T>::Nil. I like to think of the <T> part as a virtual sub module under Stack.

1 Like

That works. Thanks.

Stack::<T>::Nil really? That's ridiculous. Why? oh why?

And you actually not do that since you get:

$ cargo build
Compiling stack v0.1.0 (file:///home/pmatos/Projects/okasaki-rust/chp2-persistence/stack)
src/lib.rs:10:17: 10:18 error: type parameters are not allowed on this type [E0109]
src/lib.rs:10 Stack::::Nil => true,
^
src/lib.rs:10:17: 10:18 help: run rustc --explain E0109 to see a detailed explanation
error: aborting due to previous error
Could not compile stack.

1 Like

Oh, looks like my memory failed me. Stack::Nil::<T> is the way to go.

Anyway, it's a problem with the parser. It needs the extra :: to know that you are not trying to write something like this:

let T = 1;
let Stack = 2;

Stack < T

It doesn't keep track of much context, so it can't know which one of Stack<T> and Stack < T you are writing.

Thanks for the help.

Thanks for the report. Here's an issue.

1 Like