编译器强制我实现 trait 方法,但绑定在方法上的“Self" trait 永远不会满足我的类型 [英] Compiler forces me to implement trait method but the `Self` trait bound on method is never satisfied for my type

查看:44
本文介绍了编译器强制我实现 trait 方法,但绑定在方法上的“Self" trait 永远不会满足我的类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个特性Foo.我想强制实现者定义一个方法,如果那些实现者实现了另一个特征(在这个例子中是Clone).我的想法(Playground):

I have a trait Foo. I want to force implementors to define a method, if those implementors implement another trait (Clone in this example). My idea (Playground):

trait Foo {
    // Note: in my real application, the trait has other methods as well,
    // so I can't simply add `Clone` as super trait
    fn foo(&self) 
    where 
        Self: Clone;
}

struct NoClone;
impl Foo for NoClone {}

遗憾的是,这导致:

error[E0046]: not all trait items implemented, missing: `foo`
 --> src/lib.rs:8:1
  |
2 | /     fn foo(&self) 
3 | |     where 
4 | |         Self: Clone;
  | |____________________- `foo` from trait
...
8 |   impl Foo for NoClone {}
  |   ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation

我不明白这个错误:编译器清楚地知道 NoClone 没有实现 Clone,所以为什么我需要为 foo 提供定义?特别是,如果我试图提供一个定义(游乐场):

I don't understand this error: the compiler clearly knows that NoClone does not implement Clone, so why am I required to provide a definitoin for foo? In particular, if I attempt to provide a definition (Playground):

impl Foo for NoClone {
    fn foo(&self) 
    where 
        Self: Clone
    {
        unreachable!()
    }
}

我收到错误:

error[E0277]: the trait bound `NoClone: std::clone::Clone` is not satisfied
  --> src/lib.rs:9:5
   |
9  | /     fn foo(&self) 
10 | |     where 
11 | |         Self: Clone
12 | |     {
13 | |         unreachable!()
14 | |     }
   | |_____^ the trait `std::clone::Clone` is not implemented for `NoClone`
   |
   = help: see issue #48214
   = help: add #![feature(trivial_bounds)] to the crate attributes to enable

所以编译器肯定知道.(仅供参考:使用 #![feature(trivial_bounds)] 它可以编译,但我不想定义一堆以 unreachable!() 作为主体的方法.)

So the compiler knows for sure. (FYI: with #![feature(trivial_bounds)] it compiles, but I don't want to define a bunch of methods with unreachable!() as body.)

为什么编译器强迫我提供方法定义?我能以某种方式解决这个问题吗?

推荐答案

特性的所有实现者都需要实现所有没有默认实现的方法.特性的关键在于它具有定义的接口.向方法添加特征边界不会改变此规则的任何内容.

All implementors of a trait need to implement all methods that don't have a default implementation. It's the point of a trait that it has a defined interface. Adding trait bounds to a method does not change anything about this rule.

这是语言参考所说的主题:

一个 trait 实现必须定义由实现的 trait 声明的所有非默认关联项,可以重新定义由实现的 trait 定义的默认关联项,并且不能定义任何其他项.

A trait implementation must define all non-default associated items declared by the implemented trait, may redefine default associated items defined by the implemented trait, and cannot define any other items.

这也意味着在 trait 的方法声明中绑定在 Self 上的 trait 在功能上等同于声明一个 supertrait,除了 trait 只能在声明绑定的方法中使用.

This also means that a trait bound on Self in a method declaration on a trait is functionally equivalent to declaring a supertrait, except that the trait can only be used in the method that declares the bound.

显而易见的解决方法是为对Self有额外要求的方法定义一个单独的特征:

The obvious work-around is to define a separate trait for the methods that have additional requirements on Self:

trait FooExt: Foo + Clone {
    fn foo(&self);
}

您现在可以为所有类型实现 Foo,此外还可以为 Clone 类型实现 FooExt.

You can now implement Foo for all types, and FooExt in addition for the types that are Clone.

根据评论中的要求更新:有一个 讨论是否应该允许在没有方法主体的情况下实现具有不可满足特征边界的方法的 GitHub 问题,因此至少 { unimplemted()!} 部分可以删除.截至 2019 年 4 月,此讨论尚未得出任何结论,甚至还没有确定实现不可调用方法的确切语法.

Updated as requested in the comments: There is a GitHub issue discussing whether it should be allowed to implement methods with unsatisfiable trait bounds without the method body, so at least the { unimplemted()! } part could be dropped. As of April 2019, this discussion has not come to any conclusion yet, and not even the exact syntax for implementing the uncallable methods has been settled.

这篇关于编译器强制我实现 trait 方法,但绑定在方法上的“Self" trait 永远不会满足我的类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆