use arena::SyncDroplessArena;
use rustc::ty::{Ty, TyKind};
use std::fmt;
use std::marker::PhantomData;
use crate::type_map;
#[derive(Clone, PartialEq, Eq)]
pub struct LabeledTyS<'lty, 'tcx: 'lty, L: 'lty> {
pub ty: Ty<'tcx>,
pub args: &'lty [LabeledTy<'lty, 'tcx, L>],
pub label: L,
}
pub type LabeledTy<'lty, 'tcx, L> = &'lty LabeledTyS<'lty, 'tcx, L>;
impl<'lty, 'tcx, L: fmt::Debug> fmt::Debug for LabeledTyS<'lty, 'tcx, L> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}#{:?}{:?}", self.label, self.ty, self.args)
}
}
impl<'lty, 'tcx, L> LabeledTyS<'lty, 'tcx, L> {
pub fn for_each_label<F: FnMut(&'lty L)>(&'lty self, callback: &mut F) {
callback(&self.label);
for &arg in self.args {
arg.for_each_label(callback);
}
}
}
pub struct LabeledTyCtxt<'lty, L: 'lty> {
arena: &'lty SyncDroplessArena,
_marker: PhantomData<L>,
}
impl<'lty, 'tcx: 'lty, L: Clone> LabeledTyCtxt<'lty, L> {
pub fn new(arena: &'lty SyncDroplessArena) -> LabeledTyCtxt<'lty, L> {
LabeledTyCtxt {
arena: arena,
_marker: PhantomData,
}
}
pub fn mk_slice(&self, ltys: &[LabeledTy<'lty, 'tcx, L>]) -> &'lty [LabeledTy<'lty, 'tcx, L>] {
if ltys.len() == 0 {
return &[];
}
self.arena.alloc_slice(ltys)
}
pub fn mk(
&self,
ty: Ty<'tcx>,
args: &'lty [LabeledTy<'lty, 'tcx, L>],
label: L,
) -> LabeledTy<'lty, 'tcx, L> {
self.arena.alloc(LabeledTyS {
ty: ty,
args: args,
label: label,
})
}
pub fn label<F: FnMut(Ty<'tcx>) -> L>(
&self,
ty: Ty<'tcx>,
f: &mut F,
) -> LabeledTy<'lty, 'tcx, L> {
use rustc::ty::TyKind::*;
let label = f(ty);
match ty.sty {
Bool | Char | Int(_) | Uint(_) | Float(_) | Str | Foreign(_) | Never => {
self.mk(ty, &[], label)
}
Adt(_, substs) => {
let args = substs.types().map(|t| self.label(t, f)).collect::<Vec<_>>();
self.mk(ty, self.mk_slice(&args), label)
}
Array(elem, _) => {
let args = [self.label(elem, f)];
self.mk(ty, self.mk_slice(&args), label)
}
Slice(elem) => {
let args = [self.label(elem, f)];
self.mk(ty, self.mk_slice(&args), label)
}
RawPtr(mty) => {
let args = [self.label(mty.ty, f)];
self.mk(ty, self.mk_slice(&args), label)
}
Ref(_, mty, _) => {
let args = [self.label(mty, f)];
self.mk(ty, self.mk_slice(&args), label)
}
FnDef(_, substs) => {
let args = substs
.types()
.map(|ty| self.label(ty, f))
.collect::<Vec<_>>();
self.mk(ty, self.mk_slice(&args), label)
}
FnPtr(ref sig) => {
let args = sig
.skip_binder()
.inputs_and_output
.iter()
.map(|ty| self.label(ty, f))
.collect::<Vec<_>>();
self.mk(ty, self.mk_slice(&args), label)
}
Tuple(ref elems) => {
let args = elems.iter().map(|ty| self.label(ty, f)).collect::<Vec<_>>();
self.mk(ty, self.mk_slice(&args), label)
}
Dynamic(..)
| Closure(..)
| Generator(..)
| GeneratorWitness(..)
| Projection(..)
| UnnormalizedProjection(..)
| Opaque(..)
| Param(..)
| Bound(..)
| Placeholder(..)
| Infer(..)
| Error => self.mk(ty, &[], label),
}
}
pub fn label_slice<F>(&self, tys: &[Ty<'tcx>], f: &mut F) -> &'lty [LabeledTy<'lty, 'tcx, L>]
where
F: FnMut(Ty<'tcx>) -> L,
{
self.mk_slice(&tys.iter().map(|ty| self.label(ty, f)).collect::<Vec<_>>())
}
pub fn subst(
&self,
lty: LabeledTy<'lty, 'tcx, L>,
substs: &[LabeledTy<'lty, 'tcx, L>],
) -> LabeledTy<'lty, 'tcx, L> {
match lty.ty.sty {
TyKind::Param(ref tp) => substs[tp.idx as usize],
_ => self.mk(
lty.ty,
self.subst_slice(lty.args, substs),
lty.label.clone(),
),
}
}
pub fn subst_slice(
&self,
ltys: &[LabeledTy<'lty, 'tcx, L>],
substs: &[LabeledTy<'lty, 'tcx, L>],
) -> &'lty [LabeledTy<'lty, 'tcx, L>] {
self.mk_slice(
<ys
.iter()
.map(|lty| self.subst(lty, substs))
.collect::<Vec<_>>(),
)
}
pub fn relabel<L2, F>(
&self,
lty: LabeledTy<'lty, 'tcx, L2>,
func: &mut F,
) -> LabeledTy<'lty, 'tcx, L>
where
F: FnMut(&L2) -> L,
{
let args = self.relabel_slice(lty.args, func);
self.mk(lty.ty, args, func(<y.label))
}
pub fn relabel_slice<L2, F>(
&self,
ltys: &'lty [LabeledTy<'lty, 'tcx, L2>],
func: &mut F,
) -> &'lty [LabeledTy<'lty, 'tcx, L>]
where
F: FnMut(&L2) -> L,
{
let ltys = ltys
.iter()
.cloned()
.map(|lty| self.relabel(lty, func))
.collect::<Vec<_>>();
self.mk_slice(<ys)
}
}
impl<'lty, 'tcx, L: fmt::Debug> type_map::Type for LabeledTy<'lty, 'tcx, L> {
fn sty(&self) -> &TyKind {
&self.ty.sty
}
fn num_args(&self) -> usize {
self.args.len()
}
fn arg(&self, idx: usize) -> Self {
self.args[idx]
}
}