]>
Commit | Line | Data |
---|---|---|
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 | 9 | use crate::arena::ArenaAllocatable; |
9fa01778 | 10 | use crate::infer::canonical::{CanonicalVarInfo, CanonicalVarInfos}; |
dfeec247 XL |
11 | use crate::mir::{self, interpret::Allocation}; |
12 | use crate::ty::subst::SubstsRef; | |
13 | use crate::ty::{self, List, Ty, TyCtxt}; | |
abe05a73 | 14 | use rustc_data_structures::fx::FxHashMap; |
dfeec247 XL |
15 | use rustc_hir::def_id::{CrateNum, DefId}; |
16 | use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder}; | |
17 | use rustc_span::Span; | |
abe05a73 XL |
18 | use std::hash::Hash; |
19 | use 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. | |
24 | pub const SHORTHAND_OFFSET: usize = 0x80; | |
25 | ||
26 | pub 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 | 32 | impl<'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 | ||
39 | impl<'tcx> EncodableWithShorthand for ty::Predicate<'tcx> { | |
40 | type Variant = ty::Predicate<'tcx>; | |
41 | fn variant(&self) -> &Self::Variant { | |
42 | self | |
43 | } | |
44 | } | |
45 | ||
46 | pub trait TyEncoder: Encoder { | |
47 | fn position(&self) -> usize; | |
48 | } | |
49 | ||
8faf50e0 | 50 | impl 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 |
58 | pub fn encode_with_shorthand<E, T, M>(encoder: &mut E, value: &T, cache: M) -> Result<(), E::Error> |
59 | where | |
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 |
94 | pub 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 |
99 | where |
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 |
111 | pub 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 |
138 | pub fn decode_arena_allocable<D, T: ArenaAllocatable + Decodable>( |
139 | decoder: &mut D, | |
48663c56 | 140 | ) -> Result<&'tcx T, D::Error> |
dc9dc135 XL |
141 | where |
142 | D: TyDecoder<'tcx>, | |
48663c56 XL |
143 | { |
144 | Ok(decoder.tcx().arena.alloc(Decodable::decode(decoder)?)) | |
145 | } | |
146 | ||
147 | #[inline] | |
dc9dc135 XL |
148 | pub fn decode_arena_allocable_slice<D, T: ArenaAllocatable + Decodable>( |
149 | decoder: &mut D, | |
48663c56 | 150 | ) -> Result<&'tcx [T], D::Error> |
dc9dc135 XL |
151 | where |
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 |
158 | pub fn decode_cnum<D>(decoder: &mut D) -> Result<CrateNum, D::Error> |
159 | where | |
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 |
168 | pub fn decode_ty<D>(decoder: &mut D) -> Result<Ty<'tcx>, D::Error> |
169 | where | |
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 |
188 | pub fn decode_spanned_predicates<D>( |
189 | decoder: &mut D, | |
190 | ) -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], D::Error> | |
dc9dc135 XL |
191 | where |
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 |
215 | pub fn decode_substs<D>(decoder: &mut D) -> Result<SubstsRef<'tcx>, D::Error> |
216 | where | |
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] |
225 | pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error> | |
226 | where | |
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 |
237 | pub fn decode_region<D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error> |
238 | where | |
239 | D: TyDecoder<'tcx>, | |
abe05a73 XL |
240 | { |
241 | Ok(decoder.tcx().mk_region(Decodable::decode(decoder)?)) | |
242 | } | |
243 | ||
244 | #[inline] | |
dc9dc135 XL |
245 | pub fn decode_ty_slice<D>(decoder: &mut D) -> Result<&'tcx ty::List<Ty<'tcx>>, D::Error> |
246 | where | |
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 |
254 | pub fn decode_adt_def<D>(decoder: &mut D) -> Result<&'tcx ty::AdtDef, D::Error> |
255 | where | |
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 |
263 | pub fn decode_existential_predicate_slice<D>( |
264 | decoder: &mut D, | |
265 | ) -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, D::Error> | |
266 | where | |
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 |
274 | pub fn decode_canonical_var_infos<D>(decoder: &mut D) -> Result<CanonicalVarInfos<'tcx>, D::Error> |
275 | where | |
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 |
285 | pub fn decode_const<D>(decoder: &mut D) -> Result<&'tcx ty::Const<'tcx>, D::Error> |
286 | where | |
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 |
293 | pub fn decode_allocation<D>(decoder: &mut D) -> Result<&'tcx Allocation, D::Error> |
294 | where | |
295 | D: TyDecoder<'tcx>, | |
94b46f34 XL |
296 | { |
297 | Ok(decoder.tcx().intern_const_alloc(Decodable::decode(decoder)?)) | |
298 | } | |
299 | ||
abe05a73 XL |
300 | #[macro_export] |
301 | macro_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] |
313 | macro_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] | |
337 | macro_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] |
346 | macro_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 | } |