Skip to content

Commit

Permalink
feat: #[must_use] spam
Browse files Browse the repository at this point in the history
  • Loading branch information
raklaptudirm committed Sep 8, 2024
1 parent 2394103 commit 77ae510
Show file tree
Hide file tree
Showing 8 changed files with 51 additions and 0 deletions.
12 changes: 12 additions & 0 deletions games/src/interface/bitboard.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,55 +43,65 @@ where

/// Returns `true` if `self` has no elements in `common` with other. This is
/// equivalent to checking for an empty intersection.
#[must_use]
fn is_disjoint(self, other: Self) -> bool {
(self & other).is_empty()
}

/// Returns true if the BitBoard is a subset of another, i.e., `other`
/// contains at least all the values in `self`.
#[must_use]
fn is_subset(self, other: Self) -> bool {
(other & !self).is_empty()
}

/// Returns true if the BitBoard is a superset of another, i.e., `self`
/// contains at least all the values in `other`.
#[must_use]
fn is_superset(self, other: Self) -> bool {
other.is_subset(self)
}

/// Returns `true` if the BitBoard contains no elements.
#[must_use]
fn is_empty(self) -> bool {
self == Self::EMPTY
}

/// Returns the number of elements in the BitBoard.
#[must_use]
fn len(self) -> usize {
self.into().count_ones() as usize
}

/// Returns `true` if the BitBoard contains a value.
#[must_use]
fn contains(self, square: Self::Square) -> bool {
!(self & Self::from(square)).is_empty()
}

/// north returns a new Self with all the squares shifted to the north.
#[must_use]
fn north(self) -> Self {
(self << <Self::Square as SquareType>::File::N) & Self::UNIVERSE
}

/// south returns a new Self with all the squares shifted to the south.
#[must_use]
fn south(self) -> Self {
self >> <Self::Square as SquareType>::File::N
}

/// east returns a new Self with all the squares shifted to the east.
#[must_use]
fn east(self) -> Self {
(self << 1)
& (Self::UNIVERSE
^ unsafe { Self::file(<Self::Square as SquareType>::File::unsafe_from(0u8)) })
}

/// west returns a new Self with all the squares shifted to the west.
#[must_use]
fn west(self) -> Self {
(self >> 1)
& (Self::UNIVERSE
Expand Down Expand Up @@ -130,11 +140,13 @@ where
}

/// Returns a BitBoard containing all the squares from the given `File`.
#[must_use]
fn file(file: <Self::Square as SquareType>::File) -> Self {
Self::FIRST_FILE << file.into() as usize
}

/// Returns a BitBoard containing all the squares from the given `Rank`.
#[must_use]
fn rank(rank: <Self::Square as SquareType>::Rank) -> Self {
Self::FIRST_RANK << (<Self::Square as SquareType>::File::N * rank.into() as usize)
}
Expand Down
3 changes: 3 additions & 0 deletions games/src/interface/hash.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ impl Hash {
pub const ZERO: Hash = Hash(0);

/// new creates a new Hash value from a raw u64.
#[must_use]
pub fn new(raw: u64) -> Hash {
Hash(raw)
}
}

impl From<Hash> for u64 {
#[must_use]
fn from(value: Hash) -> Self {
value.0
}
Expand All @@ -40,6 +42,7 @@ impl ops::Not for Hash {
type Output = Self;

/// Not operator (!) switches the side to move for the Hash.
#[must_use]
fn not(self) -> Self::Output {
Hash(!self.0)
}
Expand Down
11 changes: 11 additions & 0 deletions games/src/interface/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ pub trait RepresentableType<B: Into<usize>>:
/// number, i.e. the number has a valid representation in the target type.
/// The function comes with a debug check for the same, and failure to
/// uphold this invariant will result in undefined behavior.
#[must_use]
unsafe fn unsafe_from<T: Copy + Into<usize>>(number: T) -> Self {
debug_assert!(number.into() < Self::N);
std::mem::transmute_copy(&number)
Expand All @@ -69,13 +70,15 @@ macro_rules! representable_type {
}

impl From<$type> for $base {
#[must_use]
fn from(value: $type) -> Self {
value as $base
}
}

impl TryFrom<$base> for $type {
type Error = $crate::interface::TypeParseError;

fn try_from(value: $base) -> Result<Self, Self::Error> {
if value as usize >= Self::N {
Err($crate::interface::TypeParseError::RangeError(stringify!($type).to_string()))
Expand Down Expand Up @@ -189,24 +192,28 @@ macro_rules! bitboard_type {
impl std::ops::Sub<usize> for $name {
type Output = Self;

#[must_use]
fn sub(self, rhs: usize) -> Self::Output {
Self(self.0 - rhs as u64)
}
}

impl From<$typ> for $name {
#[must_use]
fn from(num: $typ) -> Self {
Self(num)
}
}

impl From<$name> for $typ {
#[must_use]
fn from(value: $name) -> Self {
value.0
}
}

impl From<$sq> for $name {
#[must_use]
fn from(square: $sq) -> Self {
Self(1 << square as u64)
}
Expand All @@ -216,6 +223,7 @@ macro_rules! bitboard_type {
type Output = Self;

/// Returns the complementary BitBoard of `self`.
#[must_use]
fn not(self) -> Self::Output {
// ! will set the unused bits so remove them with an &.
Self(!self.0) & <Self as $crate::interface::BitBoardType>::UNIVERSE
Expand All @@ -227,6 +235,7 @@ macro_rules! bitboard_type {
type Output = Self;

/// Returns the difference of `self` and `rhs` as a new BitBoard.
#[must_use]
fn sub(self, rhs: Self) -> Self::Output {
self & !rhs
}
Expand All @@ -237,6 +246,7 @@ macro_rules! bitboard_type {
type Output = Self;

/// Returns the union of `self` and `rhs` as a new BitBoard.
#[must_use]
fn bitor(self, rhs: $sq) -> Self::Output {
self | Self::from(rhs)
}
Expand All @@ -246,6 +256,7 @@ macro_rules! bitboard_type {
type Output = Self;

/// Returns the BitBoard obtained on removing `rhs` from `self`.
#[must_use]
fn sub(self, rhs: $sq) -> Self::Output {
self & !Self::from(rhs)
}
Expand Down
4 changes: 4 additions & 0 deletions games/src/interface/move.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,11 @@ pub trait MoveStore<M>: Default {
fn push(&mut self, m: M);

/// len returns the number of [Moves](MoveType) stored in the MoveStore.
#[must_use]
fn len(&self) -> usize;

/// is_empty checks if no [Moves](MoveType) are stored in the MoveStore.
#[must_use]
fn is_empty(&self) -> bool {
self.len() == 0
}
Expand All @@ -42,10 +44,12 @@ impl<M> MoveStore<M> for MoveList<M> {
self.push(m);
}

#[must_use]
fn len(&self) -> usize {
self.len()
}

#[must_use]
fn is_empty(&self) -> bool {
self.is_empty()
}
Expand Down
3 changes: 3 additions & 0 deletions games/src/interface/piece.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ where
type Color;

/// new creates a new ColoredPiece from the given Piece and Color.
#[must_use]
fn new(piece: Self::Piece, color: Self::Color) -> Self {
unsafe { Self::unsafe_from(color.into() * Self::Piece::N as u8 + piece.into()) }
}

/// piece returns the Piece part of the given ColoredPiece.
#[must_use]
fn piece(self) -> Self::Piece;
/// color returns the Color part of the given ColoredPiece.
#[must_use]
fn color(self) -> Self::Color;
}
10 changes: 10 additions & 0 deletions games/src/interface/position.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,19 +32,26 @@ where
/// remove clears the given square, and returns the piece that was there.
fn remove(&mut self, sq: Square<Self>) -> Option<Self::ColoredPiece>;
/// at returns the piece that is in the given square.
#[must_use]
fn at(&self, sq: <Self::BitBoard as BitBoardType>::Square) -> Option<Self::ColoredPiece>;

#[must_use]
fn piece_bb(&self, piece: Piece<Self>) -> Self::BitBoard;
#[must_use]
fn color_bb(&self, color: Color<Self>) -> Self::BitBoard;
#[must_use]
fn colored_piece_bb(&self, piece: Self::ColoredPiece) -> Self::BitBoard;

#[must_use]
fn hash(&self) -> Hash;

// Game Result functions.

/// winner returns the winning side in the current position.
#[must_use]
fn winner(&self) -> Option<Color<Self>>;
/// is_game_over returns a boolean representing if the game is over.
#[must_use]
fn is_game_over(&self) -> bool {
self.winner().is_some()
}
Expand All @@ -53,6 +60,7 @@ where
/// current position. The UPDATE_PERIPHERALS flag can be interpreted as
/// toggling the non-essential updated which are done by this function, like
/// the hash function for the position.
#[must_use]
fn after_move<const UPDATE_PERIPHERALS: bool>(&self, mov: Self::Move) -> Self;

// Move Generation functions for the board representation.
Expand All @@ -71,6 +79,7 @@ where
);
/// generate_moves is similar to generate_moves_into, except that instead of
/// taking some storage as input it stores into a custom stack-based type.
#[must_use]
fn generate_moves<const ALLOW_ILLEGAL: bool, const QUIET: bool, const NOISY: bool>(
&self,
) -> MoveList<Self::Move> {
Expand All @@ -83,6 +92,7 @@ where
/// By default this is simply `generate_moves().len()`, but implementations
/// may take advantage of various optimizations counting as opposed to
/// storing the moves allows to provide a more efficient version.
#[must_use]
fn count_moves<const QUIET: bool, const NOISY: bool>(&self) -> usize {
self.generate_moves::<false, QUIET, NOISY>().len()
}
Expand Down
7 changes: 7 additions & 0 deletions games/src/interface/square.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,22 +12,26 @@ where
type Rank;

/// new creates a new Square from the given File and Rank.
#[must_use]
fn new(file: Self::File, rank: Self::Rank) -> Self {
unsafe { Self::unsafe_from(rank.into() * Self::File::N as u8 + file.into()) }
}

/// Returns the File of self.
#[must_use]
fn file(self) -> Self::File {
unsafe { Self::File::unsafe_from(self.into() % Self::File::N as u8) }
}

/// Returns the Rank of self.
#[must_use]
fn rank(self) -> Self::Rank {
unsafe { Self::Rank::unsafe_from(self.into() / Self::File::N as u8) }
}

/// Returns the square to the north of self. If there is no Square to the
/// north of self, it returns None.
#[must_use]
fn north(self) -> Option<Self> {
if self.rank().into() as usize == Self::Rank::N - 1 {
None
Expand All @@ -38,6 +42,7 @@ where

/// Returns the square to the south of self. If there is no Square to the
/// south of self, it returns None.
#[must_use]
fn south(self) -> Option<Self> {
if self.rank().into() as usize == 0 {
None
Expand All @@ -48,6 +53,7 @@ where

/// Returns the square to the east of self. If there is no Square to the
/// east of self, it returns None.
#[must_use]
fn east(self) -> Option<Self> {
if self.file().into() as usize == Self::File::N - 1 {
None
Expand All @@ -58,6 +64,7 @@ where

/// Returns the square to the west of self. If there is no Square to the
/// west of self, it returns None.
#[must_use]
fn west(self) -> Option<Self> {
if self.file().into() as usize == 0 {
None
Expand Down
1 change: 1 addition & 0 deletions games/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ use interface::PositionType;
/// "higher" terminal nodes (e.g. mate or stalemate) are not counted, instead
/// the number of move paths of a certain depth. Perft ignores draws by
/// repetition, by the fifty-move rule and by insufficient material.
#[must_use]
pub fn perft<const SPLIT: bool, const BULK: bool, T: PositionType>(position: T, depth: u8) -> u64 {
// Bulk counting if enabled. Instead of calling make move and perft for each
// move at depth 1, just return the number of legal moves, which is equivalent.
Expand Down

0 comments on commit 77ae510

Please sign in to comment.