BitAnd for specific type is `const` but not for generic type `T`?

Hi there,

I'm wondering why the BitAnd (&) operation for specifc types e.g. u32 is a const operation, while it is not for a generic type T ?

Example:

use std::ops::BitAnd;

trait Num: BitAnd<Self> + Sized {}

impl Num for u64{}

#[derive(Debug)]
struct Foo<T>(T);

/*impl<T: Num + BitAnd<Output = T>> Foo<T> {
  // this const throws compier error:  calls in constant functions are limited to constant functions, tuple structs and tuple variants
  const fn new(v: T, m: T) -> Self {
      Self(v & m)
  }
}*/

impl Foo<u32> {
// this const compiles just fine
  const fn new(v: u32, m: u32) -> Self {
      Self(v & m)
  }
}

Is there a way to make the & operator on a generic T a const operation? Doing some trait bound thingies? My T in the original code is already heavily constraint with trait bounds covered by a master Trait which is only implemented for u8, u16, u32 and u64.

I know I could generate specific implementation using a proc-macro but I'm wondering if there is a way to keep the generics ...

Thx in advance.

The operators for primtives types being const is done using compiler magic. The trait does not require them to be const, and its possible to implement BitAnd for things that allocates, which is impossible in a const fn.

2 Likes

Hi,

thanks for the quick response. So I‘ll have to go and implement the type for concrete integer types - preferably using a proc macro.

However, what would be considered as best practice then.
Having Foo<T> as generic struct and use proc macro and trait bounds to implement it for specific integer types like u8, u16, u32 or - as the proc macro is generating the code anyway go for Foo8, Foo16, Foo32 ?

Thanks for any guidance on this.

Furthermore, there's currently no way to use trait methods in const context at all. (At least not stable, but there is an experimental ~const feature for constraints.) So the u32 example here is not actually using the BitAnd trait, rather the built-in compiler support for primitive operators. If you look at the implementation of BitAnd for u32, it's literally just self & rhs, which looks recursive if the compiler didn't handle this specially.

1 Like

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.