rust 无法为结构方法返回引用局部变量(当前函数拥有的数据)的值

oxf4rvwz  于 2023-08-05  发布在  其他
关注(0)|答案(2)|浏览(182)

该方法返回从借用的字符串转换的路径。但是我不能返回值,因为它的引用,似乎不能改变这一点。
下面是结构的impl代码段。我用的版本也是2021年的

注意:重新创建此错误的完整代码片段位于此正文的最底部

pub fn path(&self) -> &'a path::Path {
      let string = self
        .additional
        .get(&DataHashMap::DataPath::ROOT_PATH.to_string())
        .unwrap()
        .clone();

      string.to_owned().push_str(self.data);

      return path::Path::new(&string);
    }

字符串
我得到的错误如下

error[E0515]: cannot return value referencing local variable `string`
   --> src\data.rs:484:14
    |
484 |       return path::Path::new(&string);
    |              ^^^^^^^^^^^^^^^^-------^
    |              |               |
    |              |               `string` is borrowed here
    |              returns a value referencing data owned by the current function


我尝试解引用该值,无论我是否正确,但它不起作用。我也不完全理解解引用。

pub fn path(&self) -> &'a path::Path {
      let string = self
        .additional
        .get(&DataHashMap::DataPath::ROOT_PATH.to_string())
        .unwrap()
        .clone();

      string.to_owned().push_str(self.data);
      let output_string = (*string.to_string()).to_string();

      return path::Path::new(&output_string);
    }


我尝试使用一个普通的借用字符串,没有得到一个错误

pub fn path(&self) -> &'a path::Path {
      let test = "lib.rs";

      return path::Path::new(test);
    }


然而,如果我将借用的字符串设置为String,并在返回时借用它,那么我再次得到错误。我还是不明白为什么会发生这种情况,我试着使用一个普通的借用字符串,没有得到错误

pub fn path(&self) -> &'a path::Path {
      let test = "lib.rs".to_string();

      return path::Path::new(&test);
        
  }


重新创建错误的代码:

mod TestProgramDataCreation {
  use std::{collections::HashMap, marker::PhantomData, path};

  // naming scheme for the keys in the hashmap
  mod TestDataHashMap {
    pub mod TestDataPath {
      pub const ROOT_PATH: &str = "data_path__root_path";
    }
  }

  pub struct Data;

  pub struct TestDataPath;

  pub struct TestProgramData<'a, T> {
    _phantom: PhantomData<T>,
    data: &'a str,
    additional: HashMap<String, String>,
  }

  impl<'a, T> TestProgramData<'a, T> {
    pub fn new(data: &'a str) -> Self {
      TestProgramData::<T> {
        _phantom: PhantomData::default(),
        data,
        additional: HashMap::new(),
      }
    }

    pub fn value(&self) -> &str {
      self.data
    }
  }

  impl<'a, TestDataPath> TestProgramData<'a, TestDataPath> {
    // get the "full" path of the of the directory or file name stored in data field
    pub fn new_path(data: &'a str, root_path: &'a str) -> Self {
      // add root path to hashmap
      let mut additional_hashmap = HashMap::new();
      additional_hashmap.insert(
        TestDataHashMap::TestDataPath::ROOT_PATH.to_string(),
        root_path.to_string(),
      );

      TestProgramData::<TestDataPath> {
        _phantom: PhantomData::default(),
        data,
        additional: additional_hashmap,
      }
    }

    pub fn path(&self) -> &'a path::Path {
      let string = self
        .additional
        .get(&TestDataHashMap::TestDataPath::ROOT_PATH.to_string())
        .unwrap()
        .clone();

      string.to_owned().push_str(self.data);

      return path::Path::new(&string);
    }
  }
}

mod ErrorRecreation {
    // file is called stackoverflow.rs for the purpose of the question
  use crate::stackoverflow::TestProgramDataCreation::TestDataPath;

  use super::TestProgramDataCreation::TestProgramData;

  fn main() {
    let test_root = "./";
    let test: TestProgramData<TestDataPath> =
      TestProgramData::<TestDataPath>::new_path("something", test_root);

    println!("test to recreate error: {:?}", test.path())
  }
}

wpcxdonn

wpcxdonn1#

你的代码中有很多错误。
首先,您的string.to_owned.push_str(self.data)行是一个空操作。使用to_owned调用复制字符串,将self.data中的字符添加到副本中,然后删除副本。我假设您希望返回string,并将self.data追加到末尾;这个方法不行。要解决这个问题,请使用let mut声明string,然后直接调用string.push_str
第二,返回一个&’a Path。这意味着您返回的路径必须与*self.data一样长。但是,实际返回的路径的生命周期与string的生命周期相关联,string的生命周期在函数返回时结束,因此太短了。
要解决这个问题,您应该返回一个PathBuf。您可以使用PathBuf::fromString转换为PathBuf

pub fn path(&self) -> path::PathBuf {
      let mut string: String = self
        .additional
        .get(&DataHashMap::DataPath::ROOT_PATH.to_string())
        .unwrap()
        .clone();
   
      string.push_str(self.data);

      path::PathBuf::from(string)
   }

字符串

wdebmtf2

wdebmtf22#

从path::Path::new:

pub fn new<S: AsRef<OsStr> + ?Sized>(s: &S) -> &Path {
    unsafe { &*(s.as_ref() as *const OsStr as *const Path) }
}

字符串
Path::new借用string并返回Path。返回的Path的生存期受string的生存期限制(在函数结束时删除)。
在这种情况下:

pub fn path(&self) -> &'a path::Path {
      let test = "lib.rs";

      return path::Path::new(test);
}


test的寿命为'static。因此,您可以在此处返回&Path

相关问题