use std::sync::atomic::Ordering;
use rustc::ty;
use rlua::prelude::{LuaMetaMethod, LuaUserData, LuaUserDataMethods};
use crate::command::TyCtxtGeneration;
use crate::context::RefactorCtxt;
#[derive(Debug, Clone)]
pub struct LuaTy {
tcx_gen_ref: TyCtxtGeneration,
tcx_gen: usize,
ty_ptr: *const (),
}
unsafe impl Send for LuaTy {}
impl LuaTy {
#[inline]
pub fn from_ty<'a, 'tcx>(ty: ty::Ty<'tcx>, cx: &'a RefactorCtxt<'a, 'tcx>) -> Self {
let tcx_gen_ref = cx.tcx_gen();
let tcx_gen = tcx_gen_ref.load(Ordering::Relaxed);
LuaTy {
tcx_gen_ref,
tcx_gen,
ty_ptr: ty as *const ty::TyS<'tcx> as *const (),
}
}
}
impl<'a> From<&LuaTy> for ty::Ty<'a> {
#[inline]
fn from(lua_ty: &LuaTy) -> Self {
let tcx_gen = lua_ty.tcx_gen_ref.load(Ordering::Relaxed);
if lua_ty.tcx_gen != tcx_gen {
panic!("Dangling LuaTy from generation {}, current is {}",
lua_ty.tcx_gen, tcx_gen);
}
unsafe { &*(lua_ty.ty_ptr as *const ty::TyS) }
}
}
#[allow(unused_doc_comments)]
impl LuaUserData for LuaTy {
fn add_methods<'lua, M: LuaUserDataMethods<'lua, Self>>(methods: &mut M) {
methods.add_meta_method(LuaMetaMethod::ToString, |_lua_ctx, this, ()| {
let ty: ty::Ty = this.into();
Ok(format!("kind:{:?} flags:{}", ty.kind, ty.flags.bits()))
});
methods.add_method("kind_name", |_lua_ctx, this, ()| {
let ty: ty::Ty = this.into();
macro_rules! match_kinds {
{[$($unit_kind:ident),*], [$($tuple_kind:ident),*]} => {
match ty.kind {
$(ty::TyKind::$unit_kind => Ok(stringify!($unit_kind)),)*
$(ty::TyKind::$tuple_kind(..) => Ok(stringify!($kind)),)*
}
}
};
match_kinds!{
[Bool, Char, Str, Never, Error],
[Int, Uint, Float, Adt, Foreign, Array, Slice, RawPtr,
Ref, FnDef, FnPtr, Dynamic, Closure, Generator,
GeneratorWitness, Tuple, Projection, UnnormalizedProjection,
Opaque, Param, Bound, Placeholder, Infer]
}
});
}
}