diff --git a/Cargo.lock b/Cargo.lock index c34a325a47492..bf568cd9e22eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2540,6 +2540,7 @@ version = "0.0.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -2604,6 +2605,7 @@ dependencies = [ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_cratesio_shim 0.0.0", "rustc_data_structures 0.0.0", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "syntax_pos 0.0.0", "termcolor 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3217,6 +3219,7 @@ dependencies = [ "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)", "rustc_data_structures 0.0.0", "scoped-tls 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", + "serde 1.0.82 (registry+https://github.com/rust-lang/crates.io-index)", "serialize 0.0.0", "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", ] diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs index a0c75cd9e9476..d8919ceb8cba9 100644 --- a/src/bootstrap/bin/rustc.rs +++ b/src/bootstrap/bin/rustc.rs @@ -109,6 +109,12 @@ fn main() { // actually downloaded, so we just always pass the `--sysroot` option. cmd.arg("--sysroot").arg(&sysroot); + // Link crates to the proc macro crate for the target, but use a host proc macro crate + // to actually run the macros + if env::var_os("RUST_DUAL_PROC_MACROS").is_some() { + cmd.arg("-Zdual-proc-macros"); + } + // When we build Rust dylibs they're all intended for intermediate // usage, so make sure we pass the -Cprefer-dynamic flag instead of // linking all deps statically into the dylib. @@ -258,13 +264,6 @@ fn main() { } } - // Force all crates compiled by this compiler to (a) be unstable and (b) - // allow the `rustc_private` feature to link to other unstable crates - // also in the sysroot. - if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() { - cmd.arg("-Z").arg("force-unstable-if-unmarked"); - } - if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") { cmd.arg("--remap-path-prefix").arg(&map); } @@ -284,6 +283,14 @@ fn main() { } } + // Force all crates compiled by this compiler to (a) be unstable and (b) + // allow the `rustc_private` feature to link to other unstable crates + // also in the sysroot. We also do this for host crates, since those + // may be proc macros, in which case we might ship them. + if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) { + cmd.arg("-Z").arg("force-unstable-if-unmarked"); + } + if env::var_os("RUSTC_PARALLEL_QUERIES").is_some() { cmd.arg("--cfg").arg("parallel_queries"); } diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs index f742bce180c05..ec6bac51de7a3 100644 --- a/src/bootstrap/builder.rs +++ b/src/bootstrap/builder.rs @@ -608,6 +608,7 @@ impl<'a> Builder<'a> { .join(self.target) .join("lib"); let _ = fs::remove_dir_all(&sysroot); + eprintln!("creating sysroot {:?}", sysroot); t!(fs::create_dir_all(&sysroot)); INTERNER.intern_path(sysroot) } @@ -811,6 +812,17 @@ impl<'a> Builder<'a> { cargo.env("RUST_CHECK", "1"); } + match mode { + Mode::Std | Mode::Test | Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTest=> {}, + Mode::Rustc | Mode::Codegen | Mode::ToolRustc => { + // Build proc macros both for the host and the target + if target != compiler.host && cmd != "check" { + cargo.arg("-Zdual-proc-macros"); + cargo.env("RUST_DUAL_PROC_MACROS", "1"); + } + }, + } + cargo.arg("-j").arg(self.jobs().to_string()); // Remove make-related flags to ensure Cargo can correctly set things up cargo.env_remove("MAKEFLAGS"); diff --git a/src/bootstrap/check.rs b/src/bootstrap/check.rs index cc539d4c89571..e9ad1c9cb971f 100644 --- a/src/bootstrap/check.rs +++ b/src/bootstrap/check.rs @@ -42,7 +42,8 @@ impl Step for Std { true); let libdir = builder.sysroot_libdir(compiler, target); - add_to_sysroot(&builder, &libdir, &libstd_stamp(builder, compiler, target)); + let hostdir = builder.sysroot_libdir(compiler, compiler.host); + add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); } } @@ -88,7 +89,8 @@ impl Step for Rustc { true); let libdir = builder.sysroot_libdir(compiler, target); - add_to_sysroot(&builder, &libdir, &librustc_stamp(builder, compiler, target)); + let hostdir = builder.sysroot_libdir(compiler, compiler.host); + add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target)); } } @@ -175,7 +177,8 @@ impl Step for Test { true); let libdir = builder.sysroot_libdir(compiler, target); - add_to_sysroot(builder, &libdir, &libtest_stamp(builder, compiler, target)); + let hostdir = builder.sysroot_libdir(compiler, compiler.host); + add_to_sysroot(builder, &libdir, &hostdir, &libtest_stamp(builder, compiler, target)); } } @@ -222,7 +225,8 @@ impl Step for Rustdoc { true); let libdir = builder.sysroot_libdir(compiler, target); - add_to_sysroot(&builder, &libdir, &rustdoc_stamp(builder, compiler, target)); + let hostdir = builder.sysroot_libdir(compiler, compiler.host); + add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target)); builder.cargo(compiler, Mode::ToolRustc, target, "clean"); } } diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs index ec04dee6c32f0..f648b40bb2ace 100644 --- a/src/bootstrap/compile.rs +++ b/src/bootstrap/compile.rs @@ -224,7 +224,8 @@ impl Step for StdLink { target_compiler.host, target)); let libdir = builder.sysroot_libdir(target_compiler, target); - add_to_sysroot(builder, &libdir, &libstd_stamp(builder, compiler, target)); + let hostdir = builder.sysroot_libdir(target_compiler, compiler.host); + add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target)); if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" { // The sanitizers are only built in stage1 or above, so the dylibs will @@ -426,8 +427,12 @@ impl Step for TestLink { &compiler.host, target_compiler.host, target)); - add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target), - &libtest_stamp(builder, compiler, target)); + add_to_sysroot( + builder, + &builder.sysroot_libdir(target_compiler, target), + &builder.sysroot_libdir(target_compiler, compiler.host), + &libtest_stamp(builder, compiler, target) + ); builder.cargo(target_compiler, Mode::ToolTest, target, "clean"); } @@ -491,8 +496,8 @@ impl Step for Rustc { return; } - // Ensure that build scripts have a std to link against. - builder.ensure(Std { + // Ensure that build scripts and proc macros have a std / libproc_macro to link against. + builder.ensure(Test { compiler: builder.compiler(self.compiler.stage, builder.config.build), target: builder.config.build, }); @@ -587,8 +592,12 @@ impl Step for RustcLink { &compiler.host, target_compiler.host, target)); - add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target), - &librustc_stamp(builder, compiler, target)); + add_to_sysroot( + builder, + &builder.sysroot_libdir(target_compiler, target), + &builder.sysroot_libdir(target_compiler, compiler.host), + &librustc_stamp(builder, compiler, target) + ); builder.cargo(target_compiler, Mode::ToolRustc, target, "clean"); } } @@ -996,10 +1005,22 @@ impl Step for Assemble { /// /// For a particular stage this will link the file listed in `stamp` into the /// `sysroot_dst` provided. -pub fn add_to_sysroot(builder: &Builder, sysroot_dst: &Path, stamp: &Path) { +pub fn add_to_sysroot( + builder: &Builder, + sysroot_dst: &Path, + sysroot_host_dst: &Path, + stamp: &Path +) { + //eprintln!("add_to_sysroot - host dir {:?} - stamp {:?}", sysroot_host_dst, stamp); t!(fs::create_dir_all(&sysroot_dst)); - for path in builder.read_stamp_file(stamp) { - builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap())); + t!(fs::create_dir_all(&sysroot_host_dst)); + for (path, host) in builder.read_stamp_file(stamp) { + if host { + eprintln!("add_to_sysroot host - copying {:?} to {:?}", path, sysroot_host_dst); + builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap())); + } else { + builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap())); + } } } @@ -1028,8 +1049,14 @@ pub fn run_cargo(builder: &Builder, let mut deps = Vec::new(); let mut toplevel = Vec::new(); let ok = stream_cargo(builder, cargo, &mut |msg| { - let filenames = match msg { - CargoMessage::CompilerArtifact { filenames, .. } => filenames, + let (filenames, crate_types) = match msg { + CargoMessage::CompilerArtifact { + filenames, + target: CargoTarget { + crate_types, + }, + .. + } => (filenames, crate_types), _ => return, }; for filename in filenames { @@ -1044,15 +1071,19 @@ pub fn run_cargo(builder: &Builder, let filename = Path::new(&*filename); // If this was an output file in the "host dir" we don't actually - // worry about it, it's not relevant for us. + // worry about it, it's not relevant for us if filename.starts_with(&host_root_dir) { + // Unless it's a proc macro used in the compiler + if crate_types.iter().any(|t| t == "proc-macro") { + deps.push((filename.to_path_buf(), true)); + } continue; } // If this was output in the `deps` dir then this is a precise file // name (hash included) so we start tracking it. if filename.starts_with(&target_deps_dir) { - deps.push(filename.to_path_buf()); + deps.push((filename.to_path_buf(), false)); continue; } @@ -1105,10 +1136,10 @@ pub fn run_cargo(builder: &Builder, let candidate = format!("{}.lib", path_to_add); let candidate = PathBuf::from(candidate); if candidate.exists() { - deps.push(candidate); + deps.push((candidate, false)); } } - deps.push(path_to_add.into()); + deps.push((path_to_add.into(), false)); } // Now we want to update the contents of the stamp file, if necessary. First @@ -1121,12 +1152,13 @@ pub fn run_cargo(builder: &Builder, let mut new_contents = Vec::new(); let mut max = None; let mut max_path = None; - for dep in deps.iter() { + for (dep, proc_macro) in deps.iter() { let mtime = mtime(dep); if Some(mtime) > max { max = Some(mtime); max_path = Some(dep.clone()); } + new_contents.extend(if *proc_macro { b"h" } else { b"t" }); new_contents.extend(dep.to_str().unwrap().as_bytes()); new_contents.extend(b"\0"); } @@ -1138,7 +1170,7 @@ pub fn run_cargo(builder: &Builder, if contents_equal && max <= stamp_mtime { builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}", stamp, max, stamp_mtime)); - return deps + return deps.into_iter().map(|(d, _)| d).collect() } if max > stamp_mtime { builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path)); @@ -1146,7 +1178,7 @@ pub fn run_cargo(builder: &Builder, builder.verbose(&format!("updating {:?} as deps changed", stamp)); } t!(fs::write(&stamp, &new_contents)); - deps + deps.into_iter().map(|(d, _)| d).collect() } pub fn stream_cargo( @@ -1192,6 +1224,11 @@ pub fn stream_cargo( status.success() } +#[derive(Deserialize)] +pub struct CargoTarget<'a> { + crate_types: Vec>, +} + #[derive(Deserialize)] #[serde(tag = "reason", rename_all = "kebab-case")] pub enum CargoMessage<'a> { @@ -1199,6 +1236,7 @@ pub enum CargoMessage<'a> { package_id: Cow<'a, str>, features: Vec>, filenames: Vec>, + target: CargoTarget<'a>, }, BuildScriptExecuted { package_id: Cow<'a, str>, diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py index 7b70236dfe8e6..67c4c4a07e5ce 100755 --- a/src/bootstrap/configure.py +++ b/src/bootstrap/configure.py @@ -43,6 +43,7 @@ def v(*args): o("sccache", None, "invoke gcc/clang via sccache to reuse object files between builds") o("local-rust", None, "use an installed rustc rather than downloading a snapshot") v("local-rust-root", None, "set prefix for local rust binary") +v("local-cargo", None, "set prefix for local rust binary") o("local-rebuild", "build.local-rebuild", "assume local-rust matches the current version, for rebuilds; implies local-rust, and is implied if local-rust already matches the current version") o("llvm-static-stdcpp", "llvm.static-libstdcpp", "statically link to libstdc++ for LLVM") o("llvm-link-shared", "llvm.link-shared", "prefer shared linking to LLVM (llvm-config --link-shared)") @@ -320,6 +321,8 @@ def set(key, value): elif option.name == 'local-rust-root': set('build.rustc', value + '/bin/rustc') set('build.cargo', value + '/bin/cargo') + elif option.name == 'local-cargo': + set('build.cargo', value) elif option.name == 'llvm-root': set('target.{}.llvm-config'.format(build()), value + '/bin/llvm-config') elif option.name == 'llvm-config': diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs index 32b03c5fb1b7c..cc61281b0b3b9 100644 --- a/src/bootstrap/lib.rs +++ b/src/bootstrap/lib.rs @@ -104,7 +104,7 @@ //! also check out the `src/bootstrap/README.md` file for more information. #![deny(bare_trait_objects)] -#![deny(warnings)] +//#![deny(warnings)] #![feature(core_intrinsics)] #![feature(drain_filter)] @@ -1142,7 +1142,7 @@ impl Build { ret } - fn read_stamp_file(&self, stamp: &Path) -> Vec { + fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> { if self.config.dry_run { return Vec::new(); } @@ -1155,8 +1155,9 @@ impl Build { if part.is_empty() { continue } - let path = PathBuf::from(t!(str::from_utf8(part))); - paths.push(path); + let host = part[0] as char == 'h'; + let path = PathBuf::from(t!(str::from_utf8(&part[1..]))); + paths.push((path, host)); } paths } diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index 1c27cf3909b1a..bd5d4d8d52098 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -1,9 +1,9 @@ ifdef VERBOSE Q := -BOOTSTRAP_ARGS := -v +BOOTSTRAP_ARGS := -vv else Q := @ -BOOTSTRAP_ARGS := +BOOTSTRAP_ARGS := -vv endif ifdef EXCLUDE_CARGO @@ -12,11 +12,11 @@ else AUX_ARGS := src/tools/cargo src/tools/cargotest endif -BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py +BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py -vv all: - $(Q)$(BOOTSTRAP) build $(BOOTSTRAP_ARGS) - $(Q)$(BOOTSTRAP) doc $(BOOTSTRAP_ARGS) + $(Q)$(BOOTSTRAP) build -vv $(BOOTSTRAP_ARGS) + $(Q)$(BOOTSTRAP) doc -vv $(BOOTSTRAP_ARGS) help: $(Q)echo 'Welcome to the rustbuild build system!' diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs index 216649808e2a4..3bf20c9c7e1ea 100644 --- a/src/bootstrap/test.rs +++ b/src/bootstrap/test.rs @@ -213,7 +213,7 @@ impl Step for Cargo { }); let mut cargo = tool::prepare_tool_cargo(builder, compiler, - Mode::ToolRustc, + Mode::ToolStd, self.host, "test", "src/tools/cargo", diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs index 9f6db73e6f713..7c4e3d9ae13e9 100644 --- a/src/bootstrap/tool.rs +++ b/src/bootstrap/tool.rs @@ -92,7 +92,8 @@ impl Step for ToolBuild { compile::CargoMessage::CompilerArtifact { package_id, features, - filenames + filenames, + target: _, } => { (package_id, features, filenames) } @@ -514,7 +515,7 @@ impl Step for Cargo { compiler: self.compiler, target: self.target, tool: "cargo", - mode: Mode::ToolRustc, + mode: Mode::ToolStd, path: "src/tools/cargo", is_optional_tool: false, source_type: SourceType::Submodule, diff --git a/src/ci/docker/dist-arm-linux/Dockerfile b/src/ci/docker/dist-arm-linux/Dockerfile index 6ddc5c1e04ae3..e8f2a0b5125ad 100644 --- a/src/ci/docker/dist-arm-linux/Dockerfile +++ b/src/ci/docker/dist-arm-linux/Dockerfile @@ -32,5 +32,5 @@ ENV CC_arm_unknown_linux_gnueabi=arm-unknown-linux-gnueabi-gcc \ ENV HOSTS=arm-unknown-linux-gnueabi -ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs -ENV SCRIPT python2.7 ../x.py dist --host $HOSTS --target $HOSTS +ENV RUST_CONFIGURE_ARGS --enable-extended --disable-docs --local-cargo=/cargobin/target/release/cargo +ENV SCRIPT python2.7 ../x.py dist -vv --host $HOSTS --target $HOSTS diff --git a/src/ci/docker/run.sh b/src/ci/docker/run.sh index ad6188568cff2..c65511d653128 100755 --- a/src/ci/docker/run.sh +++ b/src/ci/docker/run.sh @@ -127,6 +127,7 @@ exec docker \ --env TRAVIS_BRANCH \ --env TOOLSTATE_REPO_ACCESS_TOKEN \ --env CI_JOB_NAME="${CI_JOB_NAME-$IMAGE}" \ + --volume "/home/john/dev/cargo:/cargobin" \ --volume "$HOME/.cargo:/cargo" \ --volume "$HOME/rustsrc:$HOME/rustsrc" \ --init \ diff --git a/src/ci/run.sh b/src/ci/run.sh index b0e1b1651055f..9ef32ad55a6f0 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -88,6 +88,10 @@ if [ "$RUN_CHECK_WITH_PARALLEL_QUERIES" != "" ]; then rm -rf build fi +#sh -x -c "curl https://sh.rustup.rs -sSf | sh -s -- -y" + +#sh -x -c "cd /cargobin; /cargo/bin/cargo build --release" + travis_fold start configure travis_time_start $SRC/configure $RUST_CONFIGURE_ARGS diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index e2f4049b1db28..ca75703c29541 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -1216,6 +1216,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options, Use with RUST_REGION_GRAPH=help for more info"), parse_only: bool = (false, parse_bool, [UNTRACKED], "parse only; do not compile, assemble, or link"), + dual_proc_macros: bool = (false, parse_bool, [TRACKED], + "load proc macros for both target and host, but only link to the target"), no_codegen: bool = (false, parse_bool, [TRACKED], "run all passes except codegen; no output"), treat_err_as_bug: bool = (false, parse_bool, [TRACKED], diff --git a/src/librustc/session/filesearch.rs b/src/librustc/session/filesearch.rs index 19f1c7a18fad1..ef83967b8ece3 100644 --- a/src/librustc/session/filesearch.rs +++ b/src/librustc/session/filesearch.rs @@ -18,6 +18,7 @@ pub enum FileMatch { // A module for searching for libraries +#[derive(Clone)] pub struct FileSearch<'a> { sysroot: &'a Path, triple: &'a str, diff --git a/src/librustc_cratesio_shim/Cargo.toml b/src/librustc_cratesio_shim/Cargo.toml index b8e494e4040ec..5540521868e88 100644 --- a/src/librustc_cratesio_shim/Cargo.toml +++ b/src/librustc_cratesio_shim/Cargo.toml @@ -22,4 +22,5 @@ crate-type = ["dylib"] [dependencies] bitflags = "1.0" log = "0.4" +serde = { version = "1.0", features = ["serde_derive"] } unicode-width = "0.1.4" diff --git a/src/librustc_cratesio_shim/src/lib.rs b/src/librustc_cratesio_shim/src/lib.rs index 4024087f4d3ef..fd50cf11ab91e 100644 --- a/src/librustc_cratesio_shim/src/lib.rs +++ b/src/librustc_cratesio_shim/src/lib.rs @@ -6,4 +6,5 @@ extern crate bitflags; extern crate log; extern crate proc_macro; +extern crate serde; extern crate unicode_width; diff --git a/src/librustc_errors/Cargo.toml b/src/librustc_errors/Cargo.toml index b24f8ddf4d9f7..666ea4fd99781 100644 --- a/src/librustc_errors/Cargo.toml +++ b/src/librustc_errors/Cargo.toml @@ -14,6 +14,7 @@ serialize = { path = "../libserialize" } syntax_pos = { path = "../libsyntax_pos" } rustc_data_structures = { path = "../librustc_data_structures" } rustc_cratesio_shim = { path = "../librustc_cratesio_shim" } +serde = { version = "1.0", features = ["serde_derive"] } unicode-width = "0.1.4" atty = "0.2" termcolor = "1.0" diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs index 64d5ca0c2a742..e16d087dae517 100644 --- a/src/librustc_errors/lib.rs +++ b/src/librustc_errors/lib.rs @@ -16,6 +16,7 @@ extern crate libc; #[macro_use] extern crate log; extern crate rustc_data_structures; +extern crate serde; extern crate serialize as rustc_serialize; extern crate syntax_pos; extern crate unicode_width; @@ -35,6 +36,8 @@ use std::cell::Cell; use std::{error, fmt}; use std::panic; +use serde::{Serialize, Deserialize}; + use termcolor::{ColorSpec, Color}; mod diagnostic; @@ -59,7 +62,8 @@ use syntax_pos::{BytePos, /// All suggestions are marked with an `Applicability`. Tools use the applicability of a suggestion /// to determine whether it should be automatically applied or if the user should be consulted /// before applying the suggestion. -#[derive(Copy, Clone, Debug, PartialEq, Hash, RustcEncodable, RustcDecodable)] +#[derive(Copy, Clone, Debug, PartialEq, Hash, + RustcEncodable, RustcDecodable, Serialize, Deserialize)] pub enum Applicability { /// The suggestion is definitely what the user intended. This suggestion should be /// automatically applied. diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index e9785e7c88d0d..731eff62586d6 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -187,13 +187,15 @@ impl<'a> CrateLoader<'a> { }); } - fn register_crate(&mut self, - root: &Option, - ident: Symbol, - span: Span, - lib: Library, - dep_kind: DepKind) - -> (CrateNum, Lrc) { + fn register_crate( + &mut self, + host_lib: Option, + root: &Option, + ident: Symbol, + span: Span, + lib: Library, + dep_kind: DepKind + ) -> (CrateNum, Lrc) { let crate_root = lib.metadata.get_root(); info!("register crate `extern crate {} as {}`", crate_root.name, ident); self.verify_no_symbol_conflicts(span, &crate_root); @@ -221,7 +223,16 @@ impl<'a> CrateLoader<'a> { let dependencies: Vec = cnum_map.iter().cloned().collect(); let proc_macros = crate_root.proc_macro_decls_static.map(|_| { - self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) + if self.sess.opts.debugging_opts.dual_proc_macros { + let host_lib = host_lib.unwrap(); + self.load_derive_macros( + &host_lib.metadata.get_root(), + host_lib.dylib.clone().map(|p| p.0), + span + ) + } else { + self.load_derive_macros(&crate_root, dylib.clone().map(|p| p.0), span) + } }); let def_path_table = record_time(&self.sess.perf_stats.decode_def_path_tables_time, || { @@ -268,6 +279,61 @@ impl<'a> CrateLoader<'a> { (cnum, cmeta) } + fn load_proc_macro<'b> ( + &mut self, + locate_ctxt: &mut locator::Context<'b>, + path_kind: PathKind, + ) -> Option<(LoadResult, Option)> + where + 'a: 'b + { + // Use a new locator Context so trying to load a proc macro doesn't affect the error + // message we emit + let mut proc_macro_locator = locate_ctxt.clone(); + + // Try to load a proc macro + proc_macro_locator.is_proc_macro = Some(true); + + // Load the proc macro crate for the target + let (locator, target_result) = if self.sess.opts.debugging_opts.dual_proc_macros { + proc_macro_locator.reset(); + let result = match self.load(&mut proc_macro_locator)? { + LoadResult::Previous(cnum) => return Some((LoadResult::Previous(cnum), None)), + LoadResult::Loaded(library) => Some(LoadResult::Loaded(library)) + }; + // Don't look for a matching hash when looking for the host crate. + // It won't be the same as the target crate hash + locate_ctxt.hash = None; + // Use the locate_ctxt when looking for the host proc macro crate, as that is required + // so we want it to affect the error message + (locate_ctxt, result) + } else { + (&mut proc_macro_locator, None) + }; + + // Load the proc macro crate for the host + + locator.reset(); + locator.is_proc_macro = Some(true); + locator.target = &self.sess.host; + locator.triple = TargetTriple::from_triple(config::host_triple()); + locator.filesearch = self.sess.host_filesearch(path_kind); + + let host_result = self.load(locator)?; + + Some(if self.sess.opts.debugging_opts.dual_proc_macros { + let host_result = match host_result { + LoadResult::Previous(..) => { + panic!("host and target proc macros must be loaded in lock-step") + } + LoadResult::Loaded(library) => library + }; + (target_result.unwrap(), Some(host_result)) + } else { + (host_result, None) + }) + } + fn resolve_crate<'b>( &'b mut self, root: &'b Option, @@ -280,53 +346,39 @@ impl<'a> CrateLoader<'a> { mut dep_kind: DepKind, ) -> Result<(CrateNum, Lrc), LoadError<'b>> { info!("resolving crate `extern crate {} as {}`", name, ident); + let mut locate_ctxt = locator::Context { + sess: self.sess, + span, + ident, + crate_name: name, + hash: hash.map(|a| &*a), + extra_filename: extra_filename, + filesearch: self.sess.target_filesearch(path_kind), + target: &self.sess.target.target, + triple: self.sess.opts.target_triple.clone(), + root, + rejected_via_hash: vec![], + rejected_via_triple: vec![], + rejected_via_kind: vec![], + rejected_via_version: vec![], + rejected_via_filename: vec![], + should_match_name: true, + is_proc_macro: Some(false), + metadata_loader: &*self.cstore.metadata_loader, + }; + let result = if let Some(cnum) = self.existing_match(name, hash, path_kind) { - LoadResult::Previous(cnum) + (LoadResult::Previous(cnum), None) } else { info!("falling back to a load"); - let mut locate_ctxt = locator::Context { - sess: self.sess, - span, - ident, - crate_name: name, - hash: hash.map(|a| &*a), - extra_filename: extra_filename, - filesearch: self.sess.target_filesearch(path_kind), - target: &self.sess.target.target, - triple: &self.sess.opts.target_triple, - root, - rejected_via_hash: vec![], - rejected_via_triple: vec![], - rejected_via_kind: vec![], - rejected_via_version: vec![], - rejected_via_filename: vec![], - should_match_name: true, - is_proc_macro: Some(false), - metadata_loader: &*self.cstore.metadata_loader, - }; - - self.load(&mut locate_ctxt).or_else(|| { + self.load(&mut locate_ctxt).map(|r| (r, None)).or_else(|| { dep_kind = DepKind::UnexportedMacrosOnly; - - let mut proc_macro_locator = locator::Context { - target: &self.sess.host, - triple: &TargetTriple::from_triple(config::host_triple()), - filesearch: self.sess.host_filesearch(path_kind), - rejected_via_hash: vec![], - rejected_via_triple: vec![], - rejected_via_kind: vec![], - rejected_via_version: vec![], - rejected_via_filename: vec![], - is_proc_macro: Some(true), - ..locate_ctxt - }; - - self.load(&mut proc_macro_locator) + self.load_proc_macro(&mut locate_ctxt, path_kind) }).ok_or_else(move || LoadError::LocatorError(locate_ctxt))? }; match result { - LoadResult::Previous(cnum) => { + (LoadResult::Previous(cnum), None) => { let data = self.cstore.get_crate_data(cnum); if data.root.proc_macro_decls_static.is_some() { dep_kind = DepKind::UnexportedMacrosOnly; @@ -336,9 +388,10 @@ impl<'a> CrateLoader<'a> { }); Ok((cnum, data)) } - LoadResult::Loaded(library) => { - Ok(self.register_crate(root, ident, span, library, dep_kind)) + (LoadResult::Loaded(library), host_library) => { + Ok(self.register_crate(host_library, root, ident, span, library, dep_kind)) } + _ => panic!() } } @@ -354,7 +407,7 @@ impl<'a> CrateLoader<'a> { // don't want to match a host crate against an equivalent target one // already loaded. let root = library.metadata.get_root(); - if locate_ctxt.triple == &self.sess.opts.target_triple { + if locate_ctxt.triple == self.sess.opts.target_triple { let mut result = LoadResult::Loaded(library); self.cstore.iter_crate_data(|cnum, data| { if data.root.name == root.name && root.hash == data.root.hash { @@ -450,9 +503,9 @@ impl<'a> CrateLoader<'a> { fn read_extension_crate(&mut self, span: Span, orig_name: Symbol, rename: Symbol) -> ExtensionCrate { info!("read extension crate `extern crate {} as {}`", orig_name, rename); - let target_triple = &self.sess.opts.target_triple; + let target_triple = self.sess.opts.target_triple.clone(); let host_triple = TargetTriple::from_triple(config::host_triple()); - let is_cross = target_triple != &host_triple; + let is_cross = target_triple != host_triple; let mut target_only = false; let mut locate_ctxt = locator::Context { sess: self.sess, @@ -463,7 +516,7 @@ impl<'a> CrateLoader<'a> { extra_filename: None, filesearch: self.sess.host_filesearch(PathKind::Crate), target: &self.sess.host, - triple: &host_triple, + triple: host_triple, root: &None, rejected_via_hash: vec![], rejected_via_triple: vec![], diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs index ad6296e1a3bd8..6f948f3ac8f7e 100644 --- a/src/librustc_metadata/decoder.rs +++ b/src/librustc_metadata/decoder.rs @@ -647,7 +647,7 @@ impl<'a, 'tcx> CrateMetadata { pub fn get_stability(&self, id: DefIndex) -> Option { match self.is_proc_macro(id) { - true => None, + true => self.root.proc_macro_stability.clone(), false => self.entry(id).stability.map(|stab| stab.decode(self)), } } diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs index afb0218501d18..79942f614a8d0 100644 --- a/src/librustc_metadata/encoder.rs +++ b/src/librustc_metadata/encoder.rs @@ -489,7 +489,11 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } else { None }, - + proc_macro_stability: if is_proc_macro { + tcx.lookup_stability(DefId::local(CRATE_DEF_INDEX)).map(|stab| stab.clone()) + } else { + None + }, compiler_builtins: attr::contains_name(&attrs, "compiler_builtins"), needs_allocator: attr::contains_name(&attrs, "needs_allocator"), needs_panic_runtime: attr::contains_name(&attrs, "needs_panic_runtime"), diff --git a/src/librustc_metadata/locator.rs b/src/librustc_metadata/locator.rs index 6b49d6b9e52cb..20c89569efa53 100644 --- a/src/librustc_metadata/locator.rs +++ b/src/librustc_metadata/locator.rs @@ -241,11 +241,13 @@ use flate2::read::DeflateDecoder; use rustc_data_structures::owning_ref::OwningRef; +#[derive(Clone)] pub struct CrateMismatch { path: PathBuf, got: String, } +#[derive(Clone)] pub struct Context<'a> { pub sess: &'a Session, pub span: Span, @@ -255,7 +257,7 @@ pub struct Context<'a> { pub extra_filename: Option<&'a str>, // points to either self.sess.target.target or self.sess.host, must match triple pub target: &'a Target, - pub triple: &'a TargetTriple, + pub triple: TargetTriple, pub filesearch: FileSearch<'a>, pub root: &'a Option, pub rejected_via_hash: Vec, @@ -299,6 +301,14 @@ impl CratePaths { } impl<'a> Context<'a> { + pub fn reset(&mut self) { + self.rejected_via_hash.clear(); + self.rejected_via_triple.clear(); + self.rejected_via_kind.clear(); + self.rejected_via_version.clear(); + self.rejected_via_filename.clear(); + } + pub fn maybe_load_library_crate(&mut self) -> Option { let mut seen_paths = FxHashSet::default(); match self.extra_filename { @@ -396,7 +406,7 @@ impl<'a> Context<'a> { add); if (self.ident == "std" || self.ident == "core") - && self.triple != &TargetTriple::from_triple(config::host_triple()) { + && self.triple != TargetTriple::from_triple(config::host_triple()) { err.note(&format!("the `{}` target may not be installed", self.triple)); } err.span_label(self.span, "can't find crate"); @@ -715,7 +725,7 @@ impl<'a> Context<'a> { } } - if &root.triple != self.triple { + if root.triple != self.triple { info!("Rejecting via crate triple: expected {} got {}", self.triple, root.triple); diff --git a/src/librustc_metadata/schema.rs b/src/librustc_metadata/schema.rs index f3ff9747625f5..f3a5cbb2ab88b 100644 --- a/src/librustc_metadata/schema.rs +++ b/src/librustc_metadata/schema.rs @@ -187,6 +187,7 @@ pub struct CrateRoot { pub has_default_lib_allocator: bool, pub plugin_registrar_fn: Option, pub proc_macro_decls_static: Option, + pub proc_macro_stability: Option, pub crate_deps: LazySeq, pub dylib_dependency_formats: LazySeq>, diff --git a/src/libsyntax_pos/Cargo.toml b/src/libsyntax_pos/Cargo.toml index 08ee2e0f37626..c6f094a8a7b8c 100644 --- a/src/libsyntax_pos/Cargo.toml +++ b/src/libsyntax_pos/Cargo.toml @@ -13,5 +13,6 @@ serialize = { path = "../libserialize" } rustc_data_structures = { path = "../librustc_data_structures" } arena = { path = "../libarena" } scoped-tls = { version = "0.1.1", features = ["nightly"] } +serde = { version = "1.0", features = ["serde_derive"] } unicode-width = "0.1.4" cfg-if = "0.1.2" diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs index d9d7f9b0cb492..674abfe045bc8 100644 --- a/src/libsyntax_pos/lib.rs +++ b/src/libsyntax_pos/lib.rs @@ -25,6 +25,7 @@ extern crate rustc_data_structures; #[macro_use] extern crate scoped_tls; +extern crate serde; use serialize::{Encodable, Decodable, Encoder, Decoder}; @@ -36,6 +37,8 @@ extern crate cfg_if; extern crate unicode_width; +use serde::{Serialize, Deserialize}; + pub mod edition; pub mod hygiene; pub use hygiene::{Mark, SyntaxContext, ExpnInfo, ExpnFormat, CompilerDesugaringKind}; @@ -77,7 +80,10 @@ impl Globals { scoped_thread_local!(pub static GLOBALS: Globals); /// Differentiates between real files and common virtual files. -#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, RustcDecodable, RustcEncodable)] +#[derive(Debug, Eq, PartialEq, Clone, Ord, PartialOrd, Hash, + RustcDecodable, RustcEncodable, + Serialize, Deserialize, +)] pub enum FileName { Real(PathBuf), /// A macro. This includes the full name of the macro, so that there are no clashes.