trait A<'a>: Sized {
fn from_i(a: &'a i32) -> Self;
}
struct B<'a> {
a: &'a i32,
}
impl<'a> A<'a> for B<'a> {
fn from_i(a: &'a i32) -> Self {
B { a }
}
}
fn test<F, T>(f: F)
where
F: for<'a> Fn(T) -> i32,
T: for<'a> A<'a>,
{
let a = 1;
f(T::from_i(&a));
}
fn test1<'a>(b: B<'a>) -> i32 {
*b.a
}
fn main() {
test(test1);
}
目前test(test1) 会报错类型B实现的A trait不够general enough,我应该在test函数中添加什么约束来告诉编译器我只需要为生命周期为'a的T实现 A<'a>呢?
完整报警如下
error: implementation of `A` is not general enough
--> src\main.rs:29:5
|
29 | test(test1);
| ^^^^^^^^^^^ implementation of `A` is not general enough
|
= note: `A<'0>` would have to be implemented for the type `B<'_>`, for any lifetime `'0`...
= note: ...but `A<'1>` is actually implemented for the type `B<'1>`, for some specific lifetime `'1`
1
共 13 条评论, 1 页
评论区
写评论目标把 test 下的 F, T 中的范型的生命周期参数关联上。 目前两个 for<'a> 都是独立的生命周期参数。
学习了!不知道哪天会用得上(希望用不上~)
是啊 对新的不同的WhatYouActuallyWant,都需要一个新的OkIllGiveYouWhatYouWant,而且会导致编译器无法自动推断泛型的类型
--
👇
TinusgragLin: @yuyidegit 妙啊!是不是等价于:
@yuyidegit 妙啊!是不是等价于:
感觉是需要这种语义
用GAT可以实现,不过需要类型标注,对框架来说不太好用
我觉得楼主想要的应该是这样的语义:
test 接受这样一个类型参数 T:
存在一个生命周期 'l 满足:'l ⊆ test 函数的生命周期,使得 T: A<'l> 成立(因为楼主想要用 test 本地的 &i32 喂给 A<'a>::from_i(&'a i32) )。
我们已经有了:
而我们还缺:
你说这个? for<'a> A<'a>
这个就是 A<'a>, early-bound, 只是看起来像是 later-bound 而已
这个形式我也是刚发现可以这样写, 所以 for<'a> 无脑代表 later-bound 似乎是说错了, 但说它是 early-bound 是没问题的
@zylthinking,好像可以?:
你做不到, 这种尝试是 rust 不允许的。
for<'a> 说明了 'a 是 later-bound
B<'b> 要求 'b 是 early-bound
T: for<'a> A<'a> 要求 'a 同时满足 later-bound 与 early-bound, 这是做不到的, 等同于要求一个人即是男人, 又是女人。
@dakai-chen 这跟 https://github.com/rust-lang/rfcs/pull/3216 应该没什么关系?这个问题中 f 不是关键:
我觉得问题的关键是,我们要在 test 本地用本地的 &i32、依赖 A<'a>::from_i(&'a i32) 构建 T,用本地的 &i32 就意味着不能用 fn test<'a, T: A<'a>> {...},因为 'a 要长于 test 的生命周期,但是用 T: for<'a> A<'a> 又太泛了......
很遗憾,这种情况我也遇到过,只能等后续 rust 更新了。
我的想法是:
T: for<'a> A<'a> 这个条件在说:我的这个 T 啊,他很强,他实现了 A<'a>,而且 'a 是什么都行,是 'static 也好,是 'b, 'c, 'd 也好,他都给实现了;但是对于一个确定的 B<'a> 它只实现了 A<'a>,没有实现 A<'b>, A<'c>, A<'d>。像下面 C 这样式儿的,才能算那个超级强大的实现了所有 A<'a> 的 T:
那咱们为了接纳 B,只能放宽要求:咱们要的这个 T,他只要实现某一个 A<'a> 就行,这个 'a 是啥咱们也不知道,但它得是“某一个”,不是“任意一个”,至于是哪一个得让编译器从上下文中推断。所以咱们的 test 函数就变成了这样式儿的:
但是这也有问题:咱们这个标在函数体上的 'a,它也不是随便哪一个生命周期都行,它最短也得长于这个函数体的执行生命周期,要不然,咱们这个函数执行到一半,欸~,'a 结束了,咱们没准还在那儿用人家此时已经被销毁了的数据。刚才说“长于”,那为啥它不能等于这个函数的执行周期呢?唉!那不就是函数本地的数据了嘛! 你看咱们 test 函数中的这一部分:
这个 a,很遗憾,是个短命儿的主,函数本地变量,这函数一结束就没影儿了... 到这里我自己就只能把 test 改成这样了:
目前的 rust 还做不到,下面是我找到的有关这种情况资料。
https://github.com/tema3210/rfcs/blob/extended_hrtbs/text/3621-extended_hrtb.md
https://github.com/rust-lang/rfcs/pull/3216