Skip to content

Commit a4daa63

Browse files
committed
rustc_serialize: specialize opaque encoding of some u8 sequences
1 parent 417fe47 commit a4daa63

File tree

6 files changed

+32
-21
lines changed

6 files changed

+32
-21
lines changed

compiler/rustc_macros/src/serialize.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ fn encodable_body(
203203
#field_name,
204204
#field_idx,
205205
|__encoder|
206-
::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
206+
::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
207207
) {
208208
::std::result::Result::Ok(()) => (),
209209
::std::result::Result::Err(__err)
@@ -237,7 +237,7 @@ fn encodable_body(
237237
__encoder,
238238
#field_idx,
239239
|__encoder|
240-
::rustc_serialize::Encodable::encode(#bind_ident, __encoder),
240+
::rustc_serialize::Encodable::<#encoder_ty>::encode(#bind_ident, __encoder),
241241
) {
242242
::std::result::Result::Ok(()) => (),
243243
::std::result::Result::Err(__err)

compiler/rustc_middle/src/ty/query/on_disk_cache.rs

+10
Original file line numberDiff line numberDiff line change
@@ -1149,6 +1149,16 @@ where
11491149
}
11501150
}
11511151

1152+
// This ensures that the `Encodable<opaque::Encoder>::encode` specialization for byte slices
1153+
// is used when a `CacheEncoder` having an `opaque::Encoder` is passed to `Encodable::encode`.
1154+
// Unfortunately, we have to manually opt into specializations this way, given how `CacheEncoder`
1155+
// and the encoding traits currently work.
1156+
impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx, opaque::Encoder>> for [u8] {
1157+
fn encode(&self, e: &mut CacheEncoder<'a, 'tcx, opaque::Encoder>) -> opaque::EncodeResult {
1158+
self.encode(e.encoder)
1159+
}
1160+
}
1161+
11521162
// An integer that will always encode to 8 bytes.
11531163
struct IntEncodedWithFixedSize(u64);
11541164

compiler/rustc_serialize/src/collection_impls.rs

+6-18
Original file line numberDiff line numberDiff line change
@@ -11,12 +11,8 @@ use smallvec::{Array, SmallVec};
1111

1212
impl<S: Encoder, A: Array<Item: Encodable<S>>> Encodable<S> for SmallVec<A> {
1313
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
14-
s.emit_seq(self.len(), |s| {
15-
for (i, e) in self.iter().enumerate() {
16-
s.emit_seq_elt(i, |s| e.encode(s))?;
17-
}
18-
Ok(())
19-
})
14+
let slice: &[A::Item] = self;
15+
slice.encode(s)
2016
}
2117
}
2218

@@ -292,12 +288,8 @@ where
292288

293289
impl<E: Encoder, T: Encodable<E>> Encodable<E> for Rc<[T]> {
294290
fn encode(&self, s: &mut E) -> Result<(), E::Error> {
295-
s.emit_seq(self.len(), |s| {
296-
for (index, e) in self.iter().enumerate() {
297-
s.emit_seq_elt(index, |s| e.encode(s))?;
298-
}
299-
Ok(())
300-
})
291+
let slice: &[T] = self;
292+
slice.encode(s)
301293
}
302294
}
303295

@@ -315,12 +307,8 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<[T]> {
315307

316308
impl<E: Encoder, T: Encodable<E>> Encodable<E> for Arc<[T]> {
317309
fn encode(&self, s: &mut E) -> Result<(), E::Error> {
318-
s.emit_seq(self.len(), |s| {
319-
for (index, e) in self.iter().enumerate() {
320-
s.emit_seq_elt(index, |s| e.encode(s))?;
321-
}
322-
Ok(())
323-
})
310+
let slice: &[T] = self;
311+
slice.encode(s)
324312
}
325313
}
326314

compiler/rustc_serialize/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ Core encoding and decoding interfaces.
1414
#![feature(nll)]
1515
#![feature(associated_type_bounds)]
1616
#![cfg_attr(bootstrap, feature(min_const_generics))]
17+
#![feature(min_specialization)]
1718
#![cfg_attr(test, feature(test))]
1819
#![allow(rustc::internal)]
1920

compiler/rustc_serialize/src/opaque.rs

+12
Original file line numberDiff line numberDiff line change
@@ -316,3 +316,15 @@ impl<'a> serialize::Decoder for Decoder<'a> {
316316
err.to_string()
317317
}
318318
}
319+
320+
// Specialize encoding byte slices. The default implementation for slices encodes and emits each
321+
// element individually. This isn't necessary for `u8` slices encoded with an `opaque::Encoder`,
322+
// because each `u8` is emitted as-is. Therefore, we can use a more efficient implementation. This
323+
// specialization applies to encoding `Vec<u8>`s, etc., since they call `encode` on their slices.
324+
impl serialize::Encodable<Encoder> for [u8] {
325+
fn encode(&self, e: &mut Encoder) -> EncodeResult {
326+
serialize::Encoder::emit_usize(e, self.len())?;
327+
e.emit_raw_bytes(self);
328+
Ok(())
329+
}
330+
}

compiler/rustc_serialize/src/serialize.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Rc<T> {
527527
}
528528

529529
impl<S: Encoder, T: Encodable<S>> Encodable<S> for [T] {
530-
fn encode(&self, s: &mut S) -> Result<(), S::Error> {
530+
default fn encode(&self, s: &mut S) -> Result<(), S::Error> {
531531
s.emit_seq(self.len(), |s| {
532532
for (i, e) in self.iter().enumerate() {
533533
s.emit_seq_elt(i, |s| e.encode(s))?

0 commit comments

Comments
 (0)