use crate::BytePos;
use crate::Span;
use crate::SyntaxContext;
use num_bigint::BigInt;
use std::cell::RefCell;
use std::cmp::PartialEq;
use std::rc::Rc;
use std::sync::Arc;
use string_cache::Atom;
pub trait EqIgnoreSpan {
fn eq_ignore_span(&self, other: &Self) -> bool;
}
impl EqIgnoreSpan for Span {
#[inline]
fn eq_ignore_span(&self, _: &Self) -> bool {
true
}
}
impl<T> EqIgnoreSpan for [T]
where
T: EqIgnoreSpan,
{
fn eq_ignore_span(&self, other: &Self) -> bool {
self.len() == other.len()
&& self
.iter()
.zip(other.iter())
.all(|(a, b)| a.eq_ignore_span(b))
}
}
impl<T> EqIgnoreSpan for Option<T>
where
T: EqIgnoreSpan,
{
fn eq_ignore_span(&self, other: &Self) -> bool {
match (self, other) {
(Some(l), Some(r)) => l.eq_ignore_span(r),
(None, None) => true,
_ => false,
}
}
}
impl<T> EqIgnoreSpan for Vec<T>
where
T: EqIgnoreSpan,
{
fn eq_ignore_span(&self, other: &Self) -> bool {
self.len() == other.len()
&& self
.iter()
.zip(other.iter())
.all(|(a, b)| a.eq_ignore_span(b))
}
}
pub trait TypeEq {
fn type_eq(&self, other: &Self) -> bool;
}
impl TypeEq for Span {
#[inline]
fn type_eq(&self, _: &Self) -> bool {
true
}
}
impl<T> TypeEq for Option<T>
where
T: TypeEq,
{
fn type_eq(&self, other: &Self) -> bool {
match (self, other) {
(Some(l), Some(r)) => l.type_eq(r),
(None, None) => true,
_ => false,
}
}
}
impl<T> TypeEq for Vec<T>
where
T: TypeEq,
{
fn type_eq(&self, other: &Self) -> bool {
self.len() == other.len() && self.iter().zip(other.iter()).all(|(a, b)| a.type_eq(b))
}
}
macro_rules! eq {
($T:ty) => {
impl EqIgnoreSpan for $T {
#[inline]
fn eq_ignore_span(&self, other: &Self) -> bool {
self == other
}
}
impl TypeEq for $T {
#[inline]
fn type_eq(&self, other: &Self) -> bool {
self == other
}
}
};
(
$(
$T:ty
),*
) => {
$(
eq!($T);
)*
};
}
eq!(SyntaxContext, BytePos);
eq!(bool);
eq!(usize, u8, u16, u32, u64, u128);
eq!(isize, i8, i16, i32, i64, i128);
eq!(f32, f64);
eq!(char, str, String);
impl<S: PartialEq> EqIgnoreSpan for Atom<S> {
#[inline]
fn eq_ignore_span(&self, other: &Self) -> bool {
self == other
}
}
impl<S: PartialEq> TypeEq for Atom<S> {
#[inline]
fn type_eq(&self, other: &Self) -> bool {
self == other
}
}
macro_rules! deref {
($T:ident) => {
impl<N> EqIgnoreSpan for $T<N>
where
N: EqIgnoreSpan,
{
#[inline]
fn eq_ignore_span(&self, other: &Self) -> bool {
(**self).eq_ignore_span(&**other)
}
}
impl<N> TypeEq for $T<N>
where
N: TypeEq,
{
#[inline]
fn type_eq(&self, other: &Self) -> bool {
(**self).type_eq(&**other)
}
}
};
(
$(
$T:ident
),*
) => {
$(
deref!($T);
)*
};
}
deref!(Box, Rc, Arc);
impl<'a, N> EqIgnoreSpan for &'a N
where
N: EqIgnoreSpan,
{
#[inline]
fn eq_ignore_span(&self, other: &Self) -> bool {
(**self).eq_ignore_span(&**other)
}
}
impl<'a, N> TypeEq for &'a N
where
N: TypeEq,
{
#[inline]
fn type_eq(&self, other: &Self) -> bool {
(**self).type_eq(&**other)
}
}
impl<N> EqIgnoreSpan for RefCell<N>
where
N: EqIgnoreSpan,
{
fn eq_ignore_span(&self, other: &Self) -> bool {
self.borrow().eq_ignore_span(&*other.borrow())
}
}
impl<N> TypeEq for RefCell<N>
where
N: TypeEq,
{
fn type_eq(&self, other: &Self) -> bool {
self.borrow().type_eq(&*other.borrow())
}
}
impl EqIgnoreSpan for BigInt {
fn eq_ignore_span(&self, other: &Self) -> bool {
self == other
}
}
impl TypeEq for BigInt {
fn type_eq(&self, other: &Self) -> bool {
self == other
}
}