"expected type parameter `T`, found integer" when use generics instead of uint

I am trying to create Flags struct that can be used only for uint (u8, u16... usize).

Part of my code throw an error:

8  | impl<T: Unsigned + BitAnd<Output=T> + BitOr<Output=T> + Not<Output=T> + BitAndAssign + BitOrAssign> Flags<T> {
   |      - this type parameter
...
26 |         self.value & flag != 0
   |                              ^ expected type parameter `T`, found integer
   |
   = note: expected type parameter `T`
                        found type `{integer}`

also my IDE show an errors use of moved value (I will show a bit later the places where this happen).

This is my code:

use std::ops::{BitAnd, BitAndAssign, BitOr, BitOrAssign, Not};
use num_traits::{Unsigned};

pub struct Flags<T> {
    value: T,
}

impl<T: Unsigned + BitAnd<Output=T> + BitOr<Output=T> + Not<Output=T> + BitAndAssign + BitOrAssign> Flags<T> {
    pub fn new(init_value: T) -> Self {
        Self {
            value: init_value,
        }
    }

    pub fn set_flag(&mut self, flag: T) {
        if !self.flag_is_set(flag) {
            self.value |= flag;
        }
    }

    pub fn clear_flag(&mut self, flag: T) {
        self.value &= !flag;
    }

    pub fn flag_is_set(&mut self, flag: T) -> bool {
        self.value & flag != 0
    }
}

This is playground.

IDE highlight errors here:

pub fn set_flag(&mut self, flag: T) {
    if !self.flag_is_set(flag) {
        self.value |= flag; // use of moved value flag
    }
}

and here:

pub fn flag_is_set(&mut self, flag: T) -> bool {
    self.value & flag != 0 // cannot move self
}

Could anybody explain how to fix this ?

P.S. extra question about formatting: how to refactor so long trait list for struct ? I know for function I can use where, but not sure what about struct.

The literal 0 is an integer, but type parameter T is a generic type. It is not guaranteed to be an integer. You probably want to compare T with itself, and express that it can be constructed from a 0 value, which is num_traits::Zero.

In order to fix the "move of used value" error, you could just require that the value be Copy. But the check before setting the flag (the one that causes this error in the first place) is unnecessary anyway.

Why don't you just try where, then? (Or read the corresponding documentation in the language reference.) It works on impl blocks too.


By the way, since you are already using num_traits, you could just specify PrimInt instead of the long list of traits. All in all, your code could look like this Playground.


Also, instead of implementing bitflags yourself, try the bitflags or option_set crates.

1 Like

thank you very much for detailed explanation ! bitflags works for me