简体   繁体   English

在循环中构建std :: process :: Command时类型不匹配

[英]Mismatched types when building a std::process::Command in a loop

I'm new to Rust, trying to learn safe programming by working with the borrow checker. 我是Rust的新手,试图通过借用检查器来学习安全编程。 One thing I tried was to construct a std::process::Command based on input. 我尝试过的一件事是根据输入构造一个std::process::Command

If I just wanted to do what all the examples in the documentation assume I want to do and just run a command with arguments that I know at coding time, it works fine: 如果我只是想做文档中的所有示例假设我想做的事情,并且只运行一个带有我在编码时知道的参数的命令,它就可以正常工作:

use std::process::Command;

fn main() {
    let mut command = Command::new("/usr/bin/x-terminal-emulator")
                              .arg("-e")
                              .arg("editor")
                              .output()
                              .unwrap();
}

I'm trying to run a command that I build at runtime. 我正在尝试运行我在运行时构建的命令。 In order to do this, I need to separate the construction of the Command struct from the building of its arguments. 为了做到这一点,我需要将Command结构的构造与其参数的构建分开。 When I do it this way, the compiler complains about mismatched types: 当我这样做时,编译器抱怨不匹配的类型:

use std::env::args;
use std::process::Command;

fn main() {
    let args = args().collect::<Vec<_>>();
    let mut command = Command::new("/usr/bin/x-terminal-emulator");

    for arg in &args[1..args.len()] {
        command = command.arg(arg);
    }
}

The error I get is 我得到的错误是

mismatched types: expected std::process::Command , found &mut std::process::Command 不匹配的类型:期望的std::process::Command ,found &mut std::process::Command

Looking at the documentation for std::process::Command::arg , it says that it expects a &mut self and returns a &mut Command . 查看std::process::Command::arg的文档,它说它需要一个&mut self并返回一个&mut Command According to the compiler, that's exactly what it's getting. 据编译器说,这正是它所得到的。 Is the documentation wrong, or (far more likely) am I misunderstanding something here? 文档是错误的,还是(更有可能)我在这里误解了什么?

If we check out the full error provided by the compiler, that may help shed light: 如果我们检查编译器提供的完整错误,这可能有助于解决问题:

error: mismatched types:
 expected `std::process::Command`,
    found `&mut std::process::Command`
(expected struct `std::process::Command`,
    found &-ptr) [E0308]

command = command.arg(arg);
          ^~~~~~~~~~~~~~~~

The compiler is pointing to the entire right hand side of the expression. 编译器指向表达式的整个右侧。 This indicates that something is wrong with the return value of the arg call. 这表明arg调用的返回值有问题。 Let's check out the documentation for arg : 我们来看看arg文档

fn arg<S: AsRef<OsStr>>(&mut self, arg: S) -> &mut Command

So, arg operates on a mutable reference to self , accepts an arg parameter, and returns a mutable reference to itself. 因此, argself进行可变引用,接受arg参数,并返回对自身的可变引用。 Let's change your code a bit to test our hypothesis. 让我们改变你的代码来测试我们的假设。 We will use a trick to make the compiler tell us the types of variables : 我们将使用一个技巧让编译器告诉我们变量的类型

for arg in &args[1..args.len()] {
    let _: () = command;
    let _: () = command.arg(arg);
}

This yields the errors: 这会产生错误:

error: mismatched types:
 expected `()`,
    found `std::process::Command`

let _: () = command;
            ^~~~~~~

error: mismatched types:
 expected `()`,
    found `&mut std::process::Command`

let _: () = command.arg(arg);
            ^~~~~~~~~~~~~~~~

Hah, we got it! 哈,我们明白了! We are trying to store a &mut Command into a variable of type Command . 我们正尝试将存储&mut Command为类型的变量Command Not gonna work! 不会工作! Since this instance of the builder pattern mutates the builder, we don't have to do anything special to preserve it: 由于构建器模式的这个实例会改变构建器,因此我们不必执行任何特殊操作来保留它:

use std::env;
use std::process::Command;

fn main() {
    let mut command = Command::new("/usr/bin/x-terminal-emulator");

    for arg in env::args().skip(1) {
        command.arg(arg);
    }
}

There is another style of the builder pattern that accepts self by value and the returns it by value. 还有另一种构建器模式样式,它按值接受self并按值返回它。 In that case, you would have to keep track of the builder between each step, and your code would have worked as-is. 在这种情况下,你必须跟踪每个步骤之间的建设者,和你的代码会工作原样。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM