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::Pattern<'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::ValTree<'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 ConstAllocation<'tcx> {
158 fn encode(&self, e: &mut E) {
159 self.inner().encode(e)
160 }
161}
162
163impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for AdtDef<'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 AllocId {
170 fn encode(&self, e: &mut E) {
171 e.encode_alloc_id(self)
172 }
173}
174
175impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for CtfeProvenance {
176 fn encode(&self, e: &mut E) {
177 self.into_parts().encode(e);
178 }
179}
180
181impl<'tcx, E: TyEncoder<'tcx>> Encodable<E> for ty::ParamEnv<'tcx> {
182 fn encode(&self, e: &mut E) {
183 self.caller_bounds.encode(e);
184 }
185}
186
187impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for Ty<'tcx> {
188 #[allow(rustc::usage_of_ty_tykind)]
189 fn decode(decoder: &mut D) -> Ty<'tcx> {
190 if decoder.positioned_at_shorthand() {
192 let pos = decoder.read_usize();
193 if !(pos >= SHORTHAND_OFFSET) {
::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
194 let shorthand = pos - SHORTHAND_OFFSET;
195
196 decoder.cached_ty_for_shorthand(shorthand, |decoder| {
197 decoder.with_position(shorthand, Ty::decode)
198 })
199 } else {
200 let tcx = decoder.interner();
201 tcx.mk_ty_from_kind(ty::TyKind::decode(decoder))
202 }
203 }
204}
205
206impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Predicate<'tcx> {
207 fn decode(decoder: &mut D) -> ty::Predicate<'tcx> {
208 let bound_vars = Decodable::decode(decoder);
209 let predicate_kind = ty::Binder::bind_with_vars(
211 if decoder.positioned_at_shorthand() {
212 let pos = decoder.read_usize();
213 if !(pos >= SHORTHAND_OFFSET) {
::core::panicking::panic("assertion failed: pos >= SHORTHAND_OFFSET")
};assert!(pos >= SHORTHAND_OFFSET);
214 let shorthand = pos - SHORTHAND_OFFSET;
215
216 decoder.with_position(shorthand, <ty::PredicateKind<'tcx> as Decodable<D>>::decode)
217 } else {
218 <ty::PredicateKind<'tcx> as Decodable<D>>::decode(decoder)
219 },
220 bound_vars,
221 );
222 decoder.interner().mk_predicate(predicate_kind)
223 }
224}
225
226impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Clause<'tcx> {
227 fn decode(decoder: &mut D) -> ty::Clause<'tcx> {
228 let pred: ty::Predicate<'tcx> = Decodable::decode(decoder);
229 pred.expect_clause()
230 }
231}
232
233impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for GenericArgsRef<'tcx> {
234 fn decode(decoder: &mut D) -> Self {
235 let len = decoder.read_usize();
236 let tcx = decoder.interner();
237 tcx.mk_args_from_iter(
238 (0..len).map::<ty::GenericArg<'tcx>, _>(|_| Decodable::decode(decoder)),
239 )
240 }
241}
242
243impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for mir::Place<'tcx> {
244 fn decode(decoder: &mut D) -> Self {
245 let local: mir::Local = Decodable::decode(decoder);
246 let len = decoder.read_usize();
247 let projection = decoder.interner().mk_place_elems_from_iter(
248 (0..len).map::<mir::PlaceElem<'tcx>, _>(|_| Decodable::decode(decoder)),
249 );
250 mir::Place { local, projection }
251 }
252}
253
254impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CanonicalVarKinds<'tcx> {
255 fn decode(decoder: &mut D) -> Self {
256 let len = decoder.read_usize();
257 decoder.interner().mk_canonical_var_infos_from_iter(
258 (0..len).map::<CanonicalVarKind<'tcx>, _>(|_| Decodable::decode(decoder)),
259 )
260 }
261}
262
263impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AllocId {
264 fn decode(decoder: &mut D) -> Self {
265 decoder.decode_alloc_id()
266 }
267}
268
269impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for CtfeProvenance {
270 fn decode(decoder: &mut D) -> Self {
271 let parts = Decodable::decode(decoder);
272 CtfeProvenance::from_parts(parts)
273 }
274}
275
276impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::SymbolName<'tcx> {
277 fn decode(decoder: &mut D) -> Self {
278 ty::SymbolName::new(decoder.interner(), decoder.read_str())
279 }
280}
281
282impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ParamEnv<'tcx> {
283 fn decode(d: &mut D) -> Self {
284 let caller_bounds = Decodable::decode(d);
285 ty::ParamEnv { caller_bounds }
286 }
287}
288
289impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::Pattern<'tcx> {
290 fn decode(decoder: &mut D) -> Self {
291 decoder.interner().mk_pat(Decodable::decode(decoder))
292 }
293}
294
295impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ty::ValTree<'tcx> {
296 fn decode(decoder: &mut D) -> Self {
297 decoder.interner().intern_valtree(Decodable::decode(decoder))
298 }
299}
300
301impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for ConstAllocation<'tcx> {
302 fn decode(decoder: &mut D) -> Self {
303 decoder.interner().mk_const_alloc(Decodable::decode(decoder))
304 }
305}
306
307impl<'tcx, D: TyDecoder<'tcx>> Decodable<D> for AdtDef<'tcx> {
308 fn decode(decoder: &mut D) -> Self {
309 decoder.interner().mk_adt_def_from_data(Decodable::decode(decoder))
310 }
311}
312
313pub macro forward_all_decoder_methods_to {
319 (
320 |$self:ident| $inner:expr
326 ) => {
327 #[inline] fn read_usize(&mut $self) -> usize { $inner.read_usize() }
328 #[inline] fn read_u128 (&mut $self) -> u128 { $inner.read_u128() }
329 #[inline] fn read_u64 (&mut $self) -> u64 { $inner.read_u64() }
330 #[inline] fn read_u32 (&mut $self) -> u32 { $inner.read_u32() }
331 #[inline] fn read_u16 (&mut $self) -> u16 { $inner.read_u16() }
332 #[inline] fn read_u8 (&mut $self) -> u8 { $inner.read_u8() }
333 #[inline] fn read_isize(&mut $self) -> isize { $inner.read_isize() }
334 #[inline] fn read_i128 (&mut $self) -> i128 { $inner.read_i128() }
335 #[inline] fn read_i64 (&mut $self) -> i64 { $inner.read_i64() }
336 #[inline] fn read_i32 (&mut $self) -> i32 { $inner.read_i32() }
337 #[inline] fn read_i16 (&mut $self) -> i16 { $inner.read_i16() }
338
339 #[inline]
340 fn read_raw_bytes(&mut $self, len: usize) -> &[u8] {
341 $inner.read_raw_bytes(len)
342 }
343
344 #[inline]
345 fn peek_byte(&$self) -> u8 {
346 $inner.peek_byte()
347 }
348
349 #[inline]
350 fn position(&$self) -> usize {
351 $inner.position()
352 }
353 }
354}