about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--compiler/rustc_codegen_ssa/src/lib.rs10
-rw-r--r--compiler/rustc_interface/src/queries.rs3
-rw-r--r--compiler/rustc_serialize/Cargo.toml1
-rw-r--r--compiler/rustc_serialize/src/opaque.rs129
-rw-r--r--compiler/rustc_serialize/tests/opaque.rs56
-rw-r--r--tests/ui-fulldeps/deriving-encodable-decodable-box.rs34
-rw-r--r--tests/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs44
-rw-r--r--tests/ui-fulldeps/issue-14021.rs33
9 files changed, 63 insertions, 248 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 3dfe558afa6..0b0182472aa 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4060,6 +4060,7 @@ dependencies = [
  "indexmap",
  "rustc_macros",
  "smallvec",
+ "tempfile",
  "thin-vec",
 ]
 
diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs
index 26d55618b49..c3cc17c255b 100644
--- a/compiler/rustc_codegen_ssa/src/lib.rs
+++ b/compiler/rustc_codegen_ssa/src/lib.rs
@@ -31,7 +31,7 @@ use rustc_middle::dep_graph::WorkProduct;
 use rustc_middle::middle::dependency_format::Dependencies;
 use rustc_middle::middle::exported_symbols::SymbolExportKind;
 use rustc_middle::ty::query::{ExternProviders, Providers};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
+use rustc_serialize::opaque::{FileEncoder, MemDecoder};
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OutputFilenames, OutputType, RUST_CGU_EXT};
 use rustc_session::cstore::{self, CrateSource};
@@ -39,6 +39,7 @@ use rustc_session::utils::NativeLibKind;
 use rustc_span::symbol::Symbol;
 use rustc_span::DebuggerVisualizerFile;
 use std::collections::BTreeSet;
+use std::io;
 use std::path::{Path, PathBuf};
 
 pub mod back;
@@ -215,8 +216,11 @@ const RLINK_MAGIC: &[u8] = b"rustlink";
 const RUSTC_VERSION: Option<&str> = option_env!("CFG_VERSION");
 
 impl CodegenResults {
-    pub fn serialize_rlink(codegen_results: &CodegenResults) -> Vec<u8> {
-        let mut encoder = MemEncoder::new();
+    pub fn serialize_rlink(
+        rlink_file: &Path,
+        codegen_results: &CodegenResults,
+    ) -> Result<usize, io::Error> {
+        let mut encoder = FileEncoder::new(rlink_file)?;
         encoder.emit_raw_bytes(RLINK_MAGIC);
         // `emit_raw_bytes` is used to make sure that the version representation does not depend on
         // Encoder's inner representation of `u32`.
diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs
index 77fbbf64a0a..6483d51a0b9 100644
--- a/compiler/rustc_interface/src/queries.rs
+++ b/compiler/rustc_interface/src/queries.rs
@@ -368,9 +368,8 @@ impl Linker {
         }
 
         if sess.opts.unstable_opts.no_link {
-            let encoded = CodegenResults::serialize_rlink(&codegen_results);
             let rlink_file = self.prepare_outputs.with_extension(config::RLINK_EXT);
-            std::fs::write(&rlink_file, encoded)
+            CodegenResults::serialize_rlink(&rlink_file, &codegen_results)
                 .map_err(|error| sess.emit_fatal(FailedWritingFile { path: &rlink_file, error }))?;
             return Ok(());
         }
diff --git a/compiler/rustc_serialize/Cargo.toml b/compiler/rustc_serialize/Cargo.toml
index e4dbb8a637c..6046780685a 100644
--- a/compiler/rustc_serialize/Cargo.toml
+++ b/compiler/rustc_serialize/Cargo.toml
@@ -10,3 +10,4 @@ thin-vec = "0.2.12"
 
 [dev-dependencies]
 rustc_macros = { path = "../rustc_macros" }
+tempfile = "3.2"
diff --git a/compiler/rustc_serialize/src/opaque.rs b/compiler/rustc_serialize/src/opaque.rs
index 0f6e4b329b8..a2ec318df6d 100644
--- a/compiler/rustc_serialize/src/opaque.rs
+++ b/compiler/rustc_serialize/src/opaque.rs
@@ -12,118 +12,14 @@ use std::ptr;
 // Encoder
 // -----------------------------------------------------------------------------
 
-pub struct MemEncoder {
-    pub data: Vec<u8>,
-}
-
-impl MemEncoder {
-    pub fn new() -> MemEncoder {
-        MemEncoder { data: vec![] }
-    }
-
-    #[inline]
-    pub fn position(&self) -> usize {
-        self.data.len()
-    }
-
-    pub fn finish(self) -> Vec<u8> {
-        self.data
-    }
-}
-
-macro_rules! write_leb128 {
-    ($enc:expr, $value:expr, $int_ty:ty, $fun:ident) => {{
-        const MAX_ENCODED_LEN: usize = $crate::leb128::max_leb128_len::<$int_ty>();
-        let old_len = $enc.data.len();
-
-        if MAX_ENCODED_LEN > $enc.data.capacity() - old_len {
-            $enc.data.reserve(MAX_ENCODED_LEN);
-        }
-
-        // SAFETY: The above check and `reserve` ensures that there is enough
-        // room to write the encoded value to the vector's internal buffer.
-        unsafe {
-            let buf = &mut *($enc.data.as_mut_ptr().add(old_len)
-                as *mut [MaybeUninit<u8>; MAX_ENCODED_LEN]);
-            let encoded = leb128::$fun(buf, $value);
-            $enc.data.set_len(old_len + encoded.len());
-        }
-    }};
-}
-
-impl Encoder for MemEncoder {
-    #[inline]
-    fn emit_usize(&mut self, v: usize) {
-        write_leb128!(self, v, usize, write_usize_leb128)
-    }
-
-    #[inline]
-    fn emit_u128(&mut self, v: u128) {
-        write_leb128!(self, v, u128, write_u128_leb128);
-    }
-
-    #[inline]
-    fn emit_u64(&mut self, v: u64) {
-        write_leb128!(self, v, u64, write_u64_leb128);
-    }
-
-    #[inline]
-    fn emit_u32(&mut self, v: u32) {
-        write_leb128!(self, v, u32, write_u32_leb128);
-    }
-
-    #[inline]
-    fn emit_u16(&mut self, v: u16) {
-        self.data.extend_from_slice(&v.to_le_bytes());
-    }
-
-    #[inline]
-    fn emit_u8(&mut self, v: u8) {
-        self.data.push(v);
-    }
-
-    #[inline]
-    fn emit_isize(&mut self, v: isize) {
-        write_leb128!(self, v, isize, write_isize_leb128)
-    }
-
-    #[inline]
-    fn emit_i128(&mut self, v: i128) {
-        write_leb128!(self, v, i128, write_i128_leb128)
-    }
-
-    #[inline]
-    fn emit_i64(&mut self, v: i64) {
-        write_leb128!(self, v, i64, write_i64_leb128)
-    }
-
-    #[inline]
-    fn emit_i32(&mut self, v: i32) {
-        write_leb128!(self, v, i32, write_i32_leb128)
-    }
-
-    #[inline]
-    fn emit_i16(&mut self, v: i16) {
-        self.data.extend_from_slice(&v.to_le_bytes());
-    }
-
-    #[inline]
-    fn emit_raw_bytes(&mut self, s: &[u8]) {
-        self.data.extend_from_slice(s);
-    }
-}
-
 pub type FileEncodeResult = Result<usize, io::Error>;
 
 /// `FileEncoder` encodes data to file via fixed-size buffer.
 ///
-/// When encoding large amounts of data to a file, using `FileEncoder` may be
-/// preferred over using `MemEncoder` to encode to a `Vec`, and then writing the
-/// `Vec` to file, as the latter uses as much memory as there is encoded data,
-/// while the former uses the fixed amount of memory allocated to the buffer.
-/// `FileEncoder` also has the advantage of not needing to reallocate as data
-/// is appended to it, but the disadvantage of requiring more error handling,
-/// which has some runtime overhead.
+/// There used to be a `MemEncoder` type that encoded all the data into a
+/// `Vec`. `FileEncoder` is better because its memory use is determined by the
+/// size of the buffer, rather than the full length of the encoded data, and
+/// because it doesn't need to reallocate memory along the way.
 pub struct FileEncoder {
     /// The input buffer. For adequate performance, we need more control over
     /// buffering than `BufWriter` offers. If `BufWriter` ever offers a raw
@@ -645,13 +541,6 @@ impl<'a> Decoder for MemDecoder<'a> {
 
 // Specialize encoding byte slices. This specialization also applies to encoding `Vec<u8>`s, etc.,
 // since the default implementations call `encode` on their slices internally.
-impl Encodable<MemEncoder> for [u8] {
-    fn encode(&self, e: &mut MemEncoder) {
-        Encoder::emit_usize(e, self.len());
-        e.emit_raw_bytes(self);
-    }
-}
-
 impl Encodable<FileEncoder> for [u8] {
     fn encode(&self, e: &mut FileEncoder) {
         Encoder::emit_usize(e, self.len());
@@ -675,16 +564,6 @@ impl IntEncodedWithFixedSize {
     pub const ENCODED_SIZE: usize = 8;
 }
 
-impl Encodable<MemEncoder> for IntEncodedWithFixedSize {
-    #[inline]
-    fn encode(&self, e: &mut MemEncoder) {
-        let _start_pos = e.position();
-        e.emit_raw_bytes(&self.0.to_le_bytes());
-        let _end_pos = e.position();
-        debug_assert_eq!((_end_pos - _start_pos), IntEncodedWithFixedSize::ENCODED_SIZE);
-    }
-}
-
 impl Encodable<FileEncoder> for IntEncodedWithFixedSize {
     #[inline]
     fn encode(&self, e: &mut FileEncoder) {
diff --git a/compiler/rustc_serialize/tests/opaque.rs b/compiler/rustc_serialize/tests/opaque.rs
index 5e7dd18aa84..861091688bb 100644
--- a/compiler/rustc_serialize/tests/opaque.rs
+++ b/compiler/rustc_serialize/tests/opaque.rs
@@ -1,9 +1,10 @@
 #![allow(rustc::internal)]
 
 use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
+use rustc_serialize::opaque::{MemDecoder, FileEncoder};
 use rustc_serialize::{Decodable, Encodable};
 use std::fmt::Debug;
+use std::fs;
 
 #[derive(PartialEq, Clone, Debug, Encodable, Decodable)]
 struct Struct {
@@ -27,18 +28,21 @@ struct Struct {
 }
 
 fn check_round_trip<
-    T: Encodable<MemEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug,
+    T: Encodable<FileEncoder> + for<'a> Decodable<MemDecoder<'a>> + PartialEq + Debug,
 >(
     values: Vec<T>,
 ) {
-    let mut encoder = MemEncoder::new();
+    let tmpfile = tempfile::NamedTempFile::new().unwrap();
+    let tmpfile = tmpfile.path();
+
+    let mut encoder = FileEncoder::new(&tmpfile).unwrap();
     for value in &values {
         Encodable::encode(value, &mut encoder);
     }
+    encoder.finish().unwrap();
 
-    let data = encoder.finish();
+    let data = fs::read(&tmpfile).unwrap();
     let mut decoder = MemDecoder::new(&data[..], 0);
-
     for value in values {
         let decoded = Decodable::decode(&mut decoder);
         assert_eq!(value, decoded);
@@ -61,7 +65,7 @@ fn test_u8() {
 
 #[test]
 fn test_u16() {
-    for i in u16::MIN..u16::MAX {
+    for i in [u16::MIN, 111, 3333, 55555, u16::MAX] {
         check_round_trip(vec![1, 2, 3, i, i, i]);
     }
 }
@@ -92,7 +96,7 @@ fn test_i8() {
 
 #[test]
 fn test_i16() {
-    for i in i16::MIN..i16::MAX {
+    for i in [i16::MIN, -100, 0, 101, i16::MAX] {
         check_round_trip(vec![-1, 2, -3, i, i, i, 2]);
     }
 }
@@ -251,3 +255,41 @@ fn test_tuples() {
     check_round_trip(vec![(1234567isize, 100000000000000u64, 99999999999999i64)]);
     check_round_trip(vec![(String::new(), "some string".to_string())]);
 }
+
+#[test]
+fn test_unit_like_struct() {
+    #[derive(Encodable, Decodable, PartialEq, Debug)]
+    struct UnitLikeStruct;
+
+    check_round_trip(vec![UnitLikeStruct]);
+}
+
+#[test]
+fn test_box() {
+    #[derive(Encodable, Decodable, PartialEq, Debug)]
+    struct A {
+        foo: Box<[bool]>,
+    }
+
+    let obj = A { foo: Box::new([true, false]) };
+    check_round_trip(vec![obj]);
+}
+
+#[test]
+fn test_cell() {
+    use std::cell::{Cell, RefCell};
+
+    #[derive(Encodable, Decodable, PartialEq, Debug)]
+    struct A {
+        baz: isize,
+    }
+
+    #[derive(Encodable, Decodable, PartialEq, Debug)]
+    struct B {
+        foo: Cell<bool>,
+        bar: RefCell<A>,
+    }
+
+    let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
+    check_round_trip(vec![obj]);
+}
diff --git a/tests/ui-fulldeps/deriving-encodable-decodable-box.rs b/tests/ui-fulldeps/deriving-encodable-decodable-box.rs
deleted file mode 100644
index 1c376f59e51..00000000000
--- a/tests/ui-fulldeps/deriving-encodable-decodable-box.rs
+++ /dev/null
@@ -1,34 +0,0 @@
-// run-pass
-
-#![allow(unused_imports)]
-#![feature(rustc_private)]
-
-extern crate rustc_macros;
-extern crate rustc_serialize;
-
-// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
-// files.
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
-
-use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
-use rustc_serialize::{Decodable, Encodable, Encoder};
-
-#[derive(Encodable, Decodable)]
-struct A {
-    foo: Box<[bool]>,
-}
-
-fn main() {
-    let obj = A { foo: Box::new([true, false]) };
-
-    let mut encoder = MemEncoder::new();
-    obj.encode(&mut encoder);
-    let data = encoder.finish();
-
-    let mut decoder = MemDecoder::new(&data, 0);
-    let obj2 = A::decode(&mut decoder);
-
-    assert_eq!(obj.foo, obj2.foo);
-}
diff --git a/tests/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs b/tests/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs
deleted file mode 100644
index 844d40f2ecd..00000000000
--- a/tests/ui-fulldeps/deriving-encodable-decodable-cell-refcell.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-// run-pass
-
-#![allow(unused_imports)]
-// This briefly tests the capability of `Cell` and `RefCell` to implement the
-// `Encodable` and `Decodable` traits via `#[derive(Encodable, Decodable)]`
-#![feature(rustc_private)]
-
-extern crate rustc_macros;
-extern crate rustc_serialize;
-
-// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
-// files.
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
-
-use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
-use rustc_serialize::{Decodable, Encodable, Encoder};
-use std::cell::{Cell, RefCell};
-
-#[derive(Encodable, Decodable)]
-struct A {
-    baz: isize,
-}
-
-#[derive(Encodable, Decodable)]
-struct B {
-    foo: Cell<bool>,
-    bar: RefCell<A>,
-}
-
-fn main() {
-    let obj = B { foo: Cell::new(true), bar: RefCell::new(A { baz: 2 }) };
-
-    let mut encoder = MemEncoder::new();
-    obj.encode(&mut encoder);
-    let data = encoder.finish();
-
-    let mut decoder = MemDecoder::new(&data, 0);
-    let obj2 = B::decode(&mut decoder);
-
-    assert_eq!(obj.foo.get(), obj2.foo.get());
-    assert_eq!(obj.bar.borrow().baz, obj2.bar.borrow().baz);
-}
diff --git a/tests/ui-fulldeps/issue-14021.rs b/tests/ui-fulldeps/issue-14021.rs
deleted file mode 100644
index 309b5c4a03d..00000000000
--- a/tests/ui-fulldeps/issue-14021.rs
+++ /dev/null
@@ -1,33 +0,0 @@
-// run-pass
-
-#![allow(unused_mut)]
-#![allow(unused_imports)]
-#![feature(rustc_private)]
-
-extern crate rustc_macros;
-extern crate rustc_serialize;
-
-// Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
-// files.
-#[allow(unused_extern_crates)]
-extern crate rustc_driver;
-
-use rustc_macros::{Decodable, Encodable};
-use rustc_serialize::opaque::{MemDecoder, MemEncoder};
-use rustc_serialize::{Decodable, Encodable, Encoder};
-
-#[derive(Encodable, Decodable, PartialEq, Debug)]
-struct UnitLikeStruct;
-
-pub fn main() {
-    let obj = UnitLikeStruct;
-
-    let mut encoder = MemEncoder::new();
-    obj.encode(&mut encoder);
-    let data = encoder.finish();
-
-    let mut decoder = MemDecoder::new(&data, 0);
-    let obj2 = UnitLikeStruct::decode(&mut decoder);
-
-    assert_eq!(obj, obj2);
-}