< 返回版块

viruscamp 发表于 2026-05-26 00:30

Tags:trait impl generic

Rust named impl 草案

目的很明确,绕过 rust 的孤儿规则。
应该比参考链接的方案更好看且更完善。

概述

// struct trait 默认 impl, 与当前版本2024相同
pub struct Struct1<T>(T);
pub trait Trait1 {
    fn trait1_fn(&self);
}
impl<T> Trait1 for Struct1<T> {
    fn trait1_fn(&self) {
        println!("default impl");
    }
}

// 新增 named-impl 定义, 可在任意 crate
pub impl<T> Trait1 for Struct1<T> use ST1 {
    fn trait1_fn(&self) {
        println!("named impl ST1");
    }
}

// 类型定义, 在原本的泛型实现参数后追加 named-impl
type Struct1Generic = Struct1<i32>; // 泛型类型, 默认推导为下一行的 Struct1<i32, _ use default>
type Struct1Default = Struct1<i32, _ use default>; //具体类型, 与当前版本2024 Struct1 行为完全相同, 不使用任何 named-impl
type Struct1WithST1 = Struct1<i32, Trait1 use ST1>; //具体类型, 布局与 Struct1 相同, 作为 Trait1 时使用 ST1 的实现, 默认省略了最后的 _ use default

type ComplexType = Struct1<i64, From<i32> use Struct1Fromi32, From<_> use StructFrom, Trait1 use ST1>; // 多个 named-impl 泛型参数, trait 之间有冲突
// 作为 From<i32> 时使用 Struct1Fromi32 , 作为 From<&str> 时使用 StructFrom
// 从左到右找到第一个匹配的trait(use 前)后, 使用对应的实现

// 类型转换
let s = Struct1(1); // 默认推导为 Struct1<i32, _ use default>
let s1: &Struct1<i32, Trait1 use ST1> = &s; // 显式转换, 必须写明类型
let s2: &Struct1<i32, _ use default> = s1; // 多向互转

let s4 = Struct1(4); // 默认推导为 Struct1<i32, _ use default>
let s5: Struct1<i32, Trait1 use ST1> = s4; // move 加类型转换

let vs: Vec<Struct1<i32>> = vec![]; // 默认推导为 Vec<Struct1<i32, _ use default>>
let vs1: &Vec<Struct1<i32, Trait1 use ST1>> = &vs; // 类型定义中任意位置的 Struct1
let vs2: &Vec<Struct1<i32, _ use default>> = vs1;

// 最终使用
// 任意 T: Trait1 的 T 均可使用 Struct1<i32, _ use default> 和 Struct1<i32, Trait1 use ST1> 来类型实例化

// 1. UFCS
<Struct1<i32> as Trait1 use ST1>::trait1_fn(s5);

// 2. 泛型函数
fn use_trait1<T: Trait1>(a: &T) {
    a.trait1_fn();
}

use_trait1(s1); // default impl
use_trait1(s2); // named impl ST1

// 3. 泛型类型
pub struct Struct2<'a, T: Trait1>(&'a T);
impl Struct2<'a, T: Trait1> {
    pub fn use_inner(&self) {
        self.0.trait1_fn();
    }
}

let s21 = Struct2(s1);
s21.use_inner(); //  default impl

let s22 = Struct2(s2);
s22.use_inner(); // named impl ST1

禁止规则

Copy, Drop, Send, Sync, Unpin 等必须禁止 named-impl .

// 可供外部代码使用, 可置于 trait struct enum 等
#[disable_named_impl(all)]
pub trait Copy {}

Hash PartialOrd 等至少在有默认实现时禁止 named-impl .

// 可供外部代码使用, 可置于 trait struct enum 等
#[disable_named_impl(with_default)]
pub trait Hash {}

TBC

参考

  • https://internals.rust-lang.org/t/pre-rfc-selectable-trait-implementations/23829 最接近, 但没有名字
  • https://internals.rust-lang.org/t/looking-for-rfc-coauthors-on-named-impls/6275
  • https://internals.rust-lang.org/t/named-impls-and-impl-generics/22158
  • https://internals.rust-lang.org/t/pre-rfc-scoped-impl-trait-for-type/19923 理论最完善

评论区

写评论

还没有评论

1 共 0 条评论, 1 页