rust编译器如何生成;不可变借阅发生在此处;?

rust编译器如何生成;不可变借阅发生在此处;?,rust,Rust,我正在学习Rust,下面的代码来自在线书籍《Rust编程语言》: 编译程序如下所示: |让单词=第一个单词(&s); |--此处发生不可变借用 所以我认为“不可变借用发生在这里”指的是&s,而不是“let word”。 但如果我改变 let word = first_word(&s); 到 编译器错误消失。 所以我觉得“不可变借用发生在这里”是指“let word”,而不是&s 如果第一个单词的返回值仅取决于另一个字符串(这意味着第一个单词根本不取决于&s),如下所示: fn fir

我正在学习Rust,下面的代码来自在线书籍《Rust编程语言》:

编译程序如下所示:

|让单词=第一个单词(&s);
|--此处发生不可变借用
所以我认为“不可变借用发生在这里”指的是
&s
,而不是“let word”。 但如果我改变

let word = first_word(&s);

编译器错误消失。 所以我觉得“不可变借用发生在这里”是指“let word”,而不是
&s

如果
第一个单词
的返回值仅取决于另一个字符串(这意味着
第一个单词
根本不取决于
&s
),如下所示:

fn first_word(s: &String) -> &str {
    println!("the input for first word is: {}", s);

    let s1 = "hi rust";
    let bytes = s1.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s1[0..i];
        }
    }

    &s1[..]
}
编译器仍然说:

|让单词=第一个单词(&s);
|--此处发生不可变借用

我对编译器生成“此处发生不可变借用”的实际操作感到非常困惑。

您应该阅读完整错误:

error[E0502]:不能将's'作为可变项借用,因为它也是作为不可变项借用的
-->src/main.rs:18:5
|
16 | let word=第一个单词(&s);
|--此处发生不可变借用
17 | 
18 | s.clear();//错误!
|^^^^^^^^^^^^此处发生可变借用
19 | 
20 | println!(“第一个字是:{}”,字);
|----此处稍后使用的不可变借用
“不能将
s
借用为可变的,因为它也被借用为不可变的”是错误消息,其他所有内容都只是为了指出冲突借用发生的位置


如果第一个单词的返回值只依赖于另一个字符串(这意味着第一个单词根本不依赖于&s),如下所示

这是不对的。函数签名决定了生命周期。在编辑的
第一个单词中
,即使返回从静态字符串借用的
str
,实际签名(不省略寿命)如下所示

fn first_word<'a>(s: &'a String) -> &'a str {
   ...
fn第一个单词和一个str{
...

返回的
&str
绑定到
s
的生存期,而不管它来自何处。此示例仅显示如何缩短具有静态生存期的引用。由于返回值绑定到
s
的生存期,因此
s
被认为是由
word

借用的,这是否意味着回答您的问题?暂时忽略错误消息的实际内容,只关注“错误”/“无错误”。您是否理解为什么第一个代码段是错误的(错误),但如果您将
let word=first_word(&s);
更改为just
first_word(&s)
,它将变为正确的(无错误)?我完全想了解借阅检查者是如何得出结论的;但是,如果你不明白它试图保护你免受什么伤害,那么这个过程看起来就像是一堆武断的胡言乱语。(老实说,有时它还是会的。)你可以通过简单地假设借阅检查器拥有完美的信息并且总是正确的,然后尝试从这一点反向工作,看看你的代码是如何违反规则而导致未定义的行为。这种假设不是完全正确的,因为有些事情借阅检查器不理解是可以的,但是is case不是其中之一;例如,在
s.clear()
之后使用
word
确实会导致UB。Nit:第一个单词的生命周期同时表示,输出只有在
s
有效时才有效,而且
s
被借用的时间与输出的寿命一样长。这就是为什么要删除
word
“修复”问题:第一个单词的
结果立即被回收,因此借阅立即结束,可以创建新的借阅。
fn first_word(s: &String) -> &str {
    println!("the input for first word is: {}", s);

    let s1 = "hi rust";
    let bytes = s1.as_bytes();

    for (i, &item) in bytes.iter().enumerate() {
        if item == b' ' {
            return &s1[0..i];
        }
    }

    &s1[..]
}
fn first_word<'a>(s: &'a String) -> &'a str {
   ...