Как определить время жизни для привязки Fn, возвращающей ссылки? - PullRequest
0 голосов
/ 01 декабря 2018

Я пытаюсь создать структуру с полем, общим для F, где F реализует что-то вроде: Fn(&mut Compiler, &[Token]) -> &Token.Единственная проблема заключается в том, что я не уверен, как определить время жизни для признака Fn, который удовлетворяет ограничению, что возвращенные &Token ссылаются на данные в срезе &[Token], представленном в качестве аргумента.Все, что я пробовал, до сих пор вызывало загадочные ошибки.

Вот MVCE, который демонстрирует код (без времени жизни):

struct Compiler;
#[derive(Debug)]
struct Token(usize);

impl Compiler {
    // missing lifetime paramters here
    fn meth(&mut self, tokens: &[Token]) -> &Token {
        tokens.get(0).unwrap()
    }
}

// missing lifetime paramters here    
struct Rule<F> where F: Fn(&mut Compiler, &[Token]) -> &Token {
    func: F
}

fn main() {
    let mut c = Compiler;
    let tokens = vec![Token(0), Token(1), Token(2)];
    let r = Rule { func: Compiler::meth };
    (r.func)(&mut c, &tokens);
}

Естественно, это не скомпилируется с ошибкой:

   Compiling playground v0.0.1 (/playground)
error[E0106]: missing lifetime specifier
  --> src/main.rs:11:56
   |
11 | struct Rule<F> where F: Fn(&mut Compiler, &[Token]) -> &Token {
   |                                                        ^ expected lifetime parameter
   |
   = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from argument 1 or argument 2

У меня естьпопытался добавить спецификаторы продолжительности жизни здесь и там, перемещая вещи, но ничего не работает.Я был бы очень признателен за понимание этой проблемы.Спасибо!

1 Ответ

0 голосов
/ 01 декабря 2018

Согласно комментарию @ Stargateur, решением было добавить более высокую оценку черты к объявлению черты Fn.Предложение where for является частью синтаксиса, полностью специфического для этого варианта использования.

Нормальные границы времени жизни не работают, потому что мы не знаем, какие времена жизни будут применены к аргументам функции до времени вызова.

Итак, мы идем от этого:

struct Rule<F> where F: Fn(&mut Compiler, &[Token]) -> &Token {
    func: F
}

К этому:

struct Rule<F> where for<'a> F: Fn(&mut Compiler, &'a[Token]) -> &'a Token {
    func: F
}

Что диктует, что границы признаков, применяемые к функции F, должны удовлетворять всем потенциальным временам жизни'a во время разговора .Магия!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...