Rust中互相持有引用的泛型结构体循环依赖如何解决
报错原因
你遇到的是循环类型别名展开问题:Rust 中类型别名只是现有类型的同义词,编译器在计算类型大小时需要完全展开别名。你当前的定义Layer2 = SimpleLayer2<Layer3>、Layer3 = SimpleLayer3<SimpleLayer2<Layer3>>形成了无限递归的展开链,编译器无法终止计算,因此抛出错误。
解决方案
方案1:直接去掉泛型,定义互持指针的结构体
因为InternalRef本质是指针类型,大小固定(和原生指针一致),两个结构体直接互相持有对方的InternalRef是合法的,编译器可以正常计算大小:
use d2simrs::util::internalref::InternalRef; // 调整trait方法带&self,方便后续实现调用 pub trait Layer3Trait { fn foo(&self) { println!("TraitA::foo()"); } } pub trait Layer2Trait { fn bar(&self) { println!("TraitB::foo()"); } } // 直接定义结构体,互相持有对方的InternalRef pub struct SimpleLayer2 { pub layer3: InternalRef<SimpleLayer3>, } pub struct SimpleLayer3 { pub layer2: InternalRef<SimpleLayer2>, } // 为结构体实现对应trait impl Layer3Trait for SimpleLayer3 {} impl Layer2Trait for SimpleLayer2 {} pub type Layer2Ref = InternalRef<SimpleLayer2>; pub type Layer3Ref = InternalRef<SimpleLayer3>;
方案2:保留泛型,用Trait对象打破循环
如果你需要保留泛型的灵活性,支持后续替换不同的Layer实现,可以用dyn Trait作为泛型参数填充,dyn Trait是独立的动态大小类型,不需要依赖具体实现的类型定义,不会形成循环:
use d2simrs::util::internalref::InternalRef; // trait需要是对象安全,方法必须带&self pub trait Layer3Trait { fn foo(&self) { println!("TraitA::foo()"); } } pub trait Layer2Trait { fn bar(&self) { println!("TraitB::foo()"); } } // 泛型约束加?Sized,允许接收动态大小的dyn Trait pub struct SimpleLayer2<Layer3T: Layer3Trait + ?Sized> { pub layer3: InternalRef<Layer3T>, } pub struct SimpleLayer3<Layer2T: Layer2Trait + ?Sized> { pub layer2: InternalRef<Layer2T>, } // 用dyn Trait填充泛型参数,打破循环 pub type Layer2 = SimpleLayer2<dyn Layer3Trait>; pub type Layer3 = SimpleLayer3<dyn Layer2Trait>; pub type Layer2Ref = InternalRef<Layer2>; pub type Layer3Ref = InternalRef<Layer3>;
注意事项
如果使用trait对象方案,必须保证trait是对象安全的:不能有没有&self/&mut self/self参数的关联方法,不能包含泛型方法等。
内容的提问来源于stack exchange,提问作者Effie
相关产品推荐
相关产品推荐

