1use std::hash::Hash;
10use std::intrinsics;
11use std::marker::DiscriminantKind;
12
13use rustc_data_structures::fx::FxHashMap;
14use rustc_serialize::{Decodable, Encodable};
15use rustc_span::{SpanDecoder, SpanEncoder};
16
17pub use self::ref_decodable::RefDecodable;
18use crate::infer::canonical::{CanonicalVarKind, CanonicalVarKinds};
19use crate::mir;
20use crate::mir::interpret::{AllocId, ConstAllocation, CtfeProvenance};
21use crate::ty::{self, AdtDef, GenericArgsRef, Ty, TyCtxt};
22
23mod ref_decodable;
24
25pub const SHORTHAND_OFFSET: usize = 0x80;
29
30pub trait TyEncoder<'tcx>: SpanEncoder {
31 const CLEAR_CROSS_CRATE: bool;
32
33 fn position(&self) -> usize;
34
35 fn type_shorthands(&mut self) -> &mut FxHashMap<Ty<'tcx>, usize>;
36
37 fn predicate_shorthands(&mut self) -> &mut FxHashMap<ty::PredicateKind<'tcx>, usize>;
38
39 fn encode_alloc_id(&mut self, alloc_id: &AllocId);
40}
41
42pub trait TyDecoder<'tcx>:
43 SpanDecoder + rustc_type_ir::InternerDecoder<Interner = TyCtxt<'tcx>>
44{
45 const CLEAR_CROSS_CRATE: bool;
46
47 fn cached_ty_for_shorthand<F>(&mut self, shorthand: usize, or_insert_with: F) -> Ty<'tcx>
48 where
49 F: FnOnce(&mut Self) -> Ty<'tcx>;
50
51 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
52 where
53 F: FnOnce(&mut Self) -> R;
54
55 fn positioned_at_shorthand(&self) -> bool {
56 (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
57 }
58
59 fn decode_alloc_id(&mut self) -> AllocId;
60}
61
62pub trait EncodableWithShorthand<'tcx, E: TyEncoder<'tcx>>: Copy + Eq + Hash {
63 type Variant: Encodable<E>;
64 fn variant(&self) -> &Self::Variant;
65}
66
67#[allow(rustc::usage_of_ty_tykind)]
68impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for Ty<'tcx> {
69 type Variant = ty::TyKind<'tcx>;
70
71 #[inline]
72 fn variant(&self) -> &Self::Variant {
73 self.kind()
74 }
75}
76
77impl<'tcx, E: TyEncoder<'tcx>> EncodableWithShorthand<'tcx, E> for ty::PredicateKind<'tcx> {
78 type Variant = ty::PredicateKind<'tcx>;
79
80 #[inline]
81 fn variant(&self) -> &Self::Variant {
82 self
83 }
84}
85
86pub fn encode_with_shorthand<'tcx, E, T, M>(encoder: &mut E, value: &T, cache: M)
88where
89 E: TyEncoder<'tcx>,
90 M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
91 T: EncodableWithShorthand<'tcx, E>,
92 T::Variant: DiscriminantKind<Discriminant = isize>,
94{
95 let existing_shorthand = cache(encoder).get(value).copied();
96 if let Some(shorthand) = existing_shorthand {
97 encoder.emit_usize(shorthand);
98 return;
99 }
100
101 let variant = value.variant();
102
103 let start = encoder.position();
104 variant.encode(encoder);
105 let len = encoder.position() - start;
106
107 let discriminant = intrinsics::discriminant_value(variant);
110 if !(SHORTHAND_OFFSET > discriminant as usize) {
::core::panicking::panic("assertion failed: SHORTHAND_OFFSET > discriminant as usize")
};assert!(SHORTHAND_OFFSET > discriminant as usize);
111
112 let shorthand = start + SHORTHAND_OFFSET;
113
114 let leb128_bits = len * 7;
117
118 if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
121 cache(encoder).insert(*value, shorthand);
122 }
123}
124
125impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for Ty<'tcx> {
126 fn encode(&self, e: &mut E) {
127 encode_with_shorthand(e, self, TyEncoder::type_shorthands);
128 }
129}
130
131impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Predicate<'tcx> {
132 fn encode(&self, e: &mut E) {
133 let kind = self.kind();
134 kind.bound_vars().encode(e);
135 encode_with_shorthand(e, &kind.skip_binder(), TyEncoder::predicate_shorthands);
136 }
137}
138
139impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Clause<'tcx> {
140 fn encode(&self, e: &mut E) {
141 self.as_predicate().encode(e);
142 }
143}
144
145impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Const<'tcx> {
146 fn encode(&self, e: &mut E) {
147 self.0.0.encode(e);
148 }
149}
150
151impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::Pattern<'tcx> {
152 fn encode(&self, e: &mut E) {
153 self.0.0.encode(e);
154 }
155}
156
157impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ValTree<'tcx> {
158 fn encode(&self, e: &mut E) {
159 self.0.0.encode(e);
160 }
161}
162
163impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ConstAllocation<'tcx> {
164 fn encode(&self, e: &mut E) {
165 self.inner().encode(e)
166 }
167}
168
169impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'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 AllocId {
176 fn encode(&self, e: &mut E) {
177 e.encode_alloc_id(self)
178 }
179}
180
181impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for CtfeProvenance {
182 fn encode(&self, e: &mut E) {
183 self.into_parts().encode(e);
184 }
185}
186
187impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ParamEnv<'tcx> {
188 fn encode(&self, e: &mut E) {
189 self.caller_bounds.encode(e);
190 }
191}
192
193impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
194 #[allow(rustc::usage_of_ty_tykind)]
195 fn decode(decoder: &mut D) -> Ty<'tcx> {
196 if decoder.positioned_at_shorthand() {
198 let pos = decoder.read_usize();
199 if !(pos >= SHORTHAND_OFFSET) {
::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
200 let shorthand = pos - SHORTHAND_OFFSET;
201
202 decoder.cached_ty_for_shorthand(shorthand, |decoder| {
203 decoder.with_position(shorthand, Ty::decode)
204 })
205 } else {
206 let tcx = decoder.interner();
207 tcx.mk_ty_from_kind(ty::TyKind::decode(decoder))
208 }
209 }
210}
211
212impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
213 fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
214 let bound_vars = Decodable::decode(decoder);
215 let predicate_kind = ty::Binder::bind_with_vars(
217 if decoder.positioned_at_shorthand() {
218 let pos = decoder.read_usize();
219 if !(pos >= SHORTHAND_OFFSET) {
::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
220 let shorthand = pos - SHORTHAND_OFFSET;
221
222 decoder.with_position(shorthand, <ty::PredicateKind<'tcx> as Decodable<D>>::decode)
223 } else {
224 <ty::PredicateKind<'tcx> as Decodable<D>>::decode(decoder)
225 },
226 bound_vars,
227 );
228 decoder.interner().mk_predicate(predicate_kind)
229 }
230}
231
232impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Clause<'tcx> {
233 fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
234 let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
235 pred.expect_clause()
236 }
237}
238
239impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArgsRef<'tcx> {
240 fn decode(decoder: &mut D) -> Self {
241 let len = decoder.read_usize();
242 let tcx = decoder.interner();
243 tcx.mk_args_from_iter(
244 (0..len).map::<ty::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
245 )
246 }
247}
248
249impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
250 fn decode(decoder: &mut D) -> Self {
251 let local: mir::Local = Decodable::decode(decoder);
252 let len = decoder.read_usize();
253 let projection = decoder.interner().mk_place_elems_from_iter(
254 (0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
255 );
256 mir::Place { local, projection }
257 }
258}
259
260impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarKinds<'tcx> {
261 fn decode(decoder: &mut D) -> Self {
262 let len = decoder.read_usize();
263 decoder.interner().mk_canonical_var_infos_from_iter(
264 (0..len).map::<CanonicalVarKind<'tcx>, _>(|_| Decodable::decode(decoder)),
265 )
266 }
267}
268
269impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId {
270 fn decode(decoder: &mut D) -> Self {
271 decoder.decode_alloc_id()
272 }
273}
274
275impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CtfeProvenance {
276 fn decode(decoder: &mut D) -> Self {
277 let parts = Decodable::decode(decoder);
278 CtfeProvenance::from_parts(parts)
279 }
280}
281
282impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
283 fn decode(decoder: &mut D) -> Self {
284 ty::SymbolName::new(decoder.interner(), decoder.read_str())
285 }
286}
287
288impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ParamEnv<'tcx> {
289 fn decode(d: &mut D) -> Self {
290 let caller_bounds = Decodable::decode(d);
291 ty::ParamEnv { caller_bounds }
292 }
293}
294
295impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Const<'tcx> {
296 fn decode(decoder: &mut D) -> Self {
297 let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder);
298 decoder.interner().mk_ct_from_kind(kind)
299 }
300}
301
302impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Pattern<'tcx> {
303 fn decode(decoder: &mut D) -> Self {
304 decoder.interner().mk_pat(Decodable::decode(decoder))
305 }
306}
307
308impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ValTree<'tcx> {
309 fn decode(decoder: &mut D) -> Self {
310 decoder.interner().intern_valtree(Decodable::decode(decoder))
311 }
312}
313
314impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> {
315 fn decode(decoder: &mut D) -> Self {
316 decoder.interner().mk_const_alloc(Decodable::decode(decoder))
317 }
318}
319
320impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> {
321 fn decode(decoder: &mut D) -> Self {
322 decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder))
323 }
324}
325
326#[macro_export]
327macro_rules! __impl_decoder_methods {
328 ($($name:ident -> $ty:ty;)*) => {
329 $(
330 #[inline]
331 fn $name(&mut self) -> $ty {
332 self.opaque.$name()
333 }
334 )*
335 }
336}
337
338#[macro_export]
339macro_rules! implement_ty_decoder {
340 ($DecoderName:ident <$($typaram:tt),*>) => {
341 mod __ty_decoder_impl {
342 use rustc_serialize::Decoder;
343
344 use super::$DecoderName;
345
346 impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
347 $crate::__impl_decoder_methods! {
348 read_usize -> usize;
349 read_u128 -> u128;
350 read_u64 -> u64;
351 read_u32 -> u32;
352 read_u16 -> u16;
353 read_u8 -> u8;
354
355 read_isize -> isize;
356 read_i128 -> i128;
357 read_i64 -> i64;
358 read_i32 -> i32;
359 read_i16 -> i16;
360 }
361
362 #[inline]
363 fn read_raw_bytes(&mut self, len: usize) -> &[u8] {
364 self.opaque.read_raw_bytes(len)
365 }
366
367 #[inline]
368 fn peek_byte(&self) -> u8 {
369 self.opaque.peek_byte()
370 }
371
372 #[inline]
373 fn position(&self) -> usize {
374 self.opaque.position()
375 }
376 }
377 }
378 }
379}