【问题标题】:Why do I get the error "expected type argument" when I annotate a type in a Rust function?当我在 Rust 函数中注释类型时,为什么会收到错误“预期类型参数”?
【发布时间】:2017-05-01 17:29:32
【问题描述】:

我正在玩 Rust 的 capnproto library。因为 Rust 在某些情况下可以推断类型,所以我可以这样做:

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

无需知道消息的类型。如果我想将message 的引用传递给函数,我现在需要知道是什么消息让函数知道会发生什么。

一般来说有没有方便的方法来做到这一点?

到目前为止,我已经完成了以下工作:

let testing: () = message;

编译器错误失败:

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

但是当我输入注释时,我的函数如下:

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

我收到如下错误:

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

错误:由于先前的错误而中止

我是来自 C++ 背景的 Rust 新手;对不起,如果这是一个菜鸟问题!

【问题讨论】:

  • 你关心类型参数是什么吗? docs.capnproto-rust.org/capnp/message/…
  • 请查看如何创建minimal reproducible example。还包括 complete 错误消息。例如,那些^^^指向重要的东西,但我们不知道是什么。
  • 来自 C++ 背景 — 您尝试传递 vector 而不是 vector<int> — 这有帮助吗?
  • @Shepmaster ^^^s 指向 capnp::message::Builder。我是否应该假设 vector 您的意思是“Builder”是一个模板并且需要进一步的输入信息?
  • edit你的问题有完整的错误信息; cmets 不提供更多信息。

标签: types rust capnproto


【解决方案1】:

Rust 不会在函数参数位置推断类型。这是设计使然,正如Rust language FAQ 所述:

为什么不推断函数签名?

在 Rust 中,声明往往带有显式类型,而实际代码具有推断类型。这种设计有几个原因:

  • 强制声明签名有助于在模块和 crate 级别加强接口稳定性。

  • 签名提高了程序员对代码的理解能力,无需 IDE 在整个 crate 上运行推理算法来猜测函数的参数类型;它始终是明确的和附近的。

  • 从机制上讲,它简化了推理算法,因为推理一次只需要查看一个函数。

由于capnp::message::Builder<A> 采用类型参数A,您需要通过给A 一个值来限定参数的类型:

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

或者让你的函数也通用,所以它可以接受任何类型A:

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

限制A

如果您选择最后一个选项,您可能需要额外的trait bounds 以允许您在函数内使用message 执行不同的操作。例如,您可能希望将message 发送到另一个线程,这需要Builder&lt;A&gt; 实现SendBuilder 具有以下 impl (reference):

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

这意味着Builder&lt;A&gt; 可以实现Send,但只有当A 实现SendAllocator 时。您可以在A 上设置您自己的绑定(要求):

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

或者(可能稍微好一点),直接将Builder&lt;A&gt;Send 绑定:

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

那么您将只能在实现SendBuilder 上调用dump_capnp_to_file

【讨论】:

  • 您能否澄清一下您所说的 A 上的界限是什么意思?
  • @JMzance 如果您修复问题中的错误消息,我会这样做。交易? ;-)
  • @JMzance 完成。这实际上不是何时使用 trait bound 的一个很好的例子,但是当我最初回答时,我无法访问 capnproto 文档来知道这一点,所以我猜它可能是可取的
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-13
  • 1970-01-01
  • 1970-01-01
  • 2021-07-30
  • 1970-01-01
  • 2023-03-09
  • 1970-01-01
相关资源
最近更新 更多