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