Почему компилятор не допустил ошибку при этом изменяемом заимствовании, когда в области действия остается неизменная зарезервированная ссылка на фрагмент строки? - PullRequest
0 голосов
/ 28 декабря 2018

Я изучаю Rust из Книга Rust Programming Language , доступная в No Starch Press , но столкнулась с проблемой, когда компилятор не вел себя так, как описано в книге в главе 4 оп.77.

Глава 4 книги обсуждает право собственности, а пример на с.77 похоже на это без финального println!() в main() (я также добавил комментарии и функцию из стр. 76 для создания MCVE). Я также создал игровую площадку .

fn main() {
    let mut s = String::from("Hello world!");
    let word = first_word(&s);

    // according to book, compiler should not allow this mutable borrow
    // since I'm already borrowing as immutable, but it does allow it
    s.clear();

    // but of course I do get error here about immutable borrow later being
    // used here, but shouldn't it have errored on the clear() operation before
    // it got here?
    println!("First word of s is \"{}\"", word);
}

// return string slice reference to first word in string or entire string if
// no space found
fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();

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

    &s[..]
}

Я понимаю, почему компилятор выдает ошибку там, где в данный момент это происходит.Но, насколько я понимаю из книги, это должно вызвать ошибку компилятора, когда я пытался очистить строку, потому что я не могу заимствовать s как изменяемый, потому что он также заимствован как неизменяемый, таким образом исключая возможностьошибка, которую я получил (то есть, она не должна компилироваться даже без мой последний println!()).Но он прекрасно скомпилируется для меня, пока я не пытаюсь использовать ссылку на word после операции clear().

Книга использует Rust 1.21.0 ( см. стр. 2), хотя я использую Rust 1.31.0 - так что это скорее всего изменение, внесенное в компилятор, но я пытаюсь понять почему .Почему лучше ошибаться, чем в настоящее время, по сравнению с тем, что в книге сказано, что это будет ошибкой?

Чтобы было ясно, я понимаю сами ошибки. Я пытаюсь понять, почему это не так.не выдает ошибку компилятора в том месте, в котором говорится, что книга должна это сделать (то есть, почему изменилось поведение компилятора?).

1 Ответ

0 голосов
/ 28 декабря 2018

Это изменение связано с нелексическими временами жизни , обновлением, сделанным в последних версиях Rust (стабилизировано в выпуске 2018 года, представленном в Rust 1.31, если я не ошибаюсь).

В более ранних версиях Rust (включая ту, на которой основана книга), любая ссылка должна была существовать для всей области видимости, где она была создана (то есть до конца заключительных скобок),Если вы удалите строку с помощью word и попытаетесь скомпилировать код в старой версии, она выдаст ту же ошибку - «заимствовано как изменяемое, а заимствовано как неизменяемое».

Теперь средство проверки заимствования отслеживаетссылка действительно используется.Если вы не используете word после s.clear(), предполагается, что неизменная ссылка на s может быть безопасно отброшена до того, как s.clear() станет изменяемой, так что, как вы упомянули, этот код будетбыть безопасно скомпилированным.Когда есть println!, средство проверки заимствований видит, что область неизменяемых и изменяемых заимствований пересекается, и точно говорит вам об этом - обратите внимание, что ошибка делится на три части:

  1. началонеизменный заем,
  2. начало изменяемого заимствования,
  3. использование неизменного заимствования.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...