1use std::hash::Hash;
10use std::intrinsics;
11use std::marker::{DiscriminantKind, PointeeSized};
12
13use rustc_abi::FieldIdx;
14use rustc_data_structures::fx::FxHashMap;
15use rustc_hir::def_id::LocalDefId;
16use rustc_middle::ty::Const;
17use rustc_serialize::{Decodable, Encodable};
18use rustc_span::{Span, SpanDecoder, SpanEncoder, Spanned};
19
20use crate::infer::canonical::{CanonicalVarKind, CanonicalVarKinds};
21use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance};
22use crate::mono::MonoItem;
23use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt};
24use crate::{mir, traits};
25
26pub const SHORTHAND_OFFSET: usize = 0x80;
30
31pub trait TyEncoder<'tcx>: SpanEncoder {
32 const CLEAR_CROSS_CRATE: bool;
33
34 fn position(&self) -> usize;
35
36 fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
37
38 fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>;
39
40 fn encode_alloc_id(&mut self, alloc_id: &AllocId);
41}
42
43pub trait TyDecoder<'tcx>:
44 SpanDecoder + rustc_type_ir::InternerDecoder<Interner = TyCtxt<'tcx>>
45{
46 const CLEAR_CROSS_CRATE: bool;
47
48 fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
49 where
50 F: FnOnce(&mut Self) -> Ty<'tcx>;
51
52 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
53 where
54 F: FnOnce(&mut Self) -> R;
55
56 fn positioned_at_shorthand(&self) -> bool {
57 (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
58 }
59
60 fn decode_alloc_id(&mut self) -> AllocId;
61}
62
63pub trait EncodableWithShorthand<'tcx, E: TyEncoder<'tcx>>: Copy + Eq + Hash {
64 type Variant: Encodable<E>;
65 fn variant(&self) -> &Self::Variant;
66}
67
68#[allow(rustc::usage_of_ty_tykind)]
69impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for Ty<'tcx> {
70 type Variant = ty::TyKind<'tcx>;
71
72 #[inline]
73 fn variant(&self) -> &Self::Variant {
74 self.kind()
75 }
76}
77
78impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::PredicateKind<'tcx> {
79 type Variant = ty::PredicateKind<'tcx>;
80
81 #[inline]
82 fn variant(&self) -> &Self::Variant {
83 self
84 }
85}
86
87pub trait RefDecodable<'tcx, D: TyDecoder<'tcx>>: PointeeSized {
101 fn decode(d: &mut D) -> &'tcx Self;
102}
103
104pub fn encode_with_shorthand<'tcx, E, T, M>(encoder: &mut E, value: &T, cache: M)
106where
107 E: TyEncoder<'tcx>,
108 M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
109 T: EncodableWithShorthand<'tcx, E>,
110 T::Variant: DiscriminantKind<Discriminant = isize>,
112{
113 let existing_shorthand = cache(encoder).get(value).copied();
114 if let Some(shorthand) = existing_shorthand {
115 encoder.emit_usize(shorthand);
116 return;
117 }
118
119 let variant = value.variant();
120
121 let start = encoder.position();
122 variant.encode(encoder);
123 let len = encoder.position() - start;
124
125 let discriminant = intrinsics::discriminant_value(variant);
128 if !(SHORTHAND_OFFSET > discriminant as usize) {
::core::panicking::panic("assertion failed: SHORTHAND_OFFSET > discriminant as usize")
};assert!(SHORTHAND_OFFSET > discriminant as usize);
129
130 let shorthand = start + SHORTHAND_OFFSET;
131
132 let leb128_bits = len * 7;
135
136 if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
139 cache(encoder).insert(*value, shorthand);
140 }
141}
142
143impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
144 fn encode(&self, e: &mut E) {
145 encode_with_shorthand(e, self, TyEncoder::type_shorthands);
146 }
147}
148
149impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
150 fn encode(&self, e: &mut E) {
151 let kind = self.kind();
152 kind.bound_vars().encode(e);
153 encode_with_shorthand(e, &kind.skip_binder(), TyEncoder::predicate_shorthands);
154 }
155}
156
157impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Clause<'tcx> {
158 fn encode(&self, e: &mut E) {
159 self.as_predicate().encode(e);
160 }
161}
162
163impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Const<'tcx> {
164 fn encode(&self, e: &mut E) {
165 self.0.0.encode(e);
166 }
167}
168
169impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Pattern<'tcx> {
170 fn encode(&self, e: &mut E) {
171 self.0.0.encode(e);
172 }
173}
174
175impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ValTree<'tcx> {
176 fn encode(&self, e: &mut E) {
177 self.0.0.encode(e);
178 }
179}
180
181impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ConstAllocation<'tcx> {
182 fn encode(&self, e: &mut E) {
183 self.inner().encode(e)
184 }
185}
186
187impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'tcx> {
188 fn encode(&self, e: &mut E) {
189 self.0.0.encode(e)
190 }
191}
192
193impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AllocId {
194 fn encode(&self, e: &mut E) {
195 e.encode_alloc_id(self)
196 }
197}
198
199impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for CtfeProvenance {
200 fn encode(&self, e: &mut E) {
201 self.into_parts().encode(e);
202 }
203}
204
205impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ParamEnv<'tcx> {
206 fn encode(&self, e: &mut E) {
207 self.caller_bounds().encode(e);
208 }
209}
210
211impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
212 #[allow(rustc::usage_of_ty_tykind)]
213 fn decode(decoder: &mut D) -> Ty<'tcx> {
214 if decoder.positioned_at_shorthand() {
216 let pos = decoder.read_usize();
217 if !(pos >= SHORTHAND_OFFSET) {
::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
218 let shorthand = pos - SHORTHAND_OFFSET;
219
220 decoder.cached_ty_for_shorthand(shorthand, |decoder| {
221 decoder.with_position(shorthand, Ty::decode)
222 })
223 } else {
224 let tcx = decoder.interner();
225 tcx.mk_ty_from_kind(ty::TyKind::decode(decoder))
226 }
227 }
228}
229
230impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
231 fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
232 let bound_vars = Decodable::decode(decoder);
233 let predicate_kind = ty::Binder::bind_with_vars(
235 if decoder.positioned_at_shorthand() {
236 let pos = decoder.read_usize();
237 if !(pos >= SHORTHAND_OFFSET) {
::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
238 let shorthand = pos - SHORTHAND_OFFSET;
239
240 decoder.with_position(shorthand, <ty::PredicateKind<'tcx> as Decodable<D>>::decode)
241 } else {
242 <ty::PredicateKind<'tcx> as Decodable<D>>::decode(decoder)
243 },
244 bound_vars,
245 );
246 decoder.interner().mk_predicate(predicate_kind)
247 }
248}
249
250impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Clause<'tcx> {
251 fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
252 let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
253 pred.expect_clause()
254 }
255}
256
257impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArgsRef<'tcx> {
258 fn decode(decoder: &mut D) -> Self {
259 let len = decoder.read_usize();
260 let tcx = decoder.interner();
261 tcx.mk_args_from_iter(
262 (0..len).map::<ty::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
263 )
264 }
265}
266
267impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
268 fn decode(decoder: &mut D) -> Self {
269 let local: mir::Local = Decodable::decode(decoder);
270 let len = decoder.read_usize();
271 let projection = decoder.interner().mk_place_elems_from_iter(
272 (0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
273 );
274 mir::Place { local, projection }
275 }
276}
277
278impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarKinds<'tcx> {
279 fn decode(decoder: &mut D) -> Self {
280 let len = decoder.read_usize();
281 decoder.interner().mk_canonical_var_infos_from_iter(
282 (0..len).map::<CanonicalVarKind<'tcx>, _>(|_| Decodable::decode(decoder)),
283 )
284 }
285}
286
287impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId {
288 fn decode(decoder: &mut D) -> Self {
289 decoder.decode_alloc_id()
290 }
291}
292
293impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CtfeProvenance {
294 fn decode(decoder: &mut D) -> Self {
295 let parts = Decodable::decode(decoder);
296 CtfeProvenance::from_parts(parts)
297 }
298}
299
300impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
301 fn decode(decoder: &mut D) -> Self {
302 ty::SymbolName::new(decoder.interner(), decoder.read_str())
303 }
304}
305
306impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ParamEnv<'tcx> {
307 fn decode(d: &mut D) -> Self {
308 let caller_bounds = Decodable::decode(d);
309 ty::ParamEnv::new(caller_bounds)
310 }
311}
312
313macro_rules! impl_decodable_via_ref {
314 ($($t:ty,)+) => {
315 $(impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for $t {
316 fn decode(decoder: &mut D) -> Self {
317 RefDecodable::decode(decoder)
318 }
319 })*
320 }
321}
322
323impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<Ty<'tcx>> {
324 fn decode(decoder: &mut D) -> &'tcx Self {
325 let len = decoder.read_usize();
326 decoder
327 .interner()
328 .mk_type_list_from_iter((0..len).map::<Ty<'tcx>, _>(|_| Decodable::decode(decoder)))
329 }
330}
331
332impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D>
333 for ty::List<ty::PolyExistentialPredicate<'tcx>>
334{
335 fn decode(decoder: &mut D) -> &'tcx Self {
336 let len = decoder.read_usize();
337 decoder.interner().mk_poly_existential_predicates_from_iter(
338 (0..len).map::<ty::Binder<'tcx, _>, _>(|_| Decodable::decode(decoder)),
339 )
340 }
341}
342
343impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Const<'tcx> {
344 fn decode(decoder: &mut D) -> Self {
345 let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder);
346 decoder.interner().mk_ct_from_kind(kind)
347 }
348}
349
350impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Pattern<'tcx> {
351 fn decode(decoder: &mut D) -> Self {
352 decoder.interner().mk_pat(Decodable::decode(decoder))
353 }
354}
355
356impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ValTree<'tcx> {
357 fn decode(decoder: &mut D) -> Self {
358 decoder.interner().intern_valtree(Decodable::decode(decoder))
359 }
360}
361
362impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> {
363 fn decode(decoder: &mut D) -> Self {
364 decoder.interner().mk_const_alloc(Decodable::decode(decoder))
365 }
366}
367
368impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> {
369 fn decode(decoder: &mut D) -> Self {
370 decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder))
371 }
372}
373
374impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::Clause<'tcx>, Span)] {
375 fn decode(decoder: &mut D) -> &'tcx Self {
376 decoder
377 .interner()
378 .arena
379 .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
380 }
381}
382
383impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [(ty::PolyTraitRef<'tcx>, Span)] {
384 fn decode(decoder: &mut D) -> &'tcx Self {
385 decoder
386 .interner()
387 .arena
388 .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
389 }
390}
391
392impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for [Spanned<MonoItem<'tcx>>] {
393 fn decode(decoder: &mut D) -> &'tcx Self {
394 decoder
395 .interner()
396 .arena
397 .alloc_from_iter((0..decoder.read_usize()).map(|_| Decodable::decode(decoder)))
398 }
399}
400
401impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::BoundVariableKind<'tcx>> {
402 fn decode(decoder: &mut D) -> &'tcx Self {
403 let len = decoder.read_usize();
404 decoder.interner().mk_bound_variable_kinds_from_iter(
405 (0..len).map::<ty::BoundVariableKind<'tcx>, _>(|_| Decodable::decode(decoder)),
406 )
407 }
408}
409
410impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::Pattern<'tcx>> {
411 fn decode(decoder: &mut D) -> &'tcx Self {
412 let len = decoder.read_usize();
413 decoder.interner().mk_patterns_from_iter(
414 (0..len).map::<ty::Pattern<'tcx>, _>(|_| Decodable::decode(decoder)),
415 )
416 }
417}
418
419impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<ty::Const<'tcx>> {
420 fn decode(decoder: &mut D) -> &'tcx Self {
421 let len = decoder.read_usize();
422 decoder.interner().mk_const_list_from_iter(
423 (0..len).map::<ty::Const<'tcx>, _>(|_| Decodable::decode(decoder)),
424 )
425 }
426}
427
428impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D>
429 for ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>
430{
431 fn decode(decoder: &mut D) -> &'tcx Self {
432 let len = decoder.read_usize();
433 decoder.interner().mk_clauses_from_iter(
434 (0..len).map::<ty::Clause<'tcx>, _>(|_| Decodable::decode(decoder)),
435 )
436 }
437}
438
439impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<FieldIdx> {
440 fn decode(decoder: &mut D) -> &'tcx Self {
441 let len = decoder.read_usize();
442 decoder
443 .interner()
444 .mk_fields_from_iter((0..len).map::<FieldIdx, _>(|_| Decodable::decode(decoder)))
445 }
446}
447
448impl<'tcx, D: TyDecoder<'tcx>> RefDecodable<'tcx, D> for ty::List<LocalDefId> {
449 fn decode(decoder: &mut D) -> &'tcx Self {
450 let len = decoder.read_usize();
451 decoder.interner().mk_local_def_ids_from_iter(
452 (0..len).map::<LocalDefId, _>(|_| Decodable::decode(decoder)),
453 )
454 }
455}
456
457impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx ty::List<LocalDefId> {
458 fn decode(d: &mut D) -> Self {
459 RefDecodable::decode(d)
460 }
461}
462
463impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for &'tcx ty::List<Const<'tcx>> {
fn decode(decoder: &mut D) -> Self { RefDecodable::decode(decoder) }
}impl_decodable_via_ref! {
464 &'tcx ty::TypeckResults<'tcx>,
465 &'tcx ty::List<Ty<'tcx>>,
466 &'tcx ty::List<ty::PolyExistentialPredicate<'tcx>>,
467 &'tcx traits::ImplSource<'tcx, ()>,
468 &'tcx mir::Body<'tcx>,
469 &'tcx ty::List<ty::BoundVariableKind<'tcx>>,
470 &'tcx ty::List<ty::Pattern<'tcx>>,
471 &'tcx ty::ListWithCachedTypeInfo<ty::Clause<'tcx>>,
472 &'tcx ty::List<Const<'tcx>>,
473}
474
475#[macro_export]
476macro_rules! __impl_decoder_methods {
477 ($($name:ident -> $ty:ty;)*) => {
478 $(
479 #[inline]
480 fn $name(&mut self) -> $ty {
481 self.opaque.$name()
482 }
483 )*
484 }
485}
486
487#[macro_export]
488macro_rules! implement_ty_decoder {
489 ($DecoderName:ident <$($typaram:tt),*>) => {
490 mod __ty_decoder_impl {
491 use rustc_serialize::Decoder;
492
493 use super::$DecoderName;
494
495 impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
496 $crate::__impl_decoder_methods! {
497 read_usize -> usize;
498 read_u128 -> u128;
499 read_u64 -> u64;
500 read_u32 -> u32;
501 read_u16 -> u16;
502 read_u8 -> u8;
503
504 read_isize -> isize;
505 read_i128 -> i128;
506 read_i64 -> i64;
507 read_i32 -> i32;
508 read_i16 -> i16;
509 }
510
511 #[inline]
512 fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
513 self.opaque.read_raw_bytes(len)
514 }
515
516 #[inline]
517 fn peek_byte(&self) -> u8 {
518 self.opaque.peek_byte()
519 }
520
521 #[inline]
522 fn position(&self) -> usize {
523 self.opaque.position()
524 }
525 }
526 }
527 }
528}