使用`as_slice`时,“借来的价值不够长”

时间:2014-09-24 00:37:10

标签: rust

我一直在遇到问题而且我不太明白为什么不会编译这个:

fn foo(bar: &'static str) -> Foo {
  let caps_off = bar.to_ascii_lower().as_slice();
  ...
}

错误:borrowed value does not live long enough

我有点理解这里的错误,但我不知道其他任何方法来实现这一点。

我尝试将str转换为小写&然后将其转换回str类型。看似简单。

我在这里做错了什么?我该如何解决?

完整代码:

use std::collections::HashMap;
use std::ascii::StrAsciiExt;

struct Foo;

fn foo(bar: &'static str) -> Foo {
  let caps_off_ = bar.to_ascii_lower();
  let caps_off = caps_off_.as_slice();

  let mut my_foos:HashMap<&'static str, Foo> = HashMap::new();
  my_foos.insert("hi", Foo);
  *my_foos.find(&caps_off).clone().unwrap()
}

2 个答案:

答案 0 :(得分:2)

由于编译器推断出的信息,错误很难理解。

caps_off的类型是什么?您没有指定它,因此编译器必须根据其用法推断它。在这个表达式中只使用一次

*my_foos.find(&caps_off).clone().unwrap()

find method上的Map trait指定参数的类型为&K。您将地图定义为HashMap<&'static str, Foo>,因此K&'static str。因此,参数的具体类型为&&'static str。参数是&caps_off,因此您正在构建引用。编译器推断caps_off必须是&'static str类型才能匹配参数的类型。这就是问题所在。

错误告诉您caps_off_.as_slice()无法分配给caps_off,因为借用的切片活动时间不够长。这是因为bar.to_ascii_lower()返回String,并且该字符串仅在函数调用期间存在。这意味着您无法将Map.find()与此值一起使用。

幸运的是,HashMap上有另一种解决问题的方法:find_equiv。通过使用它,编译器可以推断出与您尝试分配给它的表达式(caps_off)兼容的&'a str的不同类型。只需更改foo中的最后一行即可使用它:

*my_foos.find_equiv(&caps_off).clone().unwrap()

事实上,您甚至不需要致电as_slice(),您可以直接传递String返回的bar.to_ascii_lower(),如果您不需要定义变量只使用小写字符串一次:

*my_foos.find_equiv(&bar.to_ascii_lower()).clone().unwrap()

答案 1 :(得分:0)

您应该发布完整的代码以便我们理解错误,但在该代码中,编译器无法判断新字符串的存在时间。 所以尝试:

fn foo(bar: &'static str) -> Foo {
  let caps_off_ = bar.to_ascii_lower();
  let caps_off  = caps_off_.as_slice();
  ...
}

所以caps_off_在您使用切片时保留新的String对象。

编辑:

添加到上一个答案,弗朗西斯如何解释,你宣称地图的密钥是&'static str,所以find不会接受一个没有&#39}的密钥。 t匹配相同的签名。所以你有两个选择1)将地图声明为<&str, Foo>而没有静态生命周期或2)使用find_equiv方法。

希望它有所帮助。