]> git.proxmox.com Git - rustc.git/blob - src/librustc_middle/ty/codec.rs
New upstream version 1.45.0+dfsg1
[rustc.git] / src / librustc_middle / ty / codec.rs
1 // This module contains some shared code for encoding and decoding various
2 // things from the `ty` module, and in particular implements support for
3 // "shorthands" which allow to have pointers back into the already encoded
4 // stream instead of re-encoding the same thing twice.
5 //
6 // The functionality in here is shared between persisting to crate metadata and
7 // persisting to incr. comp. caches.
8
9 use crate::arena::ArenaAllocatable;
10 use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos};
11 use crate::mir::{self, interpret::Allocation};
12 use crate::ty::subst::SubstsRef;
13 use crate::ty::{self, List, ToPredicate, Ty, TyCtxt};
14 use rustc_data_structures::fx::FxHashMap;
15 use rustc_hir::def_id::{CrateNum, DefId};
16 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
17 use rustc_span::Span;
18 use std::convert::{TryFrom, TryInto};
19 use std::hash::Hash;
20 use std::intrinsics;
21 use std::marker::DiscriminantKind;
22
23 /// The shorthand encoding uses an enum's variant index `usize`
24 /// and is offset by this value so it never matches a real variant.
25 /// This offset is also chosen so that the first byte is never < 0x80.
26 pub const SHORTHAND_OFFSET: usize = 0x80;
27
28 pub trait EncodableWithShorthand: Clone + Eq + Hash {
29 type Variant: Encodable;
30 fn variant(&self) -> &Self::Variant;
31 }
32
33 #[allow(rustc::usage_of_ty_tykind)]
34 impl<'tcx> EncodableWithShorthand for Ty<'tcx> {
35 type Variant = ty::TyKind<'tcx>;
36 fn variant(&self) -> &Self::Variant {
37 &self.kind
38 }
39 }
40
41 impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> {
42 type Variant = ty::PredicateKind<'tcx>;
43 fn variant(&self) -> &Self::Variant {
44 self.kind()
45 }
46 }
47
48 pub trait TyEncoder: Encoder {
49 fn position(&self) -> usize;
50 }
51
52 impl TyEncoder for opaque::Encoder {
53 #[inline]
54 fn position(&self) -> usize {
55 self.position()
56 }
57 }
58
59 /// Encode the given value or a previously cached shorthand.
60 pub fn encode_with_shorthand<E, T, M>(encoder: &mut E, value: &T, cache: M) -> Result<(), E::Error>
61 where
62 E: TyEncoder,
63 M: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<T, usize>,
64 T: EncodableWithShorthand,
65 <T::Variant as DiscriminantKind>::Discriminant: Ord + TryFrom<usize>,
66 {
67 let existing_shorthand = cache(encoder).get(value).cloned();
68 if let Some(shorthand) = existing_shorthand {
69 return encoder.emit_usize(shorthand);
70 }
71
72 let variant = value.variant();
73
74 let start = encoder.position();
75 variant.encode(encoder)?;
76 let len = encoder.position() - start;
77
78 // The shorthand encoding uses the same usize as the
79 // discriminant, with an offset so they can't conflict.
80 let discriminant = intrinsics::discriminant_value(variant);
81 assert!(discriminant < SHORTHAND_OFFSET.try_into().ok().unwrap());
82
83 let shorthand = start + SHORTHAND_OFFSET;
84
85 // Get the number of bits that leb128 could fit
86 // in the same space as the fully encoded type.
87 let leb128_bits = len * 7;
88
89 // Check that the shorthand is a not longer than the
90 // full encoding itself, i.e., it's an obvious win.
91 if leb128_bits >= 64 || (shorthand as u64) < (1 << leb128_bits) {
92 cache(encoder).insert(value.clone(), shorthand);
93 }
94
95 Ok(())
96 }
97
98 pub fn encode_spanned_predicates<'tcx, E, C>(
99 encoder: &mut E,
100 predicates: &'tcx [(ty::Predicate<'tcx>, Span)],
101 cache: C,
102 ) -> Result<(), E::Error>
103 where
104 E: TyEncoder,
105 C: for<'b> Fn(&'b mut E) -> &'b mut FxHashMap<ty::Predicate<'tcx>, usize>,
106 {
107 predicates.len().encode(encoder)?;
108 for (predicate, span) in predicates {
109 encode_with_shorthand(encoder, predicate, &cache)?;
110 span.encode(encoder)?;
111 }
112 Ok(())
113 }
114
115 pub trait TyDecoder<'tcx>: Decoder {
116 fn tcx(&self) -> TyCtxt<'tcx>;
117
118 fn peek_byte(&self) -> u8;
119
120 fn position(&self) -> usize;
121
122 fn cached_ty_for_shorthand<F>(
123 &mut self,
124 shorthand: usize,
125 or_insert_with: F,
126 ) -> Result<Ty<'tcx>, Self::Error>
127 where
128 F: FnOnce(&mut Self) -> Result<Ty<'tcx>, Self::Error>;
129
130 fn with_position<F, R>(&mut self, pos: usize, f: F) -> R
131 where
132 F: FnOnce(&mut Self) -> R;
133
134 fn map_encoded_cnum_to_current(&self, cnum: CrateNum) -> CrateNum;
135
136 fn positioned_at_shorthand(&self) -> bool {
137 (self.peek_byte() & (SHORTHAND_OFFSET as u8)) != 0
138 }
139 }
140
141 #[inline]
142 pub fn decode_arena_allocable<D, T: ArenaAllocatable + Decodable>(
143 decoder: &mut D,
144 ) -> Result<&'tcx T, D::Error>
145 where
146 D: TyDecoder<'tcx>,
147 {
148 Ok(decoder.tcx().arena.alloc(Decodable::decode(decoder)?))
149 }
150
151 #[inline]
152 pub fn decode_arena_allocable_slice<D, T: ArenaAllocatable + Decodable>(
153 decoder: &mut D,
154 ) -> Result<&'tcx [T], D::Error>
155 where
156 D: TyDecoder<'tcx>,
157 {
158 Ok(decoder.tcx().arena.alloc_from_iter(<Vec<T> as Decodable>::decode(decoder)?))
159 }
160
161 #[inline]
162 pub fn decode_cnum<D>(decoder: &mut D) -> Result<CrateNum, D::Error>
163 where
164 D: TyDecoder<'tcx>,
165 {
166 let cnum = CrateNum::from_u32(u32::decode(decoder)?);
167 Ok(decoder.map_encoded_cnum_to_current(cnum))
168 }
169
170 #[allow(rustc::usage_of_ty_tykind)]
171 #[inline]
172 pub fn decode_ty<D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error>
173 where
174 D: TyDecoder<'tcx>,
175 {
176 // Handle shorthands first, if we have an usize > 0x80.
177 if decoder.positioned_at_shorthand() {
178 let pos = decoder.read_usize()?;
179 assert!(pos >= SHORTHAND_OFFSET);
180 let shorthand = pos - SHORTHAND_OFFSET;
181
182 decoder.cached_ty_for_shorthand(shorthand, |decoder| {
183 decoder.with_position(shorthand, Ty::decode)
184 })
185 } else {
186 let tcx = decoder.tcx();
187 Ok(tcx.mk_ty(ty::TyKind::decode(decoder)?))
188 }
189 }
190
191 #[inline]
192 pub fn decode_spanned_predicates<D>(
193 decoder: &mut D,
194 ) -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], D::Error>
195 where
196 D: TyDecoder<'tcx>,
197 {
198 let tcx = decoder.tcx();
199 Ok(tcx.arena.alloc_from_iter(
200 (0..decoder.read_usize()?)
201 .map(|_| {
202 // Handle shorthands first, if we have an usize > 0x80.
203 let predicate_kind = if decoder.positioned_at_shorthand() {
204 let pos = decoder.read_usize()?;
205 assert!(pos >= SHORTHAND_OFFSET);
206 let shorthand = pos - SHORTHAND_OFFSET;
207
208 decoder.with_position(shorthand, ty::PredicateKind::decode)
209 } else {
210 ty::PredicateKind::decode(decoder)
211 }?;
212 let predicate = predicate_kind.to_predicate(tcx);
213 Ok((predicate, Decodable::decode(decoder)?))
214 })
215 .collect::<Result<Vec<_>, _>>()?,
216 ))
217 }
218
219 #[inline]
220 pub fn decode_substs<D>(decoder: &mut D) -> Result<SubstsRef<'tcx>, D::Error>
221 where
222 D: TyDecoder<'tcx>,
223 {
224 let len = decoder.read_usize()?;
225 let tcx = decoder.tcx();
226 Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
227 }
228
229 #[inline]
230 pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error>
231 where
232 D: TyDecoder<'tcx>,
233 {
234 let local: mir::Local = Decodable::decode(decoder)?;
235 let len = decoder.read_usize()?;
236 let projection: &'tcx List<mir::PlaceElem<'tcx>> =
237 decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
238 Ok(mir::Place { local, projection })
239 }
240
241 #[inline]
242 pub fn decode_region<D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
243 where
244 D: TyDecoder<'tcx>,
245 {
246 Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?))
247 }
248
249 #[inline]
250 pub fn decode_ty_slice<D>(decoder: &mut D) -> Result<&'tcx ty::List<Ty<'tcx>>, D::Error>
251 where
252 D: TyDecoder<'tcx>,
253 {
254 let len = decoder.read_usize()?;
255 Ok(decoder.tcx().mk_type_list((0..len).map(|_| Decodable::decode(decoder)))?)
256 }
257
258 #[inline]
259 pub fn decode_adt_def<D>(decoder: &mut D) -> Result<&'tcx ty::AdtDef, D::Error>
260 where
261 D: TyDecoder<'tcx>,
262 {
263 let def_id = DefId::decode(decoder)?;
264 Ok(decoder.tcx().adt_def(def_id))
265 }
266
267 #[inline]
268 pub fn decode_existential_predicate_slice<D>(
269 decoder: &mut D,
270 ) -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, D::Error>
271 where
272 D: TyDecoder<'tcx>,
273 {
274 let len = decoder.read_usize()?;
275 Ok(decoder.tcx().mk_existential_predicates((0..len).map(|_| Decodable::decode(decoder)))?)
276 }
277
278 #[inline]
279 pub fn decode_canonical_var_infos<D>(decoder: &mut D) -> Result<CanonicalVarInfos<'tcx>, D::Error>
280 where
281 D: TyDecoder<'tcx>,
282 {
283 let len = decoder.read_usize()?;
284 let interned: Result<Vec<CanonicalVarInfo>, _> =
285 (0..len).map(|_| Decodable::decode(decoder)).collect();
286 Ok(decoder.tcx().intern_canonical_var_infos(interned?.as_slice()))
287 }
288
289 #[inline]
290 pub fn decode_const<D>(decoder: &mut D) -> Result<&'tcx ty::Const<'tcx>, D::Error>
291 where
292 D: TyDecoder<'tcx>,
293 {
294 Ok(decoder.tcx().mk_const(Decodable::decode(decoder)?))
295 }
296
297 #[inline]
298 pub fn decode_allocation<D>(decoder: &mut D) -> Result<&'tcx Allocation, D::Error>
299 where
300 D: TyDecoder<'tcx>,
301 {
302 Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?))
303 }
304
305 #[macro_export]
306 macro_rules! __impl_decoder_methods {
307 ($($name:ident -> $ty:ty;)*) => {
308 $(
309 #[inline]
310 fn $name(&mut self) -> Result<$ty, Self::Error> {
311 self.opaque.$name()
312 }
313 )*
314 }
315 }
316
317 #[macro_export]
318 macro_rules! impl_arena_allocatable_decoder {
319 ([]$args:tt) => {};
320 ([decode $(, $attrs:ident)*]
321 [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty], $tcx:lifetime]) => {
322 impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> {
323 #[inline]
324 fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> {
325 decode_arena_allocable(self)
326 }
327 }
328
329 impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> {
330 #[inline]
331 fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> {
332 decode_arena_allocable_slice(self)
333 }
334 }
335 };
336 ([$ignore:ident $(, $attrs:ident)*]$args:tt) => {
337 impl_arena_allocatable_decoder!([$($attrs),*]$args);
338 };
339 }
340
341 #[macro_export]
342 macro_rules! impl_arena_allocatable_decoders {
343 ($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
344 $(
345 impl_arena_allocatable_decoder!($a [$args, [$name: $ty], $tcx]);
346 )*
347 }
348 }
349
350 #[macro_export]
351 macro_rules! implement_ty_decoder {
352 ($DecoderName:ident <$($typaram:tt),*>) => {
353 mod __ty_decoder_impl {
354 use std::borrow::Cow;
355
356 use rustc_serialize::{Decoder, SpecializedDecoder};
357
358 use $crate::infer::canonical::CanonicalVarInfos;
359 use $crate::ty;
360 use $crate::ty::codec::*;
361 use $crate::ty::subst::SubstsRef;
362 use rustc_hir::def_id::{CrateNum};
363
364 use rustc_span::Span;
365
366 use super::$DecoderName;
367
368 impl<$($typaram ),*> Decoder for $DecoderName<$($typaram),*> {
369 type Error = String;
370
371 __impl_decoder_methods! {
372 read_nil -> ();
373
374 read_u128 -> u128;
375 read_u64 -> u64;
376 read_u32 -> u32;
377 read_u16 -> u16;
378 read_u8 -> u8;
379 read_usize -> usize;
380
381 read_i128 -> i128;
382 read_i64 -> i64;
383 read_i32 -> i32;
384 read_i16 -> i16;
385 read_i8 -> i8;
386 read_isize -> isize;
387
388 read_bool -> bool;
389 read_f64 -> f64;
390 read_f32 -> f32;
391 read_char -> char;
392 read_str -> Cow<'_, str>;
393 }
394
395 fn error(&mut self, err: &str) -> Self::Error {
396 self.opaque.error(err)
397 }
398 }
399
400 // FIXME(#36588): These impls are horribly unsound as they allow
401 // the caller to pick any lifetime for `'tcx`, including `'static`,
402 // by using the unspecialized proxies to them.
403
404 rustc_hir::arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
405 arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
406
407 impl<$($typaram),*> SpecializedDecoder<CrateNum>
408 for $DecoderName<$($typaram),*> {
409 fn specialized_decode(&mut self) -> Result<CrateNum, Self::Error> {
410 decode_cnum(self)
411 }
412 }
413
414 impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
415 for $DecoderName<$($typaram),*> {
416 fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
417 decode_ty(self)
418 }
419 }
420
421 impl<$($typaram),*> SpecializedDecoder<&'tcx [(ty::Predicate<'tcx>, Span)]>
422 for $DecoderName<$($typaram),*> {
423 fn specialized_decode(&mut self)
424 -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], Self::Error> {
425 decode_spanned_predicates(self)
426 }
427 }
428
429 impl<$($typaram),*> SpecializedDecoder<SubstsRef<'tcx>>
430 for $DecoderName<$($typaram),*> {
431 fn specialized_decode(&mut self) -> Result<SubstsRef<'tcx>, Self::Error> {
432 decode_substs(self)
433 }
434 }
435
436 impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>>
437 for $DecoderName<$($typaram),*> {
438 fn specialized_decode(
439 &mut self
440 ) -> Result<$crate::mir::Place<'tcx>, Self::Error> {
441 decode_place(self)
442 }
443 }
444
445 impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
446 for $DecoderName<$($typaram),*> {
447 fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
448 decode_region(self)
449 }
450 }
451
452 impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::Ty<'tcx>>>
453 for $DecoderName<$($typaram),*> {
454 fn specialized_decode(&mut self)
455 -> Result<&'tcx ty::List<ty::Ty<'tcx>>, Self::Error> {
456 decode_ty_slice(self)
457 }
458 }
459
460 impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
461 for $DecoderName<$($typaram),*> {
462 fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
463 decode_adt_def(self)
464 }
465 }
466
467 impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
468 for $DecoderName<$($typaram),*> {
469 fn specialized_decode(&mut self)
470 -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, Self::Error> {
471 decode_existential_predicate_slice(self)
472 }
473 }
474
475 impl<$($typaram),*> SpecializedDecoder<CanonicalVarInfos<'tcx>>
476 for $DecoderName<$($typaram),*> {
477 fn specialized_decode(&mut self)
478 -> Result<CanonicalVarInfos<'tcx>, Self::Error> {
479 decode_canonical_var_infos(self)
480 }
481 }
482
483 impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
484 for $DecoderName<$($typaram),*> {
485 fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
486 decode_const(self)
487 }
488 }
489
490 impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
491 for $DecoderName<$($typaram),*> {
492 fn specialized_decode(
493 &mut self
494 ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
495 decode_allocation(self)
496 }
497 }
498 }
499 }
500 }