Skip to content

Commit 0547ceb

Browse files
committed
Auto merge of #58013 - Zoxc:stable-hash-macro-simple, r=oli-obk
Create a derive macro for HashStable and allow proc macros in rustc A combination of #56864 and #56795. There were complications with using `serde_derive` as rustc doesn't know which crate to use for the host when there is a serde_derive in the sysroot and cargo passes another on the command line built from crates.io. r? @eddyb (for proc macro changes) @alexcrichton (for rustbuild changes) @michaelwoerister (for the macro itself)
2 parents 88f755f + f2ef283 commit 0547ceb

24 files changed

+392
-87
lines changed

Cargo.lock

+11
Original file line numberDiff line numberDiff line change
@@ -2365,6 +2365,7 @@ dependencies = [
23652365
"rustc_data_structures 0.0.0",
23662366
"rustc_errors 0.0.0",
23672367
"rustc_fs_util 0.0.0",
2368+
"rustc_macros 0.1.0",
23682369
"rustc_target 0.0.0",
23692370
"scoped-tls 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
23702371
"serialize 0.0.0",
@@ -2817,6 +2818,16 @@ dependencies = [
28172818
"core 0.0.0",
28182819
]
28192820

2821+
[[package]]
2822+
name = "rustc_macros"
2823+
version = "0.1.0"
2824+
dependencies = [
2825+
"proc-macro2 0.4.24 (registry+https://github.com/rust-lang/crates.io-index)",
2826+
"quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)",
2827+
"syn 0.15.22 (registry+https://github.com/rust-lang/crates.io-index)",
2828+
"synstructure 0.10.1 (registry+https://github.com/rust-lang/crates.io-index)",
2829+
]
2830+
28202831
[[package]]
28212832
name = "rustc_metadata"
28222833
version = "0.0.0"

src/bootstrap/bin/rustc.rs

+14-7
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,12 @@ fn main() {
109109

110110
cmd.arg("-Zexternal-macro-backtrace");
111111

112+
// Link crates to the proc macro crate for the target, but use a host proc macro crate
113+
// to actually run the macros
114+
if env::var_os("RUST_DUAL_PROC_MACROS").is_some() {
115+
cmd.arg("-Zdual-proc-macros");
116+
}
117+
112118
// When we build Rust dylibs they're all intended for intermediate
113119
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
114120
// linking all deps statically into the dylib.
@@ -258,13 +264,6 @@ fn main() {
258264
}
259265
}
260266

261-
// Force all crates compiled by this compiler to (a) be unstable and (b)
262-
// allow the `rustc_private` feature to link to other unstable crates
263-
// also in the sysroot.
264-
if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() {
265-
cmd.arg("-Z").arg("force-unstable-if-unmarked");
266-
}
267-
268267
if let Ok(map) = env::var("RUSTC_DEBUGINFO_MAP") {
269268
cmd.arg("--remap-path-prefix").arg(&map);
270269
}
@@ -284,6 +283,14 @@ fn main() {
284283
}
285284
}
286285

286+
// Force all crates compiled by this compiler to (a) be unstable and (b)
287+
// allow the `rustc_private` feature to link to other unstable crates
288+
// also in the sysroot. We also do this for host crates, since those
289+
// may be proc macros, in which case we might ship them.
290+
if env::var_os("RUSTC_FORCE_UNSTABLE").is_some() && (stage != "0" || target.is_some()) {
291+
cmd.arg("-Z").arg("force-unstable-if-unmarked");
292+
}
293+
287294
if env::var_os("RUSTC_PARALLEL_COMPILER").is_some() {
288295
cmd.arg("--cfg").arg("parallel_compiler");
289296
}

src/bootstrap/builder.rs

+11
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,17 @@ impl<'a> Builder<'a> {
812812
cargo.env("RUST_CHECK", "1");
813813
}
814814

815+
match mode {
816+
Mode::Std | Mode::Test | Mode::ToolBootstrap | Mode::ToolStd | Mode::ToolTest=> {},
817+
Mode::Rustc | Mode::Codegen | Mode::ToolRustc => {
818+
// Build proc macros both for the host and the target
819+
if target != compiler.host && cmd != "check" {
820+
cargo.arg("-Zdual-proc-macros");
821+
cargo.env("RUST_DUAL_PROC_MACROS", "1");
822+
}
823+
},
824+
}
825+
815826
cargo.arg("-j").arg(self.jobs().to_string());
816827
// Remove make-related flags to ensure Cargo can correctly set things up
817828
cargo.env_remove("MAKEFLAGS");

src/bootstrap/check.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,8 @@ impl Step for Std {
4242
true);
4343

4444
let libdir = builder.sysroot_libdir(compiler, target);
45-
add_to_sysroot(&builder, &libdir, &libstd_stamp(builder, compiler, target));
45+
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
46+
add_to_sysroot(&builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
4647
}
4748
}
4849

@@ -88,7 +89,8 @@ impl Step for Rustc {
8889
true);
8990

9091
let libdir = builder.sysroot_libdir(compiler, target);
91-
add_to_sysroot(&builder, &libdir, &librustc_stamp(builder, compiler, target));
92+
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
93+
add_to_sysroot(&builder, &libdir, &hostdir, &librustc_stamp(builder, compiler, target));
9294
}
9395
}
9496

@@ -175,7 +177,8 @@ impl Step for Test {
175177
true);
176178

177179
let libdir = builder.sysroot_libdir(compiler, target);
178-
add_to_sysroot(builder, &libdir, &libtest_stamp(builder, compiler, target));
180+
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
181+
add_to_sysroot(builder, &libdir, &hostdir, &libtest_stamp(builder, compiler, target));
179182
}
180183
}
181184

@@ -222,7 +225,8 @@ impl Step for Rustdoc {
222225
true);
223226

224227
let libdir = builder.sysroot_libdir(compiler, target);
225-
add_to_sysroot(&builder, &libdir, &rustdoc_stamp(builder, compiler, target));
228+
let hostdir = builder.sysroot_libdir(compiler, compiler.host);
229+
add_to_sysroot(&builder, &libdir, &hostdir, &rustdoc_stamp(builder, compiler, target));
226230
builder.cargo(compiler, Mode::ToolRustc, target, "clean");
227231
}
228232
}

src/bootstrap/compile.rs

+55-19
Original file line numberDiff line numberDiff line change
@@ -224,7 +224,8 @@ impl Step for StdLink {
224224
target_compiler.host,
225225
target));
226226
let libdir = builder.sysroot_libdir(target_compiler, target);
227-
add_to_sysroot(builder, &libdir, &libstd_stamp(builder, compiler, target));
227+
let hostdir = builder.sysroot_libdir(target_compiler, compiler.host);
228+
add_to_sysroot(builder, &libdir, &hostdir, &libstd_stamp(builder, compiler, target));
228229

229230
if builder.config.sanitizers && compiler.stage != 0 && target == "x86_64-apple-darwin" {
230231
// The sanitizers are only built in stage1 or above, so the dylibs will
@@ -431,8 +432,12 @@ impl Step for TestLink {
431432
&compiler.host,
432433
target_compiler.host,
433434
target));
434-
add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target),
435-
&libtest_stamp(builder, compiler, target));
435+
add_to_sysroot(
436+
builder,
437+
&builder.sysroot_libdir(target_compiler, target),
438+
&builder.sysroot_libdir(target_compiler, compiler.host),
439+
&libtest_stamp(builder, compiler, target)
440+
);
436441

437442
builder.cargo(target_compiler, Mode::ToolTest, target, "clean");
438443
}
@@ -496,8 +501,8 @@ impl Step for Rustc {
496501
return;
497502
}
498503

499-
// Ensure that build scripts have a std to link against.
500-
builder.ensure(Std {
504+
// Ensure that build scripts and proc macros have a std / libproc_macro to link against.
505+
builder.ensure(Test {
501506
compiler: builder.compiler(self.compiler.stage, builder.config.build),
502507
target: builder.config.build,
503508
});
@@ -592,8 +597,12 @@ impl Step for RustcLink {
592597
&compiler.host,
593598
target_compiler.host,
594599
target));
595-
add_to_sysroot(builder, &builder.sysroot_libdir(target_compiler, target),
596-
&librustc_stamp(builder, compiler, target));
600+
add_to_sysroot(
601+
builder,
602+
&builder.sysroot_libdir(target_compiler, target),
603+
&builder.sysroot_libdir(target_compiler, compiler.host),
604+
&librustc_stamp(builder, compiler, target)
605+
);
597606
builder.cargo(target_compiler, Mode::ToolRustc, target, "clean");
598607
}
599608
}
@@ -1015,10 +1024,20 @@ impl Step for Assemble {
10151024
///
10161025
/// For a particular stage this will link the file listed in `stamp` into the
10171026
/// `sysroot_dst` provided.
1018-
pub fn add_to_sysroot(builder: &Builder<'_>, sysroot_dst: &Path, stamp: &Path) {
1027+
pub fn add_to_sysroot(
1028+
builder: &Builder<'_>,
1029+
sysroot_dst: &Path,
1030+
sysroot_host_dst: &Path,
1031+
stamp: &Path
1032+
) {
10191033
t!(fs::create_dir_all(&sysroot_dst));
1020-
for path in builder.read_stamp_file(stamp) {
1021-
builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
1034+
t!(fs::create_dir_all(&sysroot_host_dst));
1035+
for (path, host) in builder.read_stamp_file(stamp) {
1036+
if host {
1037+
builder.copy(&path, &sysroot_host_dst.join(path.file_name().unwrap()));
1038+
} else {
1039+
builder.copy(&path, &sysroot_dst.join(path.file_name().unwrap()));
1040+
}
10221041
}
10231042
}
10241043

@@ -1047,8 +1066,14 @@ pub fn run_cargo(builder: &Builder<'_>,
10471066
let mut deps = Vec::new();
10481067
let mut toplevel = Vec::new();
10491068
let ok = stream_cargo(builder, cargo, &mut |msg| {
1050-
let filenames = match msg {
1051-
CargoMessage::CompilerArtifact { filenames, .. } => filenames,
1069+
let (filenames, crate_types) = match msg {
1070+
CargoMessage::CompilerArtifact {
1071+
filenames,
1072+
target: CargoTarget {
1073+
crate_types,
1074+
},
1075+
..
1076+
} => (filenames, crate_types),
10521077
_ => return,
10531078
};
10541079
for filename in filenames {
@@ -1063,15 +1088,19 @@ pub fn run_cargo(builder: &Builder<'_>,
10631088
let filename = Path::new(&*filename);
10641089

10651090
// If this was an output file in the "host dir" we don't actually
1066-
// worry about it, it's not relevant for us.
1091+
// worry about it, it's not relevant for us
10671092
if filename.starts_with(&host_root_dir) {
1093+
// Unless it's a proc macro used in the compiler
1094+
if crate_types.iter().any(|t| t == "proc-macro") {
1095+
deps.push((filename.to_path_buf(), true));
1096+
}
10681097
continue;
10691098
}
10701099

10711100
// If this was output in the `deps` dir then this is a precise file
10721101
// name (hash included) so we start tracking it.
10731102
if filename.starts_with(&target_deps_dir) {
1074-
deps.push(filename.to_path_buf());
1103+
deps.push((filename.to_path_buf(), false));
10751104
continue;
10761105
}
10771106

@@ -1124,10 +1153,10 @@ pub fn run_cargo(builder: &Builder<'_>,
11241153
let candidate = format!("{}.lib", path_to_add);
11251154
let candidate = PathBuf::from(candidate);
11261155
if candidate.exists() {
1127-
deps.push(candidate);
1156+
deps.push((candidate, false));
11281157
}
11291158
}
1130-
deps.push(path_to_add.into());
1159+
deps.push((path_to_add.into(), false));
11311160
}
11321161

11331162
// Now we want to update the contents of the stamp file, if necessary. First
@@ -1140,12 +1169,13 @@ pub fn run_cargo(builder: &Builder<'_>,
11401169
let mut new_contents = Vec::new();
11411170
let mut max = None;
11421171
let mut max_path = None;
1143-
for dep in deps.iter() {
1172+
for (dep, proc_macro) in deps.iter() {
11441173
let mtime = mtime(dep);
11451174
if Some(mtime) > max {
11461175
max = Some(mtime);
11471176
max_path = Some(dep.clone());
11481177
}
1178+
new_contents.extend(if *proc_macro { b"h" } else { b"t" });
11491179
new_contents.extend(dep.to_str().unwrap().as_bytes());
11501180
new_contents.extend(b"\0");
11511181
}
@@ -1157,15 +1187,15 @@ pub fn run_cargo(builder: &Builder<'_>,
11571187
if contents_equal && max <= stamp_mtime {
11581188
builder.verbose(&format!("not updating {:?}; contents equal and {:?} <= {:?}",
11591189
stamp, max, stamp_mtime));
1160-
return deps
1190+
return deps.into_iter().map(|(d, _)| d).collect()
11611191
}
11621192
if max > stamp_mtime {
11631193
builder.verbose(&format!("updating {:?} as {:?} changed", stamp, max_path));
11641194
} else {
11651195
builder.verbose(&format!("updating {:?} as deps changed", stamp));
11661196
}
11671197
t!(fs::write(&stamp, &new_contents));
1168-
deps
1198+
deps.into_iter().map(|(d, _)| d).collect()
11691199
}
11701200

11711201
pub fn stream_cargo(
@@ -1211,13 +1241,19 @@ pub fn stream_cargo(
12111241
status.success()
12121242
}
12131243

1244+
#[derive(Deserialize)]
1245+
pub struct CargoTarget<'a> {
1246+
crate_types: Vec<Cow<'a, str>>,
1247+
}
1248+
12141249
#[derive(Deserialize)]
12151250
#[serde(tag = "reason", rename_all = "kebab-case")]
12161251
pub enum CargoMessage<'a> {
12171252
CompilerArtifact {
12181253
package_id: Cow<'a, str>,
12191254
features: Vec<Cow<'a, str>>,
12201255
filenames: Vec<Cow<'a, str>>,
1256+
target: CargoTarget<'a>,
12211257
},
12221258
BuildScriptExecuted {
12231259
package_id: Cow<'a, str>,

src/bootstrap/lib.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -1129,7 +1129,7 @@ impl Build {
11291129
ret
11301130
}
11311131

1132-
fn read_stamp_file(&self, stamp: &Path) -> Vec<PathBuf> {
1132+
fn read_stamp_file(&self, stamp: &Path) -> Vec<(PathBuf, bool)> {
11331133
if self.config.dry_run {
11341134
return Vec::new();
11351135
}
@@ -1142,8 +1142,9 @@ impl Build {
11421142
if part.is_empty() {
11431143
continue
11441144
}
1145-
let path = PathBuf::from(t!(str::from_utf8(part)));
1146-
paths.push(path);
1145+
let host = part[0] as char == 'h';
1146+
let path = PathBuf::from(t!(str::from_utf8(&part[1..])));
1147+
paths.push((path, host));
11471148
}
11481149
paths
11491150
}

src/bootstrap/tool.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ impl Step for ToolBuild {
9191
compile::CargoMessage::CompilerArtifact {
9292
package_id,
9393
features,
94-
filenames
94+
filenames,
95+
target: _,
9596
} => {
9697
(package_id, features, filenames)
9798
}

src/librustc/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ rustc-rayon = "0.1.2"
2424
rustc-rayon-core = "0.1.2"
2525
rustc_apfloat = { path = "../librustc_apfloat" }
2626
rustc_target = { path = "../librustc_target" }
27+
rustc_macros = { path = "../librustc_macros" }
2728
rustc_data_structures = { path = "../librustc_data_structures" }
2829
errors = { path = "../librustc_errors", package = "rustc_errors" }
2930
serialize = { path = "../libserialize" }

src/librustc/hir/mod.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use crate::ty::query::Providers;
3232

3333
use rustc_data_structures::sync::{ParallelIterator, par_iter, Send, Sync};
3434
use rustc_data_structures::thin_vec::ThinVec;
35+
use rustc_macros::HashStable;
3536

3637
use serialize::{self, Encoder, Encodable, Decoder, Decodable};
3738
use std::collections::{BTreeSet, BTreeMap};
@@ -149,7 +150,7 @@ pub const DUMMY_HIR_ID: HirId = HirId {
149150

150151
pub const DUMMY_ITEM_LOCAL_ID: ItemLocalId = ItemLocalId::MAX;
151152

152-
#[derive(Clone, RustcEncodable, RustcDecodable, Copy)]
153+
#[derive(Clone, RustcEncodable, RustcDecodable, Copy, HashStable)]
153154
pub struct Lifetime {
154155
pub hir_id: HirId,
155156
pub span: Span,

src/librustc/ich/impls_hir.rs

-6
Original file line numberDiff line numberDiff line change
@@ -157,12 +157,6 @@ impl_stable_hash_for!(struct ast::Label {
157157
ident
158158
});
159159

160-
impl_stable_hash_for!(struct hir::Lifetime {
161-
hir_id,
162-
span,
163-
name
164-
});
165-
166160
impl_stable_hash_for!(struct hir::Path {
167161
span,
168162
def,

src/librustc/lib.rs

+2-8
Original file line numberDiff line numberDiff line change
@@ -141,14 +141,8 @@ pub mod util {
141141
pub mod bug;
142142
}
143143

144-
// A private module so that macro-expanded idents like
145-
// `::rustc::lint::Lint` will also work in `rustc` itself.
146-
//
147-
// `libstd` uses the same trick.
148-
#[doc(hidden)]
149-
mod rustc {
150-
pub use crate::lint;
151-
}
144+
// Allows macros to refer to this crate as `::rustc`
145+
extern crate self as rustc;
152146

153147
// FIXME(#27438): right now the unit tests of librustc don't refer to any actual
154148
// functions generated in librustc_data_structures (all

src/librustc/session/config.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1232,6 +1232,8 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
12321232
Use with RUST_REGION_GRAPH=help for more info"),
12331233
parse_only: bool = (false, parse_bool, [UNTRACKED],
12341234
"parse only; do not compile, assemble, or link"),
1235+
dual_proc_macros: bool = (false, parse_bool, [TRACKED],
1236+
"load proc macros for both target and host, but only link to the target"),
12351237
no_codegen: bool = (false, parse_bool, [TRACKED],
12361238
"run all passes except codegen; no output"),
12371239
treat_err_as_bug: bool = (false, parse_bool, [TRACKED],

0 commit comments

Comments
 (0)