无法引用 &str 的一部分,因为它的寿命不够长,即使它引用的内容确实如此
Can't reference a slice of &str because it doesn't live long enough, even though what it references does
我正在用 Rust 实现一个扫描器。我在 Scanner
结构上有一个 scan
方法,它将字符串切片作为源代码,将该字符串分解为 Vec<&str>
个 UTF-8 字符(使用板条箱 unicode_segmentation
), 然后将每个字符委托给一个 scan_token
方法来确定它的词法标记和 returns 它。
extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;
struct Scanner {
start: usize,
current: usize,
}
#[derive(Debug)]
struct Token<'src> {
lexeme: &'src [&'src str],
}
impl Scanner {
pub fn scan<'src>(&mut self, source: &'src str) -> Vec<Token<'src>> {
let mut offset = 0;
let mut tokens = Vec::new();
// break up the code into UTF8 graphemes
let chars: Vec<&str> = source.graphemes(true).collect();
while let Some(_) = chars.get(offset) {
// determine which token this grapheme represents
let token = self.scan_token(&chars);
// push it to the tokens array
tokens.push(token);
offset += 1;
}
tokens
}
pub fn scan_token<'src>(&mut self, chars: &'src [&'src str]) -> Token<'src> {
// get this lexeme as some slice of the slice of chars
let lexeme = &chars[self.start..self.current];
let token = Token { lexeme };
token
}
}
fn main() {
let mut scanner = Scanner {
start: 0,
current: 0,
};
let tokens = scanner.scan("abcd");
println!("{:?}", tokens);
}
我收到的错误是:
error[E0597]: `chars` does not live long enough
--> src/main.rs:22:42
|
22 | let token = self.scan_token(&chars);
| ^^^^^ borrowed value does not live long enough
...
28 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'src as defined on the method body at 15:17...
--> src/main.rs:15:17
|
15 | pub fn scan<'src>(&mut self, source: &'src str) -> Vec<Token<'src>> {
| ^^^^
我想我理解为什么这不起作用背后的逻辑:错误清楚地表明 chars
需要与生命周期 'src
一样长,因为 tokens
包含将引用切片到 chars
内的数据中。
我不明白的是,因为 chars
只是对一个对象的引用片段, 的生命周期为 'src
(即 source
),为什么 tokens
在 chars
被删除后不能引用此数据?我对低级编程还很陌生,我想我对引用 + 生命周期的直觉可能有点不对。
你的问题可以简化为:
pub fn scan<'a>(source: &'a str) -> Option<&'a str> {
let chars: Vec<&str> = source.split("").collect();
scan_token(&chars)
}
pub fn scan_token<'a>(chars: &'a [&'a str]) -> Option<&'a str> {
chars.last().cloned()
}
error[E0597]: `chars` does not live long enough
--> src/lib.rs:3:17
|
3 | scan_token(&chars)
| ^^^^^ borrowed value does not live long enough
4 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 1:13...
--> src/lib.rs:1:13
|
1 | pub fn scan<'a>(source: &'a str) -> Option<&'a str> {
| ^^
scan_token
函数要求对切片的引用和切片内部的引用具有 相同的 生命周期:&'a [&'a str]
。由于 Vec
的生命周期较短,因此统一生命周期必须如此。但是,向量的生命周期不足以 return 值。
删除不需要的生命周期:
pub fn scan_token<'a>(chars: &[&'a str]) -> Option<&'a str>
将这些更改应用到您的完整代码,您会看到核心问题在 Token
的定义中重复出现:
struct Token<'src> {
lexeme: &'src [&'src str],
}
这种结构绝对不可能让你的代码按原样编译——没有与切片一样长的切片向量。您的代码根本不可能采用这种形式。
您 可以 传递对 Vec
的可变引用以用作存储,但这很不寻常,并且有很多缺点你尝试做任何更大的事情:
impl Scanner {
pub fn scan<'src>(&mut self, source: &'src str, chars: &'src mut Vec<&'src str>) -> Vec<Token<'src>> {
// ...
chars.extend(source.graphemes(true));
// ...
while let Some(_) = chars.get(offset) {
// ...
let token = self.scan_token(chars);
// ...
}
// ...
}
// ...
}
fn main() {
// ...
let mut chars = Vec::new();
let tokens = scanner.scan("abcd", &mut chars);
// ...
}
您可能只想 Token
成为 Vec<&'src str>
另请参阅:
- Is there any way to return a reference to a variable created in a function?
我正在用 Rust 实现一个扫描器。我在 Scanner
结构上有一个 scan
方法,它将字符串切片作为源代码,将该字符串分解为 Vec<&str>
个 UTF-8 字符(使用板条箱 unicode_segmentation
), 然后将每个字符委托给一个 scan_token
方法来确定它的词法标记和 returns 它。
extern crate unicode_segmentation;
use unicode_segmentation::UnicodeSegmentation;
struct Scanner {
start: usize,
current: usize,
}
#[derive(Debug)]
struct Token<'src> {
lexeme: &'src [&'src str],
}
impl Scanner {
pub fn scan<'src>(&mut self, source: &'src str) -> Vec<Token<'src>> {
let mut offset = 0;
let mut tokens = Vec::new();
// break up the code into UTF8 graphemes
let chars: Vec<&str> = source.graphemes(true).collect();
while let Some(_) = chars.get(offset) {
// determine which token this grapheme represents
let token = self.scan_token(&chars);
// push it to the tokens array
tokens.push(token);
offset += 1;
}
tokens
}
pub fn scan_token<'src>(&mut self, chars: &'src [&'src str]) -> Token<'src> {
// get this lexeme as some slice of the slice of chars
let lexeme = &chars[self.start..self.current];
let token = Token { lexeme };
token
}
}
fn main() {
let mut scanner = Scanner {
start: 0,
current: 0,
};
let tokens = scanner.scan("abcd");
println!("{:?}", tokens);
}
我收到的错误是:
error[E0597]: `chars` does not live long enough
--> src/main.rs:22:42
|
22 | let token = self.scan_token(&chars);
| ^^^^^ borrowed value does not live long enough
...
28 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'src as defined on the method body at 15:17...
--> src/main.rs:15:17
|
15 | pub fn scan<'src>(&mut self, source: &'src str) -> Vec<Token<'src>> {
| ^^^^
我想我理解为什么这不起作用背后的逻辑:错误清楚地表明 chars
需要与生命周期 'src
一样长,因为 tokens
包含将引用切片到 chars
内的数据中。
我不明白的是,因为 chars
只是对一个对象的引用片段, 的生命周期为 'src
(即 source
),为什么 tokens
在 chars
被删除后不能引用此数据?我对低级编程还很陌生,我想我对引用 + 生命周期的直觉可能有点不对。
你的问题可以简化为:
pub fn scan<'a>(source: &'a str) -> Option<&'a str> {
let chars: Vec<&str> = source.split("").collect();
scan_token(&chars)
}
pub fn scan_token<'a>(chars: &'a [&'a str]) -> Option<&'a str> {
chars.last().cloned()
}
error[E0597]: `chars` does not live long enough
--> src/lib.rs:3:17
|
3 | scan_token(&chars)
| ^^^^^ borrowed value does not live long enough
4 | }
| - borrowed value only lives until here
|
note: borrowed value must be valid for the lifetime 'a as defined on the function body at 1:13...
--> src/lib.rs:1:13
|
1 | pub fn scan<'a>(source: &'a str) -> Option<&'a str> {
| ^^
scan_token
函数要求对切片的引用和切片内部的引用具有 相同的 生命周期:&'a [&'a str]
。由于 Vec
的生命周期较短,因此统一生命周期必须如此。但是,向量的生命周期不足以 return 值。
删除不需要的生命周期:
pub fn scan_token<'a>(chars: &[&'a str]) -> Option<&'a str>
将这些更改应用到您的完整代码,您会看到核心问题在 Token
的定义中重复出现:
struct Token<'src> {
lexeme: &'src [&'src str],
}
这种结构绝对不可能让你的代码按原样编译——没有与切片一样长的切片向量。您的代码根本不可能采用这种形式。
您 可以 传递对 Vec
的可变引用以用作存储,但这很不寻常,并且有很多缺点你尝试做任何更大的事情:
impl Scanner {
pub fn scan<'src>(&mut self, source: &'src str, chars: &'src mut Vec<&'src str>) -> Vec<Token<'src>> {
// ...
chars.extend(source.graphemes(true));
// ...
while let Some(_) = chars.get(offset) {
// ...
let token = self.scan_token(chars);
// ...
}
// ...
}
// ...
}
fn main() {
// ...
let mut chars = Vec::new();
let tokens = scanner.scan("abcd", &mut chars);
// ...
}
您可能只想 Token
成为 Vec<&'src str>
另请参阅:
- Is there any way to return a reference to a variable created in a function?