diff --git a/src/librustc_incremental/persist/file_format.rs b/src/librustc_incremental/persist/file_format.rs index 79971740f5dae..274e05255b948 100644 --- a/src/librustc_incremental/persist/file_format.rs +++ b/src/librustc_incremental/persist/file_format.rs @@ -22,6 +22,9 @@ use std::io::{self, Read}; use std::path::Path; use std::fs::File; +use std::env; + +use rustc::session::config::nightly_options; /// The first few bytes of files generated by incremental compilation const FILE_MAGIC: &'static [u8] = b"RSIC"; @@ -38,9 +41,11 @@ pub fn write_file_header(stream: &mut W) -> io::Result<()> { stream.write_all(FILE_MAGIC)?; stream.write_all(&[(HEADER_FORMAT_VERSION >> 0) as u8, (HEADER_FORMAT_VERSION >> 8) as u8])?; - assert_eq!(RUSTC_VERSION.len(), (RUSTC_VERSION.len() as u8) as usize); - stream.write_all(&[RUSTC_VERSION.len() as u8])?; - stream.write_all(RUSTC_VERSION.as_bytes())?; + + let rustc_version = rustc_version(); + assert_eq!(rustc_version.len(), (rustc_version.len() as u8) as usize); + stream.write_all(&[rustc_version.len() as u8])?; + stream.write_all(rustc_version.as_bytes())?; Ok(()) } @@ -103,3 +108,13 @@ pub fn read_file(path: &Path) -> io::Result>> { Ok(Some(data)) } + +fn rustc_version() -> String { + if nightly_options::is_nightly_build() { + if let Some(val) = env::var_os("RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER") { + return val.to_string_lossy().into_owned() + } + } + + RUSTC_VERSION.to_string() +} diff --git a/src/test/incremental/cache_file_headers.rs b/src/test/incremental/cache_file_headers.rs new file mode 100644 index 0000000000000..274a3920be8d4 --- /dev/null +++ b/src/test/incremental/cache_file_headers.rs @@ -0,0 +1,29 @@ +// Copyright 2016 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +// This test case makes sure that the compiler does not try to re-use anything +// from the incremental compilation cache if the cache was produced by a +// different compiler version. This is tested by artificially forcing the +// emission of a different compiler version in the header of rpass1 artifacts, +// and then making sure that the only object file of the test program gets +// re-translated although the program stays unchanged. + +// The `l33t haxx0r` Rust compiler is known to produce incr. comp. artifacts +// that are outrageously incompatible with just about anything, even itself: +//[rpass1] rustc-env:RUSTC_FORCE_INCR_COMP_ARTIFACT_HEADER="l33t haxx0r rustc 2.1 LTS" + +// revisions:rpass1 rpass2 + +#![feature(rustc_attrs)] +#![rustc_partition_translated(module="cache_file_headers", cfg="rpass2")] + +fn main() { + // empty +}