Skip to content

Commit

Permalink
Rollup merge of rust-lang#77022 - Juici:master, r=lcnr
Browse files Browse the repository at this point in the history
Reduce boilerplate for BytePos and CharPos

Reduces boilerplate code for BytePos and CharPos by using a macro to implement shared traits.
  • Loading branch information
Dylan-DPC authored Sep 22, 2020
2 parents 42b3303 + 9a1f177 commit b441d26
Showing 1 changed file with 55 additions and 82 deletions.
137 changes: 55 additions & 82 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1558,58 +1558,71 @@ pub trait Pos {
fn to_u32(&self) -> u32;
}

/// A byte offset. Keep this small (currently 32-bits), as AST contains
/// a lot of them.
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct BytePos(pub u32);

/// A character offset. Because of multibyte UTF-8 characters, a byte offset
/// is not equivalent to a character offset. The `SourceMap` will convert `BytePos`
/// values to `CharPos` values as necessary.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct CharPos(pub usize);
macro_rules! impl_pos {
(
$(
$(#[$attr:meta])*
$vis:vis struct $ident:ident($inner_vis:vis $inner_ty:ty);
)*
) => {
$(
$(#[$attr])*
$vis struct $ident($inner_vis $inner_ty);

impl Pos for $ident {
#[inline(always)]
fn from_usize(n: usize) -> $ident {
$ident(n as $inner_ty)
}

// FIXME: lots of boilerplate in these impls, but so far my attempts to fix
// have been unsuccessful.
#[inline(always)]
fn to_usize(&self) -> usize {
self.0 as usize
}

impl Pos for BytePos {
#[inline(always)]
fn from_usize(n: usize) -> BytePos {
BytePos(n as u32)
}
#[inline(always)]
fn from_u32(n: u32) -> $ident {
$ident(n as $inner_ty)
}

#[inline(always)]
fn to_usize(&self) -> usize {
self.0 as usize
}
#[inline(always)]
fn to_u32(&self) -> u32 {
self.0 as u32
}
}

#[inline(always)]
fn from_u32(n: u32) -> BytePos {
BytePos(n)
}
impl Add for $ident {
type Output = $ident;

#[inline(always)]
fn to_u32(&self) -> u32 {
self.0
}
}
#[inline(always)]
fn add(self, rhs: $ident) -> $ident {
$ident(self.0 + rhs.0)
}
}

impl Add for BytePos {
type Output = BytePos;
impl Sub for $ident {
type Output = $ident;

#[inline(always)]
fn add(self, rhs: BytePos) -> BytePos {
BytePos((self.to_usize() + rhs.to_usize()) as u32)
}
#[inline(always)]
fn sub(self, rhs: $ident) -> $ident {
$ident(self.0 - rhs.0)
}
}
)*
};
}

impl Sub for BytePos {
type Output = BytePos;
impl_pos! {
/// A byte offset. Keep this small (currently 32-bits), as AST contains
/// a lot of them.
#[derive(Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Debug)]
pub struct BytePos(pub u32);

#[inline(always)]
fn sub(self, rhs: BytePos) -> BytePos {
BytePos((self.to_usize() - rhs.to_usize()) as u32)
}
/// A character offset. Because of multibyte UTF-8 characters, a byte offset
/// is not equivalent to a character offset. The `SourceMap` will convert `BytePos`
/// values to `CharPos` values as necessary.
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub struct CharPos(pub usize);
}

impl<S: rustc_serialize::Encoder> Encodable<S> for BytePos {
Expand All @@ -1624,46 +1637,6 @@ impl<D: rustc_serialize::Decoder> Decodable<D> for BytePos {
}
}

impl Pos for CharPos {
#[inline(always)]
fn from_usize(n: usize) -> CharPos {
CharPos(n)
}

#[inline(always)]
fn to_usize(&self) -> usize {
self.0
}

#[inline(always)]
fn from_u32(n: u32) -> CharPos {
CharPos(n as usize)
}

#[inline(always)]
fn to_u32(&self) -> u32 {
self.0 as u32
}
}

impl Add for CharPos {
type Output = CharPos;

#[inline(always)]
fn add(self, rhs: CharPos) -> CharPos {
CharPos(self.to_usize() + rhs.to_usize())
}
}

impl Sub for CharPos {
type Output = CharPos;

#[inline(always)]
fn sub(self, rhs: CharPos) -> CharPos {
CharPos(self.to_usize() - rhs.to_usize())
}
}

// _____________________________________________________________________________
// Loc, SourceFileAndLine, SourceFileAndBytePos
//
Expand Down

0 comments on commit b441d26

Please sign in to comment.