Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Full path in compiler error for bitfield 04 #55

Closed
robamu opened this issue Oct 11, 2022 · 2 comments
Closed

Full path in compiler error for bitfield 04 #55

robamu opened this issue Oct 11, 2022 · 2 comments

Comments

@robamu
Copy link

robamu commented Oct 11, 2022

I am trying to solve 04 right now. There is just a small thing left where I was wondering how this was done in the reference implementation.

My error output currently looks like this:

EXPECTED:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error[E0277]: the trait bound `bitfield::checks::SevenMod8: bitfield::checks::TotalSizeIsMultipleOfEightBits` is not satisfied
  --> tests/04-multiple-of-8bits.rs:53:1
   |
53 | #[bitfield]
   | ^^^^^^^^^^^ the trait `bitfield::checks::TotalSizeIsMultipleOfEightBits` is not implemented for `bitfield::checks::SevenMod8`
   |
   = help: the trait `bitfield::checks::TotalSizeIsMultipleOfEightBits` is implemented for `bitfield::checks::ZeroMod8`
   = note: this error originates in the attribute macro `bitfield` (in Nightly builds, run with -Z macro-backtrace for more info)
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

ACTUAL OUTPUT:
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈
error[E0277]: the trait bound `SevenMod8: TotalSizeIsMultipleOfEightsBits` is not satisfied
   --> tests/04-multiple-of-8bits.rs:53:1
    |
53  | #[bitfield]
    | ^^^^^^^^^^^ the trait `TotalSizeIsMultipleOfEightsBits` is not implemented for `SevenMod8`
    |
    = help: the trait `TotalSizeIsMultipleOfEightsBits` is implemented for `ZeroMod8`
note: required by a bound in `width_check`
   --> src/lib.rs
    |
    |     pub fn width_check<T: TotalSizeIsMultipleOfEightsBits>() {}
    |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `width_check`
    = note: this error originates in the attribute macro `bitfield` (in Nightly builds, run with -Z macro-backtrace for more info)
┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈┈

I am happy with this, but I was curious why my output does not have the full paths as the reference implementation had and what to consider to get those full paths.

Kind Regards
Robin

@dtolnay
Copy link
Owner

dtolnay commented Oct 11, 2022

Obviously either output is fine so you can replace 04-multiple-of-8bits.stderr if you like yours.

I checked and my reference implementation does past the current test, on current stable as well as nightly. According to cargo expand here is exactly what it expands to for 04-multiple-of-8bits.rs:

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use bitfield::*;
type A = B1;
type B = B3;
type C = B4;
type D = B23;
#[repr(C)]
pub struct NotQuiteFourBytes {
    data: [u8; {
        0 + <A as bitfield::Specifier>::BITS as usize
            + <B as bitfield::Specifier>::BITS as usize
            + <C as bitfield::Specifier>::BITS as usize
            + <D as bitfield::Specifier>::BITS as usize
    } / 8],
}
impl NotQuiteFourBytes {
    pub fn new() -> Self {
        let _: bitfield::MultipleOfEight<
            [(); {
                0 + <A as bitfield::Specifier>::BITS as usize
                    + <B as bitfield::Specifier>::BITS as usize
                    + <C as bitfield::Specifier>::BITS as usize
                    + <D as bitfield::Specifier>::BITS as usize
            } % 8],
        >;
        NotQuiteFourBytes {
            data: [0; {
                0 + <A as bitfield::Specifier>::BITS as usize
                    + <B as bitfield::Specifier>::BITS as usize
                    + <C as bitfield::Specifier>::BITS as usize
                    + <D as bitfield::Specifier>::BITS as usize
            } / 8],
        }
    }
}
impl NotQuiteFourBytes {
    fn get(&self, offset: usize, width: u8) -> u64 {
        let mut val = 0;
        for i in 0..(width as usize) {
            let offset = i + offset;
            let byte_index = offset / 8;
            let bit_offset = offset % 8;
            let byte = self.data[byte_index];
            let mask = 1 << bit_offset;
            if byte & mask == mask {
                val |= 1 << i;
            }
        }
        val
    }
    fn set(&mut self, offset: usize, width: u8, val: u64) {
        for i in 0..(width as usize) {
            let mask = 1 << i;
            let val_bit_is_set = val & mask == mask;
            let offset = i + offset;
            let byte_index = offset / 8;
            let bit_offset = offset % 8;
            let byte = &mut self.data[byte_index];
            let mask = 1 << bit_offset;
            if val_bit_is_set {
                *byte |= mask;
            } else {
                *byte &= !mask;
            }
        }
    }
    pub fn get_a(&self) -> <A as bitfield::Specifier>::GetterType {
        let val = self.get(0, <A as bitfield::Specifier>::BITS);
        <A as bitfield::Specifier>::from_u64(val)
    }
    pub fn set_a(&mut self, val: <A as bitfield::Specifier>::SetterType) {
        let val = <A as bitfield::Specifier>::into_u64(val);
        debug_assert!(val <= bitfield::max::<A>());
        self.set(0, <A as bitfield::Specifier>::BITS, val);
    }
    pub fn get_b(&self) -> <B as bitfield::Specifier>::GetterType {
        let val = self
            .get(
                0 + <A as bitfield::Specifier>::BITS as usize,
                <B as bitfield::Specifier>::BITS,
            );
        <B as bitfield::Specifier>::from_u64(val)
    }
    pub fn set_b(&mut self, val: <B as bitfield::Specifier>::SetterType) {
        let val = <B as bitfield::Specifier>::into_u64(val);
        debug_assert!(val <= bitfield::max::<A>());
        self.set(
            0 + <A as bitfield::Specifier>::BITS as usize,
            <B as bitfield::Specifier>::BITS,
            val,
        );
    }
    pub fn get_c(&self) -> <C as bitfield::Specifier>::GetterType {
        let val = self
            .get(
                0 + <A as bitfield::Specifier>::BITS as usize
                    + <B as bitfield::Specifier>::BITS as usize,
                <C as bitfield::Specifier>::BITS,
            );
        <C as bitfield::Specifier>::from_u64(val)
    }
    pub fn set_c(&mut self, val: <C as bitfield::Specifier>::SetterType) {
        let val = <C as bitfield::Specifier>::into_u64(val);
        debug_assert!(val <= bitfield::max::<A>());
        self.set(
            0 + <A as bitfield::Specifier>::BITS as usize
                + <B as bitfield::Specifier>::BITS as usize,
            <C as bitfield::Specifier>::BITS,
            val,
        );
    }
    pub fn get_d(&self) -> <D as bitfield::Specifier>::GetterType {
        let val = self
            .get(
                0 + <A as bitfield::Specifier>::BITS as usize
                    + <B as bitfield::Specifier>::BITS as usize
                    + <C as bitfield::Specifier>::BITS as usize,
                <D as bitfield::Specifier>::BITS,
            );
        <D as bitfield::Specifier>::from_u64(val)
    }
    pub fn set_d(&mut self, val: <D as bitfield::Specifier>::SetterType) {
        let val = <D as bitfield::Specifier>::into_u64(val);
        debug_assert!(val <= bitfield::max::<A>());
        self.set(
            0 + <A as bitfield::Specifier>::BITS as usize
                + <B as bitfield::Specifier>::BITS as usize
                + <C as bitfield::Specifier>::BITS as usize,
            <D as bitfield::Specifier>::BITS,
            val,
        );
    }
}
impl std::fmt::Debug for NotQuiteFourBytes {
    fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
        f.debug_struct("NotQuiteFourBytes")
            .field("a", &self.get_a())
            .field("b", &self.get_b())
            .field("c", &self.get_c())
            .field("d", &self.get_d())
            .finish()
    }
}
fn main() {}

@robamu
Copy link
Author

robamu commented Oct 11, 2022

Ah okay.. many segments look similar. Maybe it is something with the specific mod 8 check? This is how my expansion looks

#![feature(prelude_import)]
#[prelude_import]
use std::prelude::rust_2021::*;
#[macro_use]
extern crate std;
use bitfield::*;
type A = B1;
type B = B3;
type C = B4;
type D = B23;
#[repr(C)]
pub struct NotQuiteFourBytes {
    raw_data: [u8; (<A as Specifier>::BITS + <B as Specifier>::BITS
        + <C as Specifier>::BITS + <D as Specifier>::BITS) / 8],
}
impl NotQuiteFourBytes {
    const OFFSET_A: usize = 0;
    const OFFSET_B: usize = Self::OFFSET_A + <A as bitfield::Specifier>::BITS;
    const OFFSET_C: usize = Self::OFFSET_B + <B as bitfield::Specifier>::BITS;
    const OFFSET_D: usize = Self::OFFSET_C + <C as bitfield::Specifier>::BITS;
    const FULL_LEN_MOD_EIGHT: usize = (<A as Specifier>::BITS + <B as Specifier>::BITS
        + <C as Specifier>::BITS + <D as Specifier>::BITS) % 8;
    pub fn new() -> Self {
        bitfield::checks::width_check::<
            <bitfield::checks::NumDummy<
                { Self::FULL_LEN_MOD_EIGHT },
            > as bitfield::checks::NumToGeneric>::GENERIC,
        >();
        Self {
            raw_data: [0; (<A as Specifier>::BITS + <B as Specifier>::BITS
                + <C as Specifier>::BITS + <D as Specifier>::BITS) / 8],
        }
    }
    pub fn raw_data(&self) -> &[u8] {
        self.raw_data.as_ref()
    }
    pub fn set_a(&mut self, val: <A as bitfield::Specifier>::UTYPE) {
        <A as bitfield::Specifier>::write_to_bytes(
            val,
            Self::OFFSET_A,
            self.raw_data.as_mut(),
        );
    }
    pub fn set_b(&mut self, val: <B as bitfield::Specifier>::UTYPE) {
        <B as bitfield::Specifier>::write_to_bytes(
            val,
            Self::OFFSET_B,
            self.raw_data.as_mut(),
        );
    }
    pub fn set_c(&mut self, val: <C as bitfield::Specifier>::UTYPE) {
        <C as bitfield::Specifier>::write_to_bytes(
            val,
            Self::OFFSET_C,
            self.raw_data.as_mut(),
        );
    }
    pub fn set_d(&mut self, val: <D as bitfield::Specifier>::UTYPE) {
        <D as bitfield::Specifier>::write_to_bytes(
            val,
            Self::OFFSET_D,
            self.raw_data.as_mut(),
        );
    }
    pub fn get_a(&self) -> <A as bitfield::Specifier>::UTYPE {
        <A as bitfield::Specifier>::read_from_bytes(
            Self::OFFSET_A,
            self.raw_data.as_ref(),
        )
    }
    pub fn get_b(&self) -> <B as bitfield::Specifier>::UTYPE {
        <B as bitfield::Specifier>::read_from_bytes(
            Self::OFFSET_B,
            self.raw_data.as_ref(),
        )
    }
    pub fn get_c(&self) -> <C as bitfield::Specifier>::UTYPE {
        <C as bitfield::Specifier>::read_from_bytes(
            Self::OFFSET_C,
            self.raw_data.as_ref(),
        )
    }
    pub fn get_d(&self) -> <D as bitfield::Specifier>::UTYPE {
        <D as bitfield::Specifier>::read_from_bytes(
            Self::OFFSET_D,
            self.raw_data.as_ref(),
        )
    }
}
fn main() {}

I used an empty generic function to do the check. The bitfield::MultipleOfEight looks like magic to me, or/and I am unfamiliar with that syntax for generics. Is it a struct?

Kind Regards
Robin

@dtolnay dtolnay closed this as completed Feb 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants