首页 > 解决方案 > 类型别名引入错误:“cast 要求为 `'static` 借用 `*variable*`”

问题描述

我正在开发一个 roguelike 可见性功能。我想传入一个谓词来确定瓷砖是否阻挡了视线。以下代码按预期工作:

fn compute_visible_tiles(
    x: i32,
    y: i32,
    range: i32,
    pred: &dyn Fn(i32, i32) -> bool,
) -> Vec<(i32, i32)> {
    let mut visible: Vec<(i32, i32)> = Vec::new();
    let mut pos_x = x;
    let pos_y = y;

    while pred(pos_x, pos_y) && manhattan_dist(x, y, pos_x, pos_y) < range {
        visible.push((pos_x, pos_y));

        // generate new position to check
        pos_x += 1;
    }

    visible
}

pub fn run() {
    let map = new_square_map();

    let tiles = compute_visible_tiles(2, 3, 2, &|x, y| !map.is_blocking(x, y));
    println!("num tiles visible: {:?}", tiles.len());
}

但是,函数签名有点难看,所以我想为谓词引入一个类型别名,XYPredicate。但是这样做会引入错误。

type XYPredicate = dyn Fn(i32, i32) -> bool;

fn compute_visible_tiles(
    x: i32,
    y: i32,
    range: i32,
    pred: &XYPredicate,
) -> Vec<(i32, i32)> {
    let mut visible: Vec<(i32, i32)> = Vec::new();
    let mut pos_x = x;
    let pos_y = y;

    while pred(pos_x, pos_y) && manhattan_dist(x, y, pos_x, pos_y) < range {
        visible.push((pos_x, pos_y));

        // generate new position to check
        pos_x += 1;
    }

    visible
}

pub fn run() {
    let map = new_square_map();

    let tiles = compute_visible_tiles(2, 3, 2, &|x, y| !map.is_blocking(x, y));
    println!("num tiles visible: {:?}", tiles.len());
}


error[E0597]: `map` does not live long enough
  --> src/lib.rs:79:57
   |
79 |     let tiles = compute_visible_tiles(2, 3, 2, &|x, y| !map.is_blocking(x, y));
   |                                                ---------^^^------------------
   |                                                ||       |
   |                                                ||       borrowed value does not live long enough
   |                                                |value captured here
   |                                                cast requires that `map` is borrowed for `'static`
80 |     println!("num tiles visible: {:?}", tiles.len());
81 | }
   | - `map` dropped here while still borrowed

这是有问题的代码的游乐场链接。

有人会好心解释为什么使用类型别名会导致借用的映射超出其范围吗?为了修复这个错误,我的类型别名的正确语法是什么?

标签: rust

解决方案


这是由于终身省略。函数 case 中的默认生命周期(每个参数的唯一生命周期)与typecase ( 'static) 中的默认生命周期不同。您需要明确指出生命周期不是静态的:

type XYPredicate<'a> = dyn Fn(i32, i32) -> bool + 'a;

然后将应用正常的省略规则,并'a在函数调用中为其分配自己的生命周期。


推荐阅读