mirror of
https://github.com/rust-lang/rust.git
synced 2025-01-01 18:35:25 +00:00
Separate out the unboxed closure table into two tables, so that we can
generate the closure type and closure kind separately.
This commit is contained in:
parent
92f94765ec
commit
2f465869fd
@ -139,10 +139,11 @@ pub enum astencode_tag { // Reserves 0x40 -- 0x5f
|
||||
tag_table_adjustments = 0x51,
|
||||
tag_table_moves_map = 0x52,
|
||||
tag_table_capture_map = 0x53,
|
||||
tag_table_closures = 0x54,
|
||||
tag_table_upvar_capture_map = 0x55,
|
||||
tag_table_capture_modes = 0x56,
|
||||
tag_table_object_cast_map = 0x57,
|
||||
tag_table_closure_tys = 0x54,
|
||||
tag_table_closure_kinds = 0x55,
|
||||
tag_table_upvar_capture_map = 0x56,
|
||||
tag_table_capture_modes = 0x57,
|
||||
tag_table_object_cast_map = 0x58,
|
||||
}
|
||||
|
||||
static first_astencode_tag: uint = tag_ast as uint;
|
||||
@ -225,10 +226,7 @@ pub struct LinkMeta {
|
||||
pub crate_hash: Svh,
|
||||
}
|
||||
|
||||
pub const tag_closures: uint = 0x95;
|
||||
pub const tag_closure: uint = 0x96;
|
||||
pub const tag_closure_type: uint = 0x97;
|
||||
pub const tag_closure_kind: uint = 0x98;
|
||||
// GAP 0x94...0x98
|
||||
|
||||
pub const tag_struct_fields: uint = 0x99;
|
||||
pub const tag_struct_field: uint = 0x9a;
|
||||
|
@ -618,17 +618,6 @@ fn encode_visibility(rbml_w: &mut Encoder, visibility: ast::Visibility) {
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_closure_kind(rbml_w: &mut Encoder, kind: ty::ClosureKind) {
|
||||
rbml_w.start_tag(tag_closure_kind);
|
||||
let ch = match kind {
|
||||
ty::FnClosureKind => 'f',
|
||||
ty::FnMutClosureKind => 'm',
|
||||
ty::FnOnceClosureKind => 'o',
|
||||
};
|
||||
rbml_w.wr_str(&ch.to_string()[]);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_explicit_self(rbml_w: &mut Encoder,
|
||||
explicit_self: &ty::ExplicitSelfCategory) {
|
||||
rbml_w.start_tag(tag_item_trait_method_explicit_self);
|
||||
@ -1843,24 +1832,6 @@ fn encode_macro_defs(rbml_w: &mut Encoder,
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_closures<'a>(ecx: &'a EncodeContext, rbml_w: &'a mut Encoder) {
|
||||
rbml_w.start_tag(tag_closures);
|
||||
for (closure_id, closure) in ecx.tcx.closures.borrow().iter() {
|
||||
if closure_id.krate != ast::LOCAL_CRATE {
|
||||
continue
|
||||
}
|
||||
|
||||
rbml_w.start_tag(tag_closure);
|
||||
encode_def_id(rbml_w, *closure_id);
|
||||
rbml_w.start_tag(tag_closure_type);
|
||||
write_closure_type(ecx, rbml_w, &closure.closure_type);
|
||||
rbml_w.end_tag();
|
||||
encode_closure_kind(rbml_w, closure.kind);
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
rbml_w.end_tag();
|
||||
}
|
||||
|
||||
fn encode_struct_field_attrs(rbml_w: &mut Encoder, krate: &ast::Crate) {
|
||||
struct StructFieldVisitor<'a, 'b:'a> {
|
||||
rbml_w: &'a mut Encoder<'b>,
|
||||
@ -2069,7 +2040,6 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
|
||||
native_lib_bytes: u64,
|
||||
plugin_registrar_fn_bytes: u64,
|
||||
macro_defs_bytes: u64,
|
||||
closure_bytes: u64,
|
||||
impl_bytes: u64,
|
||||
misc_bytes: u64,
|
||||
item_bytes: u64,
|
||||
@ -2084,7 +2054,6 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
|
||||
native_lib_bytes: 0,
|
||||
plugin_registrar_fn_bytes: 0,
|
||||
macro_defs_bytes: 0,
|
||||
closure_bytes: 0,
|
||||
impl_bytes: 0,
|
||||
misc_bytes: 0,
|
||||
item_bytes: 0,
|
||||
@ -2154,11 +2123,6 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
|
||||
encode_macro_defs(&mut rbml_w, krate);
|
||||
stats.macro_defs_bytes = rbml_w.writer.tell().unwrap() - i;
|
||||
|
||||
// Encode the types of all closures in this crate.
|
||||
i = rbml_w.writer.tell().unwrap();
|
||||
encode_closures(&ecx, &mut rbml_w);
|
||||
stats.closure_bytes = rbml_w.writer.tell().unwrap() - i;
|
||||
|
||||
// Encode the def IDs of impls, for coherence checking.
|
||||
i = rbml_w.writer.tell().unwrap();
|
||||
encode_impls(&ecx, krate, &mut rbml_w);
|
||||
@ -2199,7 +2163,6 @@ fn encode_metadata_inner(wr: &mut SeekableMemWriter,
|
||||
println!(" native bytes: {}", stats.native_lib_bytes);
|
||||
println!("plugin registrar bytes: {}", stats.plugin_registrar_fn_bytes);
|
||||
println!(" macro def bytes: {}", stats.macro_defs_bytes);
|
||||
println!(" closure bytes: {}", stats.closure_bytes);
|
||||
println!(" impl bytes: {}", stats.impl_bytes);
|
||||
println!(" misc bytes: {}", stats.misc_bytes);
|
||||
println!(" item bytes: {}", stats.item_bytes);
|
||||
|
@ -647,30 +647,7 @@ impl<'tcx> tr for MethodOrigin<'tcx> {
|
||||
}
|
||||
|
||||
pub fn encode_closure_kind(ebml_w: &mut Encoder, kind: ty::ClosureKind) {
|
||||
use serialize::Encoder;
|
||||
|
||||
ebml_w.emit_enum("ClosureKind", |ebml_w| {
|
||||
match kind {
|
||||
ty::FnClosureKind => {
|
||||
ebml_w.emit_enum_variant("FnClosureKind", 0, 3, |_| {
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
ty::FnMutClosureKind => {
|
||||
ebml_w.emit_enum_variant("FnMutClosureKind", 1, 3, |_| {
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
ty::FnOnceClosureKind => {
|
||||
ebml_w.emit_enum_variant("FnOnceClosureKind",
|
||||
2,
|
||||
3,
|
||||
|_| {
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
}).unwrap()
|
||||
kind.encode(ebml_w).unwrap();
|
||||
}
|
||||
|
||||
pub trait vtable_decoder_helpers<'tcx> {
|
||||
@ -1310,12 +1287,20 @@ fn encode_side_tables_for_id(ecx: &e::EncodeContext,
|
||||
})
|
||||
}
|
||||
|
||||
for closure in tcx.closures.borrow().get(&ast_util::local_def(id)).iter() {
|
||||
rbml_w.tag(c::tag_table_closures, |rbml_w| {
|
||||
for &closure_type in tcx.closure_tys.borrow().get(&ast_util::local_def(id)).iter() {
|
||||
rbml_w.tag(c::tag_table_closure_tys, |rbml_w| {
|
||||
rbml_w.id(id);
|
||||
rbml_w.tag(c::tag_table_val, |rbml_w| {
|
||||
rbml_w.emit_closure_type(ecx, &closure.closure_type);
|
||||
encode_closure_kind(rbml_w, closure.kind)
|
||||
rbml_w.emit_closure_type(ecx, closure_type);
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
for &&closure_kind in tcx.closure_kinds.borrow().get(&ast_util::local_def(id)).iter() {
|
||||
rbml_w.tag(c::tag_table_closure_kinds, |rbml_w| {
|
||||
rbml_w.id(id);
|
||||
rbml_w.tag(c::tag_table_val, |rbml_w| {
|
||||
encode_closure_kind(rbml_w, closure_kind)
|
||||
})
|
||||
})
|
||||
}
|
||||
@ -1354,8 +1339,10 @@ trait rbml_decoder_decoder_helpers<'tcx> {
|
||||
-> subst::Substs<'tcx>;
|
||||
fn read_auto_adjustment<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
|
||||
-> ty::AutoAdjustment<'tcx>;
|
||||
fn read_closure<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
|
||||
-> ty::Closure<'tcx>;
|
||||
fn read_closure_kind<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
|
||||
-> ty::ClosureKind;
|
||||
fn read_closure_ty<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
|
||||
-> ty::ClosureTy<'tcx>;
|
||||
fn read_auto_deref_ref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
|
||||
-> ty::AutoDerefRef<'tcx>;
|
||||
fn read_autoref<'a, 'b>(&mut self, dcx: &DecodeContext<'a, 'b, 'tcx>)
|
||||
@ -1782,35 +1769,23 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
|
||||
}).unwrap()
|
||||
}
|
||||
|
||||
fn read_closure<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
|
||||
-> ty::Closure<'tcx> {
|
||||
let closure_type = self.read_opaque(|this, doc| {
|
||||
fn read_closure_kind<'b, 'c>(&mut self, _dcx: &DecodeContext<'b, 'c, 'tcx>)
|
||||
-> ty::ClosureKind
|
||||
{
|
||||
Decodable::decode(self).ok().unwrap()
|
||||
}
|
||||
|
||||
fn read_closure_ty<'b, 'c>(&mut self, dcx: &DecodeContext<'b, 'c, 'tcx>)
|
||||
-> ty::ClosureTy<'tcx>
|
||||
{
|
||||
self.read_opaque(|this, doc| {
|
||||
Ok(tydecode::parse_ty_closure_data(
|
||||
doc.data,
|
||||
dcx.cdata.cnum,
|
||||
doc.start,
|
||||
dcx.tcx,
|
||||
|s, a| this.convert_def_id(dcx, s, a)))
|
||||
}).unwrap();
|
||||
let variants = &[
|
||||
"FnClosureKind",
|
||||
"FnMutClosureKind",
|
||||
"FnOnceClosureKind"
|
||||
];
|
||||
let kind = self.read_enum("ClosureKind", |this| {
|
||||
this.read_enum_variant(variants, |_, i| {
|
||||
Ok(match i {
|
||||
0 => ty::FnClosureKind,
|
||||
1 => ty::FnMutClosureKind,
|
||||
2 => ty::FnOnceClosureKind,
|
||||
_ => panic!("bad enum variant for ty::ClosureKind"),
|
||||
})
|
||||
})
|
||||
}).unwrap();
|
||||
ty::Closure {
|
||||
closure_type: closure_type,
|
||||
kind: kind,
|
||||
}
|
||||
}).unwrap()
|
||||
}
|
||||
|
||||
/// Converts a def-id that appears in a type. The correct
|
||||
@ -1937,11 +1912,17 @@ fn decode_side_tables(dcx: &DecodeContext,
|
||||
let adj: ty::AutoAdjustment = val_dsr.read_auto_adjustment(dcx);
|
||||
dcx.tcx.adjustments.borrow_mut().insert(id, adj);
|
||||
}
|
||||
c::tag_table_closures => {
|
||||
let closure =
|
||||
val_dsr.read_closure(dcx);
|
||||
dcx.tcx.closures.borrow_mut().insert(ast_util::local_def(id),
|
||||
closure);
|
||||
c::tag_table_closure_tys => {
|
||||
let closure_ty =
|
||||
val_dsr.read_closure_ty(dcx);
|
||||
dcx.tcx.closure_tys.borrow_mut().insert(ast_util::local_def(id),
|
||||
closure_ty);
|
||||
}
|
||||
c::tag_table_closure_kinds => {
|
||||
let closure_kind =
|
||||
val_dsr.read_closure_kind(dcx);
|
||||
dcx.tcx.closure_kinds.borrow_mut().insert(ast_util::local_def(id),
|
||||
closure_kind);
|
||||
}
|
||||
_ => {
|
||||
dcx.tcx.sess.bug(
|
||||
|
@ -260,12 +260,10 @@ impl OverloadedCallType {
|
||||
fn from_closure(tcx: &ty::ctxt, closure_did: ast::DefId)
|
||||
-> OverloadedCallType {
|
||||
let trait_did =
|
||||
tcx.closures
|
||||
tcx.closure_kinds
|
||||
.borrow()
|
||||
.get(&closure_did)
|
||||
.expect("OverloadedCallType::from_closure: didn't \
|
||||
find closure id")
|
||||
.kind
|
||||
.expect("OverloadedCallType::from_closure: didn't find closure id")
|
||||
.trait_did(tcx);
|
||||
OverloadedCallType::from_trait_id(tcx, trait_did)
|
||||
}
|
||||
|
@ -790,7 +790,11 @@ pub struct ctxt<'tcx> {
|
||||
|
||||
/// Records the type of each closure. The def ID is the ID of the
|
||||
/// expression defining the closure.
|
||||
pub closures: RefCell<DefIdMap<Closure<'tcx>>>,
|
||||
pub closure_kinds: RefCell<DefIdMap<ClosureKind>>,
|
||||
|
||||
/// Records the type of each closure. The def ID is the ID of the
|
||||
/// expression defining the closure.
|
||||
pub closure_tys: RefCell<DefIdMap<ClosureTy<'tcx>>>,
|
||||
|
||||
pub node_lint_levels: RefCell<FnvHashMap<(ast::NodeId, lint::LintId),
|
||||
lint::LevelSource>>,
|
||||
@ -2251,16 +2255,7 @@ pub struct ItemSubsts<'tcx> {
|
||||
pub substs: Substs<'tcx>,
|
||||
}
|
||||
|
||||
/// Records information about each closure.
|
||||
#[derive(Clone)]
|
||||
pub struct Closure<'tcx> {
|
||||
/// The type of the closure.
|
||||
pub closure_type: ClosureTy<'tcx>,
|
||||
/// The kind of closure this is.
|
||||
pub kind: ClosureKind,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)]
|
||||
pub enum ClosureKind {
|
||||
FnClosureKind,
|
||||
FnMutClosureKind,
|
||||
@ -2399,7 +2394,8 @@ pub fn mk_ctxt<'tcx>(s: Session,
|
||||
extern_const_variants: RefCell::new(DefIdMap()),
|
||||
method_map: RefCell::new(FnvHashMap()),
|
||||
dependency_formats: RefCell::new(FnvHashMap()),
|
||||
closures: RefCell::new(DefIdMap()),
|
||||
closure_kinds: RefCell::new(DefIdMap()),
|
||||
closure_tys: RefCell::new(DefIdMap()),
|
||||
node_lint_levels: RefCell::new(FnvHashMap()),
|
||||
transmute_restrictions: RefCell::new(Vec::new()),
|
||||
stability: RefCell::new(stability),
|
||||
@ -2446,7 +2442,7 @@ impl<'tcx> ctxt<'tcx> {
|
||||
}
|
||||
|
||||
pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind {
|
||||
self.closures.borrow()[def_id].kind
|
||||
self.closure_kinds.borrow()[def_id]
|
||||
}
|
||||
|
||||
pub fn closure_type(&self,
|
||||
@ -2454,7 +2450,7 @@ impl<'tcx> ctxt<'tcx> {
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> ty::ClosureTy<'tcx>
|
||||
{
|
||||
self.closures.borrow()[def_id].closure_type.subst(self, substs)
|
||||
self.closure_tys.borrow()[def_id].subst(self, substs)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -405,9 +405,9 @@ pub fn ty_to_string<'tcx>(cx: &ctxt<'tcx>, typ: &ty::TyS<'tcx>) -> String {
|
||||
}
|
||||
ty_str => "str".to_string(),
|
||||
ty_closure(ref did, _, substs) => {
|
||||
let closures = cx.closures.borrow();
|
||||
closures.get(did).map(|cl| {
|
||||
closure_to_string(cx, &cl.closure_type.subst(cx, substs))
|
||||
let closure_tys = cx.closure_tys.borrow();
|
||||
closure_tys.get(did).map(|closure_type| {
|
||||
closure_to_string(cx, &closure_type.subst(cx, substs))
|
||||
}).unwrap_or_else(|| {
|
||||
if did.krate == ast::LOCAL_CRATE {
|
||||
let span = cx.map.span(did.node);
|
||||
|
@ -273,7 +273,7 @@ pub fn self_type_for_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
}
|
||||
|
||||
pub fn kind_for_closure(ccx: &CrateContext, closure_id: ast::DefId) -> ty::ClosureKind {
|
||||
ccx.tcx().closures.borrow()[closure_id].kind
|
||||
ccx.tcx().closure_kinds.borrow()[closure_id]
|
||||
}
|
||||
|
||||
pub fn decl_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
|
||||
|
@ -125,7 +125,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
|
||||
closure_id: ast::DefId,
|
||||
substs: &Substs<'tcx>)
|
||||
-> Option<Datum<'tcx, Rvalue>> {
|
||||
if !ccx.tcx().closures.borrow().contains_key(&closure_id) {
|
||||
if !ccx.tcx().closure_kinds.borrow().contains_key(&closure_id) {
|
||||
// Not a closure.
|
||||
return None
|
||||
}
|
||||
|
@ -129,12 +129,8 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
|
||||
fn_ty.sig.repr(fcx.tcx()),
|
||||
kind);
|
||||
|
||||
let closure = ty::Closure {
|
||||
closure_type: fn_ty,
|
||||
kind: kind,
|
||||
};
|
||||
|
||||
fcx.inh.closures.borrow_mut().insert(expr_def_id, closure);
|
||||
fcx.inh.closure_tys.borrow_mut().insert(expr_def_id, fn_ty);
|
||||
fcx.inh.closure_kinds.borrow_mut().insert(expr_def_id, kind);
|
||||
}
|
||||
|
||||
fn deduce_expectations_from_expected_type<'a,'tcx>(
|
||||
|
@ -598,9 +598,9 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
_ => continue,
|
||||
};
|
||||
|
||||
let closures = self.fcx.inh.closures.borrow();
|
||||
let closure_data = match closures.get(&closure_def_id) {
|
||||
Some(data) => data,
|
||||
let closure_kinds = self.fcx.inh.closure_kinds.borrow();
|
||||
let closure_kind = match closure_kinds.get(&closure_def_id) {
|
||||
Some(&k) => k,
|
||||
None => {
|
||||
self.tcx().sess.span_bug(
|
||||
self.span,
|
||||
@ -610,7 +610,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
|
||||
};
|
||||
|
||||
// this closure doesn't implement the right kind of `Fn` trait
|
||||
if closure_data.kind != kind {
|
||||
if closure_kind != kind {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -160,7 +160,8 @@ pub struct Inherited<'a, 'tcx: 'a> {
|
||||
adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
|
||||
method_map: MethodMap<'tcx>,
|
||||
upvar_capture_map: RefCell<ty::UpvarCaptureMap>,
|
||||
closures: RefCell<DefIdMap<ty::Closure<'tcx>>>,
|
||||
closure_tys: RefCell<DefIdMap<ty::ClosureTy<'tcx>>>,
|
||||
closure_kinds: RefCell<DefIdMap<ty::ClosureKind>>,
|
||||
object_cast_map: ObjectCastMap<'tcx>,
|
||||
|
||||
// A mapping from each fn's id to its signature, with all bound
|
||||
@ -352,7 +353,7 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
def_id: ast::DefId)
|
||||
-> Option<ty::ClosureKind>
|
||||
{
|
||||
Some(self.inh.closures.borrow()[def_id].kind)
|
||||
self.inh.closure_kinds.borrow().get(&def_id).cloned()
|
||||
}
|
||||
|
||||
fn closure_type(&self,
|
||||
@ -360,7 +361,7 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
|
||||
substs: &subst::Substs<'tcx>)
|
||||
-> ty::ClosureTy<'tcx>
|
||||
{
|
||||
self.inh.closures.borrow()[def_id].closure_type.subst(self.tcx(), substs)
|
||||
self.inh.closure_tys.borrow()[def_id].subst(self.tcx(), substs)
|
||||
}
|
||||
|
||||
fn closure_upvars(&self,
|
||||
@ -386,7 +387,8 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
|
||||
method_map: RefCell::new(FnvHashMap()),
|
||||
object_cast_map: RefCell::new(NodeMap()),
|
||||
upvar_capture_map: RefCell::new(FnvHashMap()),
|
||||
closures: RefCell::new(DefIdMap()),
|
||||
closure_tys: RefCell::new(DefIdMap()),
|
||||
closure_kinds: RefCell::new(DefIdMap()),
|
||||
fn_sig_map: RefCell::new(NodeMap()),
|
||||
fulfillment_cx: RefCell::new(traits::FulfillmentContext::new()),
|
||||
deferred_resolutions: RefCell::new(Vec::new()),
|
||||
|
@ -204,14 +204,13 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
|
||||
return
|
||||
}
|
||||
|
||||
for (def_id, closure) in self.fcx.inh.closures.borrow().iter() {
|
||||
let closure_ty = self.resolve(&closure.closure_type,
|
||||
ResolvingClosure(*def_id));
|
||||
let closure = ty::Closure {
|
||||
closure_type: closure_ty,
|
||||
kind: closure.kind,
|
||||
};
|
||||
self.fcx.tcx().closures.borrow_mut().insert(*def_id, closure);
|
||||
for (def_id, closure_ty) in self.fcx.inh.closure_tys.borrow().iter() {
|
||||
let closure_ty = self.resolve(closure_ty, ResolvingClosure(*def_id));
|
||||
self.fcx.tcx().closure_tys.borrow_mut().insert(*def_id, closure_ty);
|
||||
}
|
||||
|
||||
for (def_id, &closure_kind) in self.fcx.inh.closure_kinds.borrow().iter() {
|
||||
self.fcx.tcx().closure_kinds.borrow_mut().insert(*def_id, closure_kind);
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user