Skip to content

Commit 69656fa

Browse files
committed
Auto merge of #62659 - Centril:rollup-90oz643, r=Centril
Rollup of 5 pull requests Successful merges: - #62577 (Add an AtomicCell abstraction) - #62585 (Make struct_tail normalize when possible) - #62604 (Handle errors during error recovery gracefully) - #62636 (rustbuild: Improve assert about building tools once) - #62651 (Make some rustc macros more hygienic) Failed merges: r? @ghost
2 parents ec30876 + 791ceb6 commit 69656fa

File tree

32 files changed

+313
-88
lines changed

32 files changed

+313
-88
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3018,6 +3018,7 @@ name = "rustc_data_structures"
30183018
version = "0.0.0"
30193019
dependencies = [
30203020
"cfg-if 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)",
3021+
"crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)",
30213022
"ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
30223023
"graphviz 0.0.0",
30233024
"indexmap 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",

src/bootstrap/tool.rs

+48-21
Original file line numberDiff line numberDiff line change
@@ -109,36 +109,63 @@ impl Step for ToolBuild {
109109
continue
110110
}
111111

112-
// Don't worry about libs that turn out to be host dependencies
113-
// or build scripts, we only care about target dependencies that
114-
// are in `deps`.
115-
if let Some(maybe_target) = val.1
116-
.parent() // chop off file name
117-
.and_then(|p| p.parent()) // chop off `deps`
118-
.and_then(|p| p.parent()) // chop off `release`
119-
.and_then(|p| p.file_name())
120-
.and_then(|p| p.to_str())
121-
{
122-
if maybe_target != &*target {
123-
continue
112+
// Don't worry about compiles that turn out to be host
113+
// dependencies or build scripts. To skip these we look for
114+
// anything that goes in `.../release/deps` but *doesn't* go in
115+
// `$target/release/deps`. This ensure that outputs in
116+
// `$target/release` are still considered candidates for
117+
// deduplication.
118+
if let Some(parent) = val.1.parent() {
119+
if parent.ends_with("release/deps") {
120+
let maybe_target = parent
121+
.parent()
122+
.and_then(|p| p.parent())
123+
.and_then(|p| p.file_name())
124+
.and_then(|p| p.to_str())
125+
.unwrap();
126+
if maybe_target != &*target {
127+
continue;
128+
}
124129
}
125130
}
126131

132+
// Record that we've built an artifact for `id`, and if one was
133+
// already listed then we need to see if we reused the same
134+
// artifact or produced a duplicate.
127135
let mut artifacts = builder.tool_artifacts.borrow_mut();
128136
let prev_artifacts = artifacts
129137
.entry(target)
130138
.or_default();
131-
if let Some(prev) = prev_artifacts.get(&*id) {
132-
if prev.1 != val.1 {
133-
duplicates.push((
134-
id.to_string(),
135-
val,
136-
prev.clone(),
137-
));
139+
let prev = match prev_artifacts.get(&*id) {
140+
Some(prev) => prev,
141+
None => {
142+
prev_artifacts.insert(id.to_string(), val);
143+
continue;
138144
}
139-
return
145+
};
146+
if prev.1 == val.1 {
147+
return; // same path, same artifact
140148
}
141-
prev_artifacts.insert(id.to_string(), val);
149+
150+
// If the paths are different and one of them *isn't* inside of
151+
// `release/deps`, then it means it's probably in
152+
// `$target/release`, or it's some final artifact like
153+
// `libcargo.rlib`. In these situations Cargo probably just
154+
// copied it up from `$target/release/deps/libcargo-xxxx.rlib`,
155+
// so if the features are equal we can just skip it.
156+
let prev_no_hash = prev.1.parent().unwrap().ends_with("release/deps");
157+
let val_no_hash = val.1.parent().unwrap().ends_with("release/deps");
158+
if prev.2 == val.2 || !prev_no_hash || !val_no_hash {
159+
return;
160+
}
161+
162+
// ... and otherwise this looks like we duplicated some sort of
163+
// compilation, so record it to generate an error later.
164+
duplicates.push((
165+
id.to_string(),
166+
val,
167+
prev.clone(),
168+
));
142169
}
143170
});
144171

src/librustc/lib.rs

-2
Original file line numberDiff line numberDiff line change
@@ -49,15 +49,13 @@
4949
#![feature(optin_builtin_traits)]
5050
#![feature(range_is_empty)]
5151
#![feature(rustc_diagnostic_macros)]
52-
#![feature(rustc_attrs)]
5352
#![feature(slice_patterns)]
5453
#![feature(specialization)]
5554
#![feature(unboxed_closures)]
5655
#![feature(thread_local)]
5756
#![feature(trace_macros)]
5857
#![feature(trusted_len)]
5958
#![feature(vec_remove_item)]
60-
#![feature(step_trait)]
6159
#![feature(stmt_expr_attributes)]
6260
#![feature(integer_atomics)]
6361
#![feature(test)]

src/librustc/ty/layout.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
543543
return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
544544
}
545545

546-
let unsized_part = tcx.struct_tail(pointee);
546+
let unsized_part = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
547547
let metadata = match unsized_part.sty {
548548
ty::Foreign(..) => {
549549
return Ok(tcx.intern_layout(LayoutDetails::scalar(self, data_ptr)));
@@ -1664,7 +1664,7 @@ impl<'tcx> SizeSkeleton<'tcx> {
16641664
ty::Ref(_, pointee, _) |
16651665
ty::RawPtr(ty::TypeAndMut { ty: pointee, .. }) => {
16661666
let non_zero = !ty.is_unsafe_ptr();
1667-
let tail = tcx.struct_tail(pointee);
1667+
let tail = tcx.struct_tail_erasing_lifetimes(pointee, param_env);
16681668
match tail.sty {
16691669
ty::Param(_) | ty::Projection(_) => {
16701670
debug_assert!(tail.has_param_types() || tail.has_self_ty());
@@ -2015,7 +2015,7 @@ where
20152015
}));
20162016
}
20172017

2018-
match tcx.struct_tail(pointee).sty {
2018+
match tcx.struct_tail_erasing_lifetimes(pointee, cx.param_env()).sty {
20192019
ty::Slice(_) |
20202020
ty::Str => tcx.types.usize,
20212021
ty::Dynamic(_, _) => {

src/librustc/ty/util.rs

+94-8
Original file line numberDiff line numberDiff line change
@@ -257,10 +257,46 @@ impl<'tcx> TyCtxt<'tcx> {
257257
false
258258
}
259259

260-
/// Returns the deeply last field of nested structures, or the same type,
261-
/// if not a structure at all. Corresponds to the only possible unsized
262-
/// field, and its type can be used to determine unsizing strategy.
263-
pub fn struct_tail(self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
260+
/// Attempts to returns the deeply last field of nested structures, but
261+
/// does not apply any normalization in its search. Returns the same type
262+
/// if input `ty` is not a structure at all.
263+
pub fn struct_tail_without_normalization(self, ty: Ty<'tcx>) -> Ty<'tcx>
264+
{
265+
let tcx = self;
266+
tcx.struct_tail_with_normalize(ty, |ty| ty)
267+
}
268+
269+
/// Returns the deeply last field of nested structures, or the same type if
270+
/// not a structure at all. Corresponds to the only possible unsized field,
271+
/// and its type can be used to determine unsizing strategy.
272+
///
273+
/// Should only be called if `ty` has no inference variables and does not
274+
/// need its lifetimes preserved (e.g. as part of codegen); otherwise
275+
/// normalization attempt may cause compiler bugs.
276+
pub fn struct_tail_erasing_lifetimes(self,
277+
ty: Ty<'tcx>,
278+
param_env: ty::ParamEnv<'tcx>)
279+
-> Ty<'tcx>
280+
{
281+
let tcx = self;
282+
tcx.struct_tail_with_normalize(ty, |ty| tcx.normalize_erasing_regions(param_env, ty))
283+
}
284+
285+
/// Returns the deeply last field of nested structures, or the same type if
286+
/// not a structure at all. Corresponds to the only possible unsized field,
287+
/// and its type can be used to determine unsizing strategy.
288+
///
289+
/// This is parameterized over the normalization strategy (i.e. how to
290+
/// handle `<T as Trait>::Assoc` and `impl Trait`); pass the identity
291+
/// function to indicate no normalization should take place.
292+
///
293+
/// See also `struct_tail_erasing_lifetimes`, which is suitable for use
294+
/// during codegen.
295+
pub fn struct_tail_with_normalize(self,
296+
mut ty: Ty<'tcx>,
297+
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>)
298+
-> Ty<'tcx>
299+
{
264300
loop {
265301
match ty.sty {
266302
ty::Adt(def, substs) => {
@@ -281,6 +317,15 @@ impl<'tcx> TyCtxt<'tcx> {
281317
}
282318
}
283319

320+
ty::Projection(_) | ty::Opaque(..) => {
321+
let normalized = normalize(ty);
322+
if ty == normalized {
323+
return ty;
324+
} else {
325+
ty = normalized;
326+
}
327+
}
328+
284329
_ => {
285330
break;
286331
}
@@ -294,10 +339,35 @@ impl<'tcx> TyCtxt<'tcx> {
294339
/// structure definitions.
295340
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
296341
/// whereas struct_tail produces `T`, and `Trait`, respectively.
297-
pub fn struct_lockstep_tails(self,
298-
source: Ty<'tcx>,
299-
target: Ty<'tcx>)
300-
-> (Ty<'tcx>, Ty<'tcx>) {
342+
///
343+
/// Should only be called if the types have no inference variables and do
344+
/// not need their lifetimes preserved (e.g. as part of codegen); otherwise
345+
/// normalization attempt may cause compiler bugs.
346+
pub fn struct_lockstep_tails_erasing_lifetimes(self,
347+
source: Ty<'tcx>,
348+
target: Ty<'tcx>,
349+
param_env: ty::ParamEnv<'tcx>)
350+
-> (Ty<'tcx>, Ty<'tcx>)
351+
{
352+
let tcx = self;
353+
tcx.struct_lockstep_tails_with_normalize(
354+
source, target, |ty| tcx.normalize_erasing_regions(param_env, ty))
355+
}
356+
357+
/// Same as applying struct_tail on `source` and `target`, but only
358+
/// keeps going as long as the two types are instances of the same
359+
/// structure definitions.
360+
/// For `(Foo<Foo<T>>, Foo<dyn Trait>)`, the result will be `(Foo<T>, Trait)`,
361+
/// whereas struct_tail produces `T`, and `Trait`, respectively.
362+
///
363+
/// See also `struct_lockstep_tails_erasing_lifetimes`, which is suitable for use
364+
/// during codegen.
365+
pub fn struct_lockstep_tails_with_normalize(self,
366+
source: Ty<'tcx>,
367+
target: Ty<'tcx>,
368+
normalize: impl Fn(Ty<'tcx>) -> Ty<'tcx>)
369+
-> (Ty<'tcx>, Ty<'tcx>)
370+
{
301371
let (mut a, mut b) = (source, target);
302372
loop {
303373
match (&a.sty, &b.sty) {
@@ -319,6 +389,22 @@ impl<'tcx> TyCtxt<'tcx> {
319389
break;
320390
}
321391
},
392+
(ty::Projection(_), _) | (ty::Opaque(..), _) |
393+
(_, ty::Projection(_)) | (_, ty::Opaque(..)) => {
394+
// If either side is a projection, attempt to
395+
// progress via normalization. (Should be safe to
396+
// apply to both sides as normalization is
397+
// idempotent.)
398+
let a_norm = normalize(a);
399+
let b_norm = normalize(b);
400+
if a == a_norm && b == b_norm {
401+
break;
402+
} else {
403+
a = a_norm;
404+
b = b_norm;
405+
}
406+
}
407+
322408
_ => break,
323409
}
324410
}

src/librustc_codegen_ssa/base.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,8 @@ pub fn unsized_info<'tcx, Cx: CodegenMethods<'tcx>>(
128128
target: Ty<'tcx>,
129129
old_info: Option<Cx::Value>,
130130
) -> Cx::Value {
131-
let (source, target) = cx.tcx().struct_lockstep_tails(source, target);
131+
let (source, target) =
132+
cx.tcx().struct_lockstep_tails_erasing_lifetimes(source, target, cx.param_env());
132133
match (&source.sty, &target.sty) {
133134
(&ty::Array(_, len), &ty::Slice(_)) => {
134135
cx.const_usize(len.unwrap_usize(cx.tcx()))

src/librustc_codegen_ssa/traits/type_.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,12 @@ pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
7777
}
7878

7979
fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
80-
if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
80+
let param_env = ty::ParamEnv::reveal_all();
81+
if ty.is_sized(self.tcx().at(DUMMY_SP), param_env) {
8182
return false;
8283
}
8384

84-
let tail = self.tcx().struct_tail(ty);
85+
let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env);
8586
match tail.sty {
8687
ty::Foreign(..) => false,
8788
ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,

src/librustc_data_structures/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ lazy_static = "1"
1818
serialize = { path = "../libserialize" }
1919
graphviz = { path = "../libgraphviz" }
2020
cfg-if = "0.1.2"
21+
crossbeam-utils = { version = "0.6.5", features = ["nightly"] }
2122
stable_deref_trait = "1.0.0"
2223
rayon = { version = "0.2.0", package = "rustc-rayon" }
2324
rayon-core = { version = "0.2.0", package = "rustc-rayon-core" }

0 commit comments

Comments
 (0)