use rustc_hir::def_id::DefId;
use rustc_middle::mir::Promoted;
use rustc_middle::ty::{GenericArg, GenericArgKind};
use rustc_middle::ty::{Const, Ty};
use crate::mir::context::ContextId;
use std::rc::Rc;
rustc_index::newtype_index! {
#[orderable]
#[debug_format = "FuncId({})"]
pub struct FuncId {}
}
#[derive(Copy, Clone, Debug, Eq, PartialOrd, PartialEq, Hash, Ord)]
pub struct CSFuncId {
pub cid: ContextId,
pub func_id: FuncId,
}
impl CSFuncId {
pub fn new(cid: ContextId, func_id: FuncId) -> Self {
Self { cid, func_id }
}
}
impl From<CSFuncId> for FuncId {
fn from(f: CSFuncId) -> Self {
f.func_id
}
}
#[derive(Clone, Debug, Eq, PartialOrd, PartialEq, Hash, Ord)]
pub struct FunctionReference<'tcx> {
pub def_id: DefId,
pub generic_args: Vec<GenericArgE<'tcx>>,
pub promoted: Option<Promoted>,
}
#[derive(Clone, Debug, Eq, PartialOrd, PartialEq, Hash, Ord)]
pub enum GenericArgE<'tcx> {
Region,
Const(Const<'tcx>),
Type(Ty<'tcx>),
}
impl<'tcx> From<&GenericArg<'tcx>> for GenericArgE<'tcx> {
fn from(ga: &GenericArg<'tcx>) -> GenericArgE<'tcx> {
match ga.unpack() {
GenericArgKind::Lifetime(_) => GenericArgE::Region,
GenericArgKind::Const(c) => GenericArgE::Const(c),
GenericArgKind::Type(ty) => GenericArgE::Type(ty),
}
}
}
impl<'tcx> FunctionReference<'tcx> {
pub fn new_function_reference(
def_id: DefId,
generic_args: Vec<GenericArgE<'tcx>>,
) -> Rc<FunctionReference<'tcx>> {
Rc::new(FunctionReference {
def_id,
generic_args,
promoted: None,
})
}
pub fn new_promoted_reference(
def_id: DefId,
generic_args: Vec<GenericArgE<'tcx>>,
promoted: Promoted,
) -> Rc<FunctionReference<'tcx>> {
Rc::new(FunctionReference {
def_id,
generic_args,
promoted: Some(promoted),
})
}
}
impl<'tcx> ToString for FunctionReference<'tcx> {
fn to_string(&self) -> String {
let const_to_str = |c: &Const| -> String {
if let Some(v) = c.try_to_scalar() {
return v.to_string();
}
return "_".to_string();
};
let tmp1 = format!("{:?}", self.def_id);
let crate_name = &tmp1[tmp1.find("~ ").unwrap() + 2..tmp1.find("[").unwrap()];
let tmp2 = &tmp1[tmp1.find("::").unwrap() + 2..tmp1.len() - 1];
let mut tmp3 = "".to_string();
if !self.generic_args.is_empty() {
tmp3.push('<');
let tys = self
.generic_args
.iter()
.filter_map(|t| match t {
GenericArgE::Type(ty) => Some(format!("{:?}", ty)),
GenericArgE::Const(c) => Some(const_to_str(c)),
_ => None,
})
.collect::<Vec<String>>();
tmp3.push_str(&tys.join(", "));
tmp3.push('>');
}
if let Some(promoted) = self.promoted {
format!("{}::{}::promoted[{}]", crate_name, tmp2, promoted.index())
} else {
format!("{}::{}{}", crate_name, tmp2, tmp3)
}
}
}