3
votes

I am playing around with Rust's capnproto library. Because Rust can infer types in some situations, I can do things like this:

let mut message = ::capnp::message::Builder::new_default();

Without having to know the type of message. If I want to pass a reference to message into a function, I now need to know what message is to let the function know what to expect.

Is there a convenient way to do this in general?

So far I have done the following:

let testing: () = message;

which fails with the compiler error:

error[E0308]: mismatched types
   --> src/main.rs:197:18
    |
197 |                 let temp: () = message;
    |                           ^^^^^^^ expected (), found struct `capnp::message::Builder`

But when I type annotate my function as follows:

fn example_fn(message: capnp::message::Builder) {...}

I get an error like:

error[E0243]: wrong number of type arguments: expected 1, found 0
  --> src/main.rs:72:32
   |
72 | fn dump_capnp_to_file(message: capnp::message::Builder, filename: &str) {
   |                                ^^^^^^^^^^^^^^^^^^^^^^^ expected 1 type argument

error: aborting due to previous error

I'm very new to Rust coming from a C++ background; sorry if this a rookie question!

1
Do you care what the type argument is? docs.capnproto-rust.org/capnp/message/…Josh Lee
Please review how to create a minimal reproducible example. Also include the complete error message. For example, those ^^^ point at something important but we can't tell what.Shepmaster
coming from a C++ background — you're trying to pass a vector instead of a vector<int> — does that help?Shepmaster
@Shepmaster the ^^^s point at capnp::message::Builder. Should I assume that by vector you mean that 'Builder' is a template and needs further typing information?JMzance
Please edit your question to have the complete error message; comments are not for additional information.Shepmaster

1 Answers

2
votes

Rust will not infer types in function parameter position. This is by design, as the Rust language FAQ states:

Why aren't function signatures inferred?

In Rust, declarations tend to come with explicit types, while actual code has its types inferred. There are several reasons for this design:

  • Mandatory declaration signatures help enforce interface stability at both the module and crate level.

  • Signatures improve code comprehension for the programmer, eliminating the need for an IDE running an inference algorithm across an entire crate to be able to guess at a function’s argument types; it’s always explicit and nearby.

  • Mechanically, it simplifies the inference algorithm, as inference only requires looking at one function at a time.

Since capnp::message::Builder<A> takes a type parameter A, you need to qualify the type of the parameter by giving A a value:

fn dump_capnp_to_file(message: capnp::message::Builder<SomeType>, filename: String) {
//                                                    ^^^^^^^^^^

or else make your function also generic so it can accept any type A:

fn dump_capnp_to_file<A>(message: capnp::message::Builder<A>, filename: String) {
//                   ^^^                                 ^^^

Putting bounds on A

If you take the last option, you might want additional trait bounds to allow you to do different things with message inside the function. For example, you might want to send message to another thread, which requires that Builder<A> implement Send. Builder has the following impl (reference):

impl <A> Send for Builder<A> where A: Send + Allocator

which means that Builder<A> can implement Send, but only when A implements Send and Allocator. You can make that your own bound (requirement) on A:

fn dump_capnp_to_file<A>(message: capnp::message::Builder<A>, filename: String)
    where A: Send + Allocator
{
    // multi-threaded code...
}

Alternatively (and maybe slightly better), bound Builder<A> with Send directly:

fn dump_capnp_to_file<A>(message: capnp::message::Builder<A>, filename: String)
    where capnp::message::Builder<A>: Send

Then you will only be able to call dump_capnp_to_file on a Builder that implements Send.