ciniml / rust-dap

CMSIS-DAP Rust implementation
Apache License 2.0
88 stars 10 forks source link

トレイトの汎用実装を異なるトレイト境界に対して持つ方法 #49

Open ciniml opened 1 year ago

ciniml commented 1 year ago

現状、rust-dapのトレイトのうち、 BitBangSwdIoPrimitiveSwdIo は上位のトレイトの汎用の実装を持っている。

trait CmsisDapCommandInner {}
trait PrimitiveSwdIo {}
trait BitBangSwdIo {}

struct SwdIoSet {}
impl BitBangSwdIo for SwdIoSet {}
impl<Io: BitBangSwdIo> PrimitiveSwdIo for Io {}
impl<Io: PrimitiveSwdIo> CmsisDapCommandInner for Io {}

SWDだけだとこれでよかったが、JTAG用の型も追加すると、 CmsisDapCommandInner の汎用実装をJTAG用の型に対しても追加したくなる。

struct JtagIoSet {}
trait BitBangJtagIo {}
trait PrimitiveJtagIo {}
impl BitBangJtagIo for JtagIoSet{}
impl<io: BitBangJtagIo > PrimitiveJtagIo for Io {} 
impl<io: PrimitiveJtagIo> CmsisDapCommandInner for Io {} // Error

実際にこのような構成にすると、 PrimitiveJtagIo に対する CmsisDapCommandInner の箇所でエラーになる。

もっと単純化して、

trait C {}

trait A {}
impl<I: A> C for I {}

trait B {}
impl<I: B> C for I {}

でもエラーになる。

Compiling playground v0.0.1 (/playground)
error[[E0119]](https://doc.rust-lang.org/stable/error-index.html#E0119): conflicting implementations of trait `C`
 --> src/main.rs:7:1
  |
4 | impl<I: A> C for I {}
  | ------------------ first implementation here
...
7 | impl<I: B> C for I {}
  | ^^^^^^^^^^^^^^^^^^ conflicting implementation

For more information about this error, try `rustc --explain E0119`.
error: could not compile `playground` due to previous error
https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=1f6e1fbe833caa1a9fd5939e64363d19

これは、ジェネリクスを用いたトレイトの汎用実装は、高々一つまでしか許可されないからで、rustcのissueにも古くから上がっているようだが、現在のところ解決策は出ていない。

まあ、よくよく考えてみれば、汎用実装を提供している2つのトレイトを実装した型があった場合、どちらの実装を用いるのか解決できなくなるので当たり前のような気もする。 (C++の多重継承の問題に近い)

trait C {}

trait A {}
impl<I: A> C for I {}

trait B {}
impl<I: B> C for I {}

struct Hoge {}
impl A for Hoge {}
impl B for Hoge {}
// Hogeに対してどっちのCの実装をつかえばいい?

なので、現状のrust-dapにおける CmsisDapCommandInner の汎用実装の課題も同様であるが、どう対応すべきか悩ましい。

現状は CmsisDapCommandInner に対する汎用実装は PrimitiveSwdIo 実装型に対してのみ提供しており、JTAG側の型には提供していないという非対称な定義で対策をしているが、本来は対象であるべき。

なにかいい方法を考えたい。