此代码简化了更复杂的代码以隔离问题:
use std::marker::PhantomData;
pub trait ExtWrite {
fn write_end<W>(&mut self, &mut W);
}
pub struct ST;
impl ExtWrite for ST {
fn write_end<W>(&mut self, _: &mut W) {}
}
struct MCW<'a, 'b, W: 'a, EW: 'b + ExtWrite>(&'a mut W, &'b mut [EW]);
impl<'a, 'b, W: 'a, EW: 'b + ExtWrite> MCW<'a, 'b, W, EW> {
fn write_end_all(&mut self) {
if let Some((f, last)) = self.1.split_first_mut() {
let mut el = MCW(self.0, last);
f.write_end(&mut el);
// do on current el.write_end();
}
}
}
pub fn rec_test() {
let mut buff = ();
let v: Vec<TSW<ST>> = Vec::new();
let mut el: TSW<ST> = TSW(Box::new(v), PhantomData);
el.write_end(&mut buff);
}
pub struct TSW<E: ExtWrite>(Box<Vec<TSW<E>>>, PhantomData<E>);
impl<E: ExtWrite> ExtWrite for TSW<E> {
fn write_end<W>(&mut self, w: &mut W) {
let mut el = MCW(w, &mut self.0[..]);
el.write_end_all();
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
导致以下错误:
error: reached the recursion limit while instantiating `<TSW<E> as ExtWrite><ST>::write_end::<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<MCW<(), TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>, TSW<ST>>>`
--> <anon>:40:3
|
40 | fn write_end<W>(&mut self, w: &mut W) {
| ^
Run Code Online (Sandbox Code Playgroud)
我每晚都在使用Rust(9c31d76e9 2016-10-03).
代码是一个结构,包含指向Vec同一结构类型的数组的指针.这些符号化的数组被递归地调用以在编写器中应用一些写入(W特征约束被删除,因为它与该问题无关),并且在实际代码中ExtWrite变为Writer某些情况.
有一些地方特征解析变得时髦导致类型的递归,当考虑W特征的解析中的单态时,递归似乎相当合乎逻辑.MCW,取决于递归的深度,将包含无数个可能的类型,但这实际上与MCW(原始代码中需要的)的使用有关,并且函数的W参数read_end没有链接到结构定义而是与这个函数的无限可能变化.
然而,在这个片段中,W总是()而且MCW应该永远如此MCW<(),TSW<ST>>.
我在寻找简化时遇到的类似情况:
struct IntSt<'a, W: 'a>(&'a W);
pub fn comp_err() {
let w: u8 = 0;
rec(true, &w);
}
pub struct A(bool);
fn rec<W>(b: bool, w: &W) {
if (b) {
rec(false, &IntSt(w).0);
// rec(false, w)
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
导致:
error: reached the recursion limit while instantiating `rec::<&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&u8>`
--> <anon>:14:1
|
14 | fn rec<W>(b: bool, w: &W) {
| ^
Run Code Online (Sandbox Code Playgroud)
它的行为正确,但我真的没有看到如何在我之前的案例中进行这种改变:
struct IntSt<'a, W: 'a>(&'a W);
pub fn comp_err() {
let w: u8 = 0;
rec(true, &w);
}
pub struct A(bool);
fn rec<W>(b: bool, w: &W) {
if (b) {
rec(false, IntSt(w).0);
// rec(false, w)
}
}
fn main() {}
Run Code Online (Sandbox Code Playgroud)
看起来MCW,用作临时作家的轻型结构会导致其生命周期复杂化.这只发生在递归的情况下.这似乎真的很边缘,我不知道它是更多的错误或预期的限制.我也试图使用排名更高的特质界限,但在这种情况下,我们真的在结构上工作,我的几次尝试都没有成功.
我可以简单地重新设计TSW(在我的现实情况下,我只可选指针结构包含Vec的TSW上一个级别),并引入了TSW_2没有指针Vec,但它真的会心疼(在不满意至少)作为解决方案.
- 编辑
是的,感谢Matthieu,这是正确的诊断(MCW误导了我(当测试时我删除了它并且一切运行正常,但它没有做同样的事情):
- TSW<ST>::write_end<()> (&mut sel, w : &mut ())
- MCW<(), TSW<ST>>::write_end_all(&mut self)
- (f from slipt_first mut )
TSW<ST>::write_end<MCW<(),TSW<ST>>
MCW<MCW<(),TSW<ST>, > ...
Run Code Online (Sandbox Code Playgroud)
事实上,当考虑原始问题时,类型应该完全是...... MCW <MCW <(),TSW,>叠加N次,N是向量的大小.(vec中的元素是Writers扩展,它应该应用于Vec的前一个元素(一种分层编写者)).
回想一下我记得第一个问题是链接我的W然后通过使用vec来存储它们来解决它(然后我得到了单个类型,带有迭代的多层写入),但后来我需要使用这个Vec来编写一些有效载荷. Vec和这里我应该使用相同的推理和双数组).但我这样做的方法是简单地尝试使用胖指针覆盖可选结构.这并不顺利,因为我做了类似"Option <Box <otherstructcontainingvec >>"的事情,但是包含vec的其他结构没有特性,而且在这个示例代码中类似Vec也没有特性.
所以我希望我终于得到了我的解决方案:使用Vec <TSW <E >>(我的结构包含它在实际代码中)作为特征并且有一个真正的胖指针(更优化的解决方案是双维vec(但我的用例是实际上是单一的重叠).
你有一个乒乓球在这里,没有尽头.
TSW<E>::write_end<W>(&mut self, w : &mut W)MCW<W, TSW<E>>::write_end_all(&mut self)TSW<E>::write_end<MCW<W, TCW<E>>>(&mut self, w: &mut )每个新级别的递归都会在新类型上堆积,这就是为什么错误消息中的类型如此之大.rustc编译器,而不是进入无限循环,告诉你,你可能不想实例化无数个函数.
这里你的逻辑有问题.这不是一生.
在开始递归时,您需要一个退出策略的计划:它应该以可预测的方式结束.
在泛型类型的递归的特定情况下,它应该可以预测地终止参数的运行时值.
不知道正确的逻辑应该是什么,我给你一个迭代的解决方案:
fn write_end_all(&mut self) {
for ew in self.1.iter_mut().rev() {
ew.write_end(self.0);
// do on current el.write_end();
}
}
Run Code Online (Sandbox Code Playgroud)
它更简单,不会导致尝试实例化无数个函数,并且可能不是您正在寻找的功能:)
| 归档时间: |
|
| 查看次数: |
565 次 |
| 最近记录: |