Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why are type parameters are not allowed on this type?

Attempting to compile the following,

fn do_it() -> Result<i32, u32> {
    Result::<i32, u32>::Ok(3)
}


fn main() {
    println!("{}", do_it());
}

results in:

./result_test.rs:2:14: 2:17 error: type parameters are not allowed on this type [E0109]
./result_test.rs:2     Result::<i32, u32>::Ok(3)
                                ^~~

Why are type parameters not allowed on this type?

This is a minimal example, my real-world example is a macro trying to return the following:

match $reader.$read_func() {
    Ok(n) => Result::<$read_type, LocalReadError>::Ok(n),
    Err(err) => Result::<$read_type, LocalReadError>::Err(
        LocalReadError::from(err)
    ),
}

$read_func is a function, $read_type is the return type of that function. (If I had a programmatic way to get that, I'd do so; I don't know how, so it's an arg…); as-is, I get the above error. If I remove the specification of the generic's parameters, type inteference complains that it can't figure out the type. (Because it ends up with Result<_, LocalReadError> in one branch of the match, and Result<$read_type, _> in the other? I'm not really sure. It says:

error: unable to infer enough type information about `_`; type annotations or generic parameter binding required [E0282]
    match $reader.$read_func() {
                  ^~~~~~~~~~~~

)

Note: The question about why type parameters are not allowed is answered below. Turns out this is not the cause of the "unable to infer enough type information". (read_func is a function, in my case, I'm passing a templated function, but forgetting the template arg, which can't be inferred.)

like image 787
Thanatos Avatar asked Jul 22 '15 04:07

Thanatos


People also ask

Are static Fields of type parameters allowed?

A class's static field is a class-level variable shared by all non-static objects of the class. Hence, static fields of type parameters are not allowed.

How do you declare a type parameter?

To declare a bounded type parameter, list the type parameter's name, followed by the extends keyword, followed by its upper bound, which in this example is Number . Note that, in this context, extends is used in a general sense to mean either "extends" (as in classes) or "implements" (as in interfaces).

What does a type parameter do?

A type parameter, also known as a type variable, is an identifier that specifies a generic type name. The type parameters can be used to declare the return type and act as placeholders for the types of the arguments passed to the generic method, which are known as actual type arguments.

How many type parameters can be used in a generic class?

Multiple parameters You can also use more than one type parameter in generics in Java, you just need to pass specify another type parameter in the angle brackets separated by comma.


1 Answers

this is actually an inconsistency with enums that was discussed but not considered important enough to block 1.0.

The working syntax to specify types is Result::Ok::<i32, u32>(3).

An enum works like something between a type (that would go with the syntax you were trying to write) and a namespace (and namespaces don't accept type parameters).

To demonstrate how enums are like namespaces, you can write:

use std::result::Result::*;

fn main() {
    println!("{:?}", Ok::<i32, u32>(3));
}

This namespacing aspect is a desirable property of enums, but moving type parameters where one would intuitively think they should be would make this type of code very awkward to write.

like image 187
Paolo Falabella Avatar answered Oct 20 '22 19:10

Paolo Falabella