66471


フィボナッチ数を計算するコードを書きました。  
次のコードは rustc 1.41.1 ではコンパイルが通りますが1.35.0ではエラーになります。  
vecの要素はi32なのでindexアクセスをした際にcopyが行われ、借用は行われないと思うのですがどういう理由によるのでしょうか？また、どのように解決すればよいでしょうか？

[code]

    fn main() {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).ok();
        let n: usize = s.trim().parse().unwrap();
    
        let mut fib = vec![1,1];
        for i in 0..n-1{
            fib.push(fib[i]+fib[i+1]);
        }
        let ans = fib.last().unwrap();
        println!("{}", ans);
    }
    
[/code]

error文  
[![error内容](https://i.stack.imgur.com/eUhxH.png)](https://i.stack.imgur.com/eUhxH.png)


CC BY-SA 4.0
2020-05-09T18:04:07.333
66470
2020-05-09T22:57:44.480
20533
question
rust
rustにてmutableなvecに自身の要素を追加しようとするとコンパイラのバージョンによっては借用errorになる


エラーの理由は、Indexアクセスを行う時に所有権の借用が行われるからです。  
質問者さんのコードを例に記述いたしますと

1.「.push(」でmutable参照の借用が開始され  
2.「fib[]」でimmutable参照の借用が開始され(Indexトレイト)  
3.「);」でfib借用のライフタイムが終了

という流れになります。  
恐らく察しが付いたと思いますが  
これはRustの借用ルール(mutableとimmutableは同時に複数持てない)に違反するのでエラーになります。

そして本題、Rust1.41.1でエラーにならない件についてですが  
Rust1.36.0から「Non-Lexical Lifetimes」という機能がデフォルト有効になりました  
[What are non-lexical
lifetimes?](https://stackoverflow.com/questions/50251487/what-are-non-lexical-
lifetimes)

fib.push(fib[i]+fib[i+1]);という式において、参照が同時に使われる事が無いのは人の目で見て明確です  
その事をコンパイラが認識できるようになり(適切なタイミングで借用を行う)  
コンパイルが通るようになります

【解決策について】  
1.ソースコードの変更  
色々な解決方法があると思いますが  
以下のように式を分離してしまうのが一番簡単かと(個人的には)思います

[code]

    fn main() {
        let mut s = String::new();
        std::io::stdin().read_line(&mut s).ok();
        let n: usize = s.trim().parse().unwrap();
    
        let mut fib = vec![1,1];
    
        for i in 0..n-1{
            let val = fib[i] + fib[i+1];
            fib.push(val);
        }
        let ans = fib.last().unwrap();
        println!("{}", ans);
    }
    
[/code]

2.Rust2018へ変更する  
上記の海外stackoverflow回答にもある通り  
cargoを利用しcargo.tomlへ以下のように記載します

[code]

    [package]
    name = "foo"
    version = "0.0.1"
    authors = ["An Devloper <an.devloper@example.com>"]
    edition = "2018"
    
[/code]

Rust2018については以下の記事を参照下さい  
[What is Rust 2018?](https://blog.rust-lang.org/2018/07/27/what-is-
rust-2018.html)  
[Rust 2018のリリース前情報](https://qiita.com/garkimasera/items/1bc973eae60fe0c10210)

ただし、各記事でも述べられています通り  
C++で言うC++11みたいな物なので副作用が有るかもしれません


CC BY-SA 4.0
2020-05-09T20:51:06.790
66471
2020-05-09T22:57:44.480
2020-05-09T22:57:44.480
24599
24599
66470
answer