Skip to content

Commit 5a2cab4

Browse files
committed
Monomorphize in check mode to avoid almost all PMEs
1 parent f4f5fc3 commit 5a2cab4

File tree

152 files changed

+955
-925
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

152 files changed

+955
-925
lines changed

compiler/rustc_codegen_ssa/src/back/symbol_export.rs

+4-9
Original file line numberDiff line numberDiff line change
@@ -42,10 +42,6 @@ pub fn crates_export_threshold(crate_types: &[CrateType]) -> SymbolExportLevel {
4242
fn reachable_non_generics_provider(tcx: TyCtxt<'_>, cnum: CrateNum) -> DefIdMap<SymbolExportInfo> {
4343
assert_eq!(cnum, LOCAL_CRATE);
4444

45-
if !tcx.sess.opts.output_types.should_codegen() {
46-
return Default::default();
47-
}
48-
4945
// Check to see if this crate is a "special runtime crate". These
5046
// crates, implementation details of the standard library, typically
5147
// have a bunch of `pub extern` and `#[no_mangle]` functions as the
@@ -172,10 +168,6 @@ fn exported_symbols_provider_local(
172168
) -> &[(ExportedSymbol<'_>, SymbolExportInfo)] {
173169
assert_eq!(cnum, LOCAL_CRATE);
174170

175-
if !tcx.sess.opts.output_types.should_codegen() {
176-
return &[];
177-
}
178-
179171
// FIXME: Sorting this is unnecessary since we are sorting later anyway.
180172
// Can we skip the later sorting?
181173
let mut symbols: Vec<_> = tcx.with_stable_hashing_context(|hcx| {
@@ -289,7 +281,10 @@ fn exported_symbols_provider_local(
289281
));
290282
}
291283

292-
if tcx.sess.opts.share_generics() && tcx.local_crate_exports_generics() {
284+
if tcx.sess.opts.share_generics()
285+
&& tcx.local_crate_exports_generics()
286+
&& tcx.sess.opts.output_types.should_codegen()
287+
{
293288
use rustc_middle::mir::mono::{Linkage, MonoItem, Visibility};
294289
use rustc_middle::ty::InstanceDef;
295290

compiler/rustc_driver_impl/src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -342,6 +342,10 @@ fn run_compiler(
342342

343343
queries.global_ctxt()?.enter(|tcx| tcx.analysis(()))?;
344344

345+
if !sess.opts.output_types.should_codegen() && sess.compile_status().is_ok() {
346+
queries.global_ctxt()?.enter(|tcx| tcx.collect_crate_mono_items_for_check(()));
347+
}
348+
345349
if callbacks.after_analysis(compiler, queries) == Compilation::Stop {
346350
return early_exit();
347351
}

compiler/rustc_middle/src/query/mod.rs

+5
Original file line numberDiff line numberDiff line change
@@ -1857,6 +1857,11 @@ rustc_queries! {
18571857
desc { "collect_and_partition_mono_items" }
18581858
}
18591859

1860+
query collect_crate_mono_items_for_check(_: ()) {
1861+
eval_always
1862+
desc { "monomorphize the crate graph" }
1863+
}
1864+
18601865
query is_codegened_item(def_id: DefId) -> bool {
18611866
desc { |tcx| "determining whether `{}` needs codegen", tcx.def_path_str(def_id) }
18621867
}

compiler/rustc_monomorphize/src/collector.rs

+42-9
Original file line numberDiff line numberDiff line change
@@ -203,9 +203,14 @@ use crate::errors::{
203203
EncounteredErrorWhileInstantiating, LargeAssignmentsLint, RecursionLimit, TypeLengthLimit,
204204
};
205205

206-
#[derive(PartialEq)]
206+
#[derive(Debug, Copy, Clone)]
207207
pub enum MonoItemCollectionMode {
208-
Eager,
208+
Eager {
209+
/// Whether to use optimized mir for collection or just analyis MIR.
210+
/// By default uses optimized mir, but for `cargo check` we use unoptimized mir,
211+
/// as that is faster.
212+
optimized_mir: bool,
213+
},
209214
Lazy,
210215
}
211216

@@ -351,6 +356,7 @@ pub fn collect_crate_mono_items(
351356
&mut recursion_depths,
352357
recursion_limit,
353358
inlining_map,
359+
mode,
354360
);
355361
});
356362
});
@@ -408,6 +414,7 @@ fn collect_items_rec<'tcx>(
408414
recursion_depths: &mut DefIdMap<usize>,
409415
recursion_limit: Limit,
410416
inlining_map: MTRef<'_, MTLock<InliningMap<'tcx>>>,
417+
mode: MonoItemCollectionMode,
411418
) {
412419
if !visited.lock_mut().insert(starting_point.node) {
413420
// We've been here already, no need to search again.
@@ -476,7 +483,7 @@ fn collect_items_rec<'tcx>(
476483
check_type_length_limit(tcx, instance);
477484

478485
rustc_data_structures::stack::ensure_sufficient_stack(|| {
479-
collect_neighbours(tcx, instance, &mut neighbors);
486+
collect_neighbours(tcx, instance, &mut neighbors, mode);
480487
});
481488
}
482489
MonoItem::GlobalAsm(item_id) => {
@@ -532,7 +539,15 @@ fn collect_items_rec<'tcx>(
532539
inlining_map.lock_mut().record_accesses(starting_point.node, &neighbors.items);
533540

534541
for (neighbour, _) in neighbors.items {
535-
collect_items_rec(tcx, neighbour, visited, recursion_depths, recursion_limit, inlining_map);
542+
collect_items_rec(
543+
tcx,
544+
neighbour,
545+
visited,
546+
recursion_depths,
547+
recursion_limit,
548+
inlining_map,
549+
mode,
550+
);
536551
}
537552

538553
if let Some((def_id, depth)) = recursion_depth_reset {
@@ -1191,7 +1206,7 @@ impl<'v> RootCollector<'_, 'v> {
11911206
fn process_item(&mut self, id: hir::ItemId) {
11921207
match self.tcx.def_kind(id.owner_id) {
11931208
DefKind::Enum | DefKind::Struct | DefKind::Union => {
1194-
if self.mode == MonoItemCollectionMode::Eager
1209+
if let MonoItemCollectionMode::Eager { .. } = self.mode
11951210
&& self.tcx.generics_of(id.owner_id).count() == 0
11961211
{
11971212
debug!("RootCollector: ADT drop-glue for `{id:?}`",);
@@ -1224,7 +1239,7 @@ impl<'v> RootCollector<'_, 'v> {
12241239
}
12251240
}
12261241
DefKind::Impl { .. } => {
1227-
if self.mode == MonoItemCollectionMode::Eager {
1242+
if let MonoItemCollectionMode::Eager { .. } = self.mode {
12281243
create_mono_items_for_default_impls(self.tcx, id, self.output);
12291244
}
12301245
}
@@ -1244,7 +1259,7 @@ impl<'v> RootCollector<'_, 'v> {
12441259
fn is_root(&self, def_id: LocalDefId) -> bool {
12451260
!item_requires_monomorphization(self.tcx, def_id)
12461261
&& match self.mode {
1247-
MonoItemCollectionMode::Eager => true,
1262+
MonoItemCollectionMode::Eager { .. } => true,
12481263
MonoItemCollectionMode::Lazy => {
12491264
self.entry_fn.and_then(|(id, _)| id.as_local()) == Some(def_id)
12501265
|| self.tcx.is_reachable_non_generic(def_id)
@@ -1396,9 +1411,27 @@ fn collect_neighbours<'tcx>(
13961411
tcx: TyCtxt<'tcx>,
13971412
instance: Instance<'tcx>,
13981413
output: &mut MonoItems<'tcx>,
1414+
mode: MonoItemCollectionMode,
13991415
) {
1400-
let body = tcx.instance_mir(instance.def);
1401-
MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(&body);
1416+
let mut collect = |body: &mir::Body<'tcx>| {
1417+
MirNeighborCollector { tcx, body: &body, output, instance }.visit_body(body)
1418+
};
1419+
if let MonoItemCollectionMode::Eager { optimized_mir: false } = mode {
1420+
if let ty::InstanceDef::Item(def) = instance.def {
1421+
let def_kind = tcx.def_kind(def.did);
1422+
match def_kind {
1423+
// Generators get their optimized_mir taken (and thus drop elab mir stolen) in order
1424+
// to compute their Send/Sync bounds.
1425+
DefKind::Generator |
1426+
DefKind::Ctor(..) => {},
1427+
_ => if let Some(def) = def.as_local() && !tcx.sess.opts.unstable_opts.polymorphize {
1428+
collect(&*tcx.mir_drops_elaborated_and_const_checked(def).borrow());
1429+
return;
1430+
},
1431+
}
1432+
}
1433+
}
1434+
collect(tcx.instance_mir(instance.def));
14021435
}
14031436

14041437
#[instrument(skip(tcx, output), level = "debug")]

compiler/rustc_monomorphize/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#![feature(array_windows)]
2+
#![feature(let_chains)]
23
#![recursion_limit = "256"]
34
#![allow(rustc::potential_query_instability)]
45
#![deny(rustc::untranslatable_diagnostic)]

compiler/rustc_monomorphize/src/partitioning/mod.rs

+10-2
Original file line numberDiff line numberDiff line change
@@ -347,13 +347,20 @@ where
347347
}
348348
}
349349

350+
fn collect_crate_mono_items_for_check(tcx: TyCtxt<'_>, (): ()) {
351+
collector::collect_crate_mono_items(
352+
tcx,
353+
MonoItemCollectionMode::Eager { optimized_mir: false },
354+
);
355+
}
356+
350357
fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[CodegenUnit<'_>]) {
351358
let collection_mode = match tcx.sess.opts.unstable_opts.print_mono_items {
352359
Some(ref s) => {
353360
let mode = s.to_lowercase();
354361
let mode = mode.trim();
355362
if mode == "eager" {
356-
MonoItemCollectionMode::Eager
363+
MonoItemCollectionMode::Eager { optimized_mir: true }
357364
} else {
358365
if mode != "lazy" {
359366
tcx.sess.emit_warning(UnknownCguCollectionMode { mode });
@@ -364,7 +371,7 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> (&DefIdSet, &[Co
364371
}
365372
None => {
366373
if tcx.sess.link_dead_code() {
367-
MonoItemCollectionMode::Eager
374+
MonoItemCollectionMode::Eager { optimized_mir: true }
368375
} else {
369376
MonoItemCollectionMode::Lazy
370377
}
@@ -582,6 +589,7 @@ fn codegened_and_inlined_items(tcx: TyCtxt<'_>, (): ()) -> &DefIdSet {
582589

583590
pub fn provide(providers: &mut Providers) {
584591
providers.collect_and_partition_mono_items = collect_and_partition_mono_items;
592+
providers.collect_crate_mono_items_for_check = collect_crate_mono_items_for_check;
585593
providers.codegened_and_inlined_items = codegened_and_inlined_items;
586594

587595
providers.is_codegened_item = |tcx, def_id| {

tests/ui/associated-consts/defaults-cyclic-fail.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// build-fail
2-
31
// Cyclic assoc. const defaults don't error unless *used*
42
trait Tr {
53
const A: u8 = Self::B;

tests/ui/associated-consts/defaults-cyclic-fail.stderr

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,17 @@
11
error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
2-
--> $DIR/defaults-cyclic-fail.rs:5:19
2+
--> $DIR/defaults-cyclic-fail.rs:3:19
33
|
44
LL | const A: u8 = Self::B;
55
| ^^^^^^^
66
|
77
note: ...which requires const-evaluating + checking `Tr::B`...
8-
--> $DIR/defaults-cyclic-fail.rs:8:19
8+
--> $DIR/defaults-cyclic-fail.rs:6:19
99
|
1010
LL | const B: u8 = Self::A;
1111
| ^^^^^^^
1212
= note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
1313
note: cycle used when const-evaluating + checking `main::promoted[1]`
14-
--> $DIR/defaults-cyclic-fail.rs:16:16
14+
--> $DIR/defaults-cyclic-fail.rs:14:16
1515
|
1616
LL | assert_eq!(<() as Tr>::A, 0);
1717
| ^^^^^^^^^^^^^

tests/ui/associated-consts/defaults-not-assumed-fail.rs

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
// build-fail
2-
31
trait Tr {
42
const A: u8 = 255;
53

tests/ui/associated-consts/defaults-not-assumed-fail.stderr

+4-12
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,25 @@
11
error[E0080]: evaluation of `<() as Tr>::B` failed
2-
--> $DIR/defaults-not-assumed-fail.rs:8:19
2+
--> $DIR/defaults-not-assumed-fail.rs:6:19
33
|
44
LL | const B: u8 = Self::A + 1;
55
| ^^^^^^^^^^^ attempt to compute `u8::MAX + 1_u8`, which would overflow
66

77
note: erroneous constant used
8-
--> $DIR/defaults-not-assumed-fail.rs:33:16
8+
--> $DIR/defaults-not-assumed-fail.rs:31:16
99
|
1010
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
1111
| ^^^^^^^^^^^^^
1212

1313
note: erroneous constant used
14-
--> $DIR/defaults-not-assumed-fail.rs:33:5
14+
--> $DIR/defaults-not-assumed-fail.rs:31:5
1515
|
1616
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
1717
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
1818
|
1919
= note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
2020

2121
note: erroneous constant used
22-
--> $DIR/defaults-not-assumed-fail.rs:33:5
23-
|
24-
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
25-
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
26-
|
27-
= note: this note originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
28-
29-
note: erroneous constant used
30-
--> $DIR/defaults-not-assumed-fail.rs:33:5
22+
--> $DIR/defaults-not-assumed-fail.rs:31:5
3123
|
3224
LL | assert_eq!(<() as Tr>::B, 0); // causes the error above
3325
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

tests/ui/async-await/large_moves.attribute.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: moving 10024 bytes
2-
--> $DIR/large_moves.rs:13:13
2+
--> $DIR/large_moves.rs:12:13
33
|
44
LL | let x = async {
55
| _____________^
@@ -18,23 +18,23 @@ LL | #![deny(large_assignments)]
1818
| ^^^^^^^^^^^^^^^^^
1919

2020
error: moving 10024 bytes
21-
--> $DIR/large_moves.rs:19:14
21+
--> $DIR/large_moves.rs:18:14
2222
|
2323
LL | let z = (x, 42);
2424
| ^ value moved from here
2525
|
2626
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
2727

2828
error: moving 10024 bytes
29-
--> $DIR/large_moves.rs:19:13
29+
--> $DIR/large_moves.rs:18:13
3030
|
3131
LL | let z = (x, 42);
3232
| ^^^^^^^ value moved from here
3333
|
3434
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
3535

3636
error: moving 10024 bytes
37-
--> $DIR/large_moves.rs:21:13
37+
--> $DIR/large_moves.rs:20:13
3838
|
3939
LL | let a = z.0;
4040
| ^^^ value moved from here

tests/ui/async-await/large_moves.option.stderr

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: moving 10024 bytes
2-
--> $DIR/large_moves.rs:13:13
2+
--> $DIR/large_moves.rs:12:13
33
|
44
LL | let x = async {
55
| _____________^
@@ -18,23 +18,23 @@ LL | #![deny(large_assignments)]
1818
| ^^^^^^^^^^^^^^^^^
1919

2020
error: moving 10024 bytes
21-
--> $DIR/large_moves.rs:19:14
21+
--> $DIR/large_moves.rs:18:14
2222
|
2323
LL | let z = (x, 42);
2424
| ^ value moved from here
2525
|
2626
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
2727

2828
error: moving 10024 bytes
29-
--> $DIR/large_moves.rs:19:13
29+
--> $DIR/large_moves.rs:18:13
3030
|
3131
LL | let z = (x, 42);
3232
| ^^^^^^^ value moved from here
3333
|
3434
= note: The current maximum size is 1000, but it can be customized with the move_size_limit attribute: `#![move_size_limit = "..."]`
3535

3636
error: moving 10024 bytes
37-
--> $DIR/large_moves.rs:21:13
37+
--> $DIR/large_moves.rs:20:13
3838
|
3939
LL | let a = z.0;
4040
| ^^^ value moved from here

tests/ui/async-await/large_moves.rs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
#![deny(large_assignments)]
22
#![feature(large_assignments)]
33
#![cfg_attr(attribute, move_size_limit = "1000")]
4-
// build-fail
54
// only-x86_64
65
// revisions: attribute option
76
// [option]compile-flags: -Zmove-size-limit=1000

tests/ui/async-await/mutually-recursive-async-impl-trait-type.stderr

-21
This file was deleted.

tests/ui/async-await/recursive-async-impl-trait-type.stderr

-12
This file was deleted.

0 commit comments

Comments
 (0)