Mismatched type error when writing generic code
mkeeter opened this issue · 2 comments
I recently tried to make my functions more generic, taking a <D: DynasmApi + DynasmLabelApi>
instead of a VecAssembler
. To my surprise, this doesn't compile:
use dynasmrt::{dynasm, DynasmApi, DynasmLabelApi};
pub fn loopy<D: DynasmApi + DynasmLabelApi>(ops: &mut D) {
dynasm!(ops
; ->Loop:
; b >Loop
);
}
Checking dynasm-test v0.1.0 (/Users/mkeeter/code/dynasm-test)
error[E0308]: mismatched types
--> src/lib.rs:6:14
|
4 | / dynasm!(ops
5 | | ; ->Loop:
6 | | ; b >Loop // we're done!
| | ^^^^ expected associated type, found tuple
7 | | );
| |_____- arguments to this function are incorrect
|
= note: expected associated type `<<D as DynasmLabelApi>::Relocation as Relocation>::Encoding`
found tuple `(u8,)`
= help: consider constraining the associated type `<<D as DynasmLabelApi>::Relocation as Relocation>::Encoding` to `(u8,)` or calling a method that returns `<<D as DynasmLabelApi>::Relocation as Relocation>::Encoding`
= note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
note: associated function defined here
--> /Users/mkeeter/.cargo/registry/src/github.com-1ecc6299db9ec823/dynasmrt-2.0.0/src/lib.rs:250:8
|
250 | fn forward_reloc( &mut self, name: &'static str, target_offset: isize, field_offset: u8, ref_offset: u8, kind: <Self::Relocation as R...
| ^^^^^^^^^^^^^
It expands to
#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use dynasmrt::{dynasm, DynasmApi, DynasmLabelApi};
pub fn loopy<D: DynasmApi + DynasmLabelApi>(ops: &mut D) -> usize {
{
ops.global_label("Loop");
ops.extend(b"\x00\x00\x00\x14");
ops.forward_reloc("Loop", 0isize, 4u8, 4u8, (0u8,));
};
}
It seems like codegen is happy to generate kind: <Self::Relocation as Relocation>::Encoding
as a (u8,)
, but the trait bounds of DynasmApi + DynasmLabelApi
don't actually enforce that type, so we can't write this generic code.
I could add a further constraint <<D as DynasmLabelApi>::Relocation as Relocation>::Encoding: (u8,)
, but that's awfully wordy!
It likely needs some kind of bound like where D::Relocation=X64Relocation
(or where <D as DynasmLabelApi>::Relocation=X64Relocation
).
After some fighting with the compiler, the correct signature is
pub fn loopy<D: DynasmApi + DynasmLabelApi<Relocation = dynasmrt::aarch64::Aarch64Relocation>>(
ops: &mut D,
) {
Thanks!