Rust «заимствованная стоимость не живет достаточно долго» при присвоении переменной stati c - PullRequest
0 голосов
/ 07 марта 2020

Моя цель - сохранить переменную stati c и переопределить значение аргументами CLI, но мне трудно найти способ сохранить копию c значения, полученного из аргументов iterator.

static mut ROOT_DIRECTORY: &str = "C:\\test\\source";

fn main() {
  let args: Vec<String> = env::args().collect();
  let mut index = 0;
  for arg in args {
    match arg.as_str() {
      "/r" => unsafe {
        if args_length <= index + 1 {
          panic!("Missing root directory value.");
        }
        ROOT_DIRECTORY = args.get(index + 1).unwrap();
        if ROOT_DIRECTORY.is_empty() {
          panic!("Root directory value cannot be empty.")
        }
      }
    }
  }
}

Выдает следующую ошибку компиляции

error[E0597]: `args` does not live long enough
   --> src\main.rs:90:34
    |
90  |                 ROOT_DIRECTORY = args.get(index + 1).unwrap();
    |                                  ^^^^---------------
    |                                  |
    |                                  borrowed value does not live long enough
    |                                  argument requires that `args` is borrowed for `'static`
...
168 | }
    | - `args` dropped here while still borrowed

error[E0382]: borrow of moved value: `args`
  --> src\main.rs:90:34
   |
54 |     let args: Vec<String> = env::args().collect();
   |         ---- move occurs because `args` has type `std::vec::Vec<std::string::String>`, which does not implement the `Copy` trait
...
76 |     for arg in args {
   |                ----
   |                |
   |                value moved here
   |                help: consider borrowing to avoid moving into the for loop: `&args`
...
90 |                 ROOT_DIRECTORY = args.get(index + 1).unwrap();
   | 

Можно ли как-нибудь создать stati c копию значения из итератора?

1 Ответ

1 голос
/ 07 марта 2020

Вы не можете этого сделать. Переменные Stati c должны быть 'static, то есть не должны содержать не 'static времени жизни. Вот почему вы можете указать срок службы в декларации о ссылках. Ваша на самом деле эквивалентна:

static mut ROOT_DIRECTORY: &'static str = "C:\\test\\source";

А ваша args является локальной переменной, поэтому ссылка на нее не 'static.

Есть ли способ для мне создать stati c копию значения из итератора?

Самый простой вариант - присвоить переменной stati c свои данные, а не ссылаться, то есть пусть это будет String. К сожалению, конструктор stati c должен быть const, и единственный известный мне const конструктор String - String::new(). Вы можете добавить вспомогательную функцию fn get_root_directory() -> &'static str, которая считывает глобальную переменную и возвращает значение по умолчанию, если оно не установлено, но если вам это нужно, вы можете сделать следующее: c a Option<String>:

static mut ROOT_DIRECTORY: Option<String> = None;

pub fn get_root_directory() -> &'static str {
    unsafe {
        ROOT_DIRECTORY.as_deref().unwrap_or("C:\\test\\source")
    }
}

Другим вариантом может быть утечка выделенной в куче строки, чтобы сделать ее stati c. Пока вы назначаете его только один раз, утечка не должна быть проблемой. Что-то вроде:

static mut ROOT_DIRECTORY: &'static str = "default value";

fn main() {
    let x = "...".to_string();
    unsafe {
        ROOT_DIRECTORY = Box::leak(x.into_boxed_str());
    }
}
...