Rust技术问询:能否为超trait的关联类型添加trait约束?
在Rust Nightly中给关联类型加子trait约束(指定T必须Sized)
我需要在Rust Nightly里定义HasFooAssoc作为HasAssoc的子trait,要求它的关联类型Assoc<T>实现Foo,但得保持HasAssoc的通用性——后续还要基于它扩展HasBarAssoc这类trait,不能把Foo约束直接写死在HasAssoc里。
之前的写法碰到了两个问题:
for<T>默认会给T加上?Sized约束,但我的场景里T必须是Sized- 语法上不允许直接写
for<T: Sized>来限定类型参数
错误的实现代码如下:
#![feature(non_lifetime_binders)] trait Foo {} trait HasAssoc { type Assoc<T>; } trait HasFooAssoc: for<T> HasAssoc<Assoc<T>: Foo> {} struct X; struct Y<T>(T); impl<T> Foo for Y<T> {} impl HasAssoc for X { type Assoc<T> = Y<T>; } impl HasFooAssoc for X {}
要是直接把Foo约束硬编码进HasAssoc确实能跑,但这样就没法扩展其他trait了,不符合抽象需求:
trait Foo {} trait HasAssoc { type Assoc<T>: Foo; } struct X; struct Y<T>(T); impl<T> Foo for Y<T> {} impl HasAssoc for X { type Assoc<T> = Y<T>; }
解决办法
借助non_lifetime_binders特性,把T: Sized和Assoc<T>: Foo的约束放到where子句里,用for<T>绑定来实现。这样既能保留HasAssoc的通用性,又能在子trait里添加特定约束:
#![feature(non_lifetime_binders)] trait Foo {} trait HasAssoc { type Assoc<T>; } // 在子trait的where子句里用for<T>绑定,同时指定T:Sized和Assoc<T>:Foo trait HasFooAssoc: HasAssoc where for<T: Sized> Self::Assoc<T>: Foo, {} struct X; struct Y<T>(T); impl<T> Foo for Y<T> {} impl HasAssoc for X { type Assoc<T> = Y<T>; } // 现在能正常实现HasFooAssoc,因为Y<T>满足Foo约束,且T是Sized impl HasFooAssoc for X {}
说明
- 这种写法把
HasFooAssoc的约束拆成了两部分:先继承HasAssoc,再通过where for<T: Sized> Self::Assoc<T>: Foo明确要求所有Sized类型T对应的Assoc必须实现Foo - 既满足了抽象需求(
HasAssoc本身不带业务约束),又解决了T必须是Sized的场景要求 - 后续要加
HasBarAssoc的话,直接复制这个结构替换Foo为Bar就行,完全复用HasAssoc的定义
内容的提问来源于stack exchange,提问作者ajp
相关产品推荐
相关产品推荐

