Skip to content

Commit 1221e43

Browse files
committedMay 26, 2023
Auto merge of #111984 - matthiaskrgr:rollup-6u7ynyv, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #111384 (Fix linking Mac Catalyst by including LC_BUILD_VERSION in object files) - #111899 (CGU cleanups) - #111940 (Clarify safety concern of `io::Read::read` is only relevant in unsafe code) - #111947 (Add test for RPIT defined with different hidden types with different substs) - #111951 (Correct comment on privately uninhabited pattern.) Failed merges: - #111954 (improve error message for calling a method on a raw pointer with an unknown pointee) r? `@ghost` `@rustbot` modify labels: rollup
·
1.90.01.71.0
2 parents be72f25 + dd74ae0 commit 1221e43

File tree

14 files changed

+424
-289
lines changed

14 files changed

+424
-289
lines changed
 

‎compiler/rustc_codegen_ssa/src/back/metadata.rs‎

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,11 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
188188
};
189189

190190
let mut file = write::Object::new(binary_format, architecture, endianness);
191+
if sess.target.is_like_osx {
192+
if let Some(build_version) = macho_object_build_version_for_target(&sess.target) {
193+
file.set_macho_build_version(build_version)
194+
}
195+
}
191196
let e_flags = match architecture {
192197
Architecture::Mips => {
193198
let arch = match sess.target.options.cpu.as_ref() {
@@ -258,6 +263,33 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
258263
Some(file)
259264
}
260265

266+
/// Apple's LD, when linking for Mac Catalyst, requires object files to
267+
/// contain information about what they were built for (LC_BUILD_VERSION):
268+
/// the platform (macOS/watchOS etc), minimum OS version, and SDK version.
269+
/// This returns a `MachOBuildVersion` if necessary for the target.
270+
fn macho_object_build_version_for_target(
271+
target: &Target,
272+
) -> Option<object::write::MachOBuildVersion> {
273+
if !target.llvm_target.ends_with("-macabi") {
274+
return None;
275+
}
276+
/// The `object` crate demands "X.Y.Z encoded in nibbles as xxxx.yy.zz"
277+
/// e.g. minOS 14.0 = 0x000E0000, or SDK 16.2 = 0x00100200
278+
fn pack_version((major, minor): (u32, u32)) -> u32 {
279+
(major << 16) | (minor << 8)
280+
}
281+
282+
let platform = object::macho::PLATFORM_MACCATALYST;
283+
let min_os = (14, 0);
284+
let sdk = (16, 2);
285+
286+
let mut build_version = object::write::MachOBuildVersion::default();
287+
build_version.platform = platform;
288+
build_version.minos = pack_version(min_os);
289+
build_version.sdk = pack_version(sdk);
290+
Some(build_version)
291+
}
292+
261293
pub enum MetadataPosition {
262294
First,
263295
Last,

‎compiler/rustc_middle/src/mir/mono.rs‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,7 @@ impl<'tcx> CodegenUnit<'tcx> {
334334
}
335335

336336
pub fn modify_size_estimate(&mut self, delta: usize) {
337-
assert!(self.size_estimate.is_some());
338-
if let Some(size_estimate) = self.size_estimate {
339-
self.size_estimate = Some(size_estimate + delta);
340-
}
337+
*self.size_estimate.as_mut().unwrap() += delta;
341338
}
342339

343340
pub fn contains_item(&self, item: &MonoItem<'tcx>) -> bool {

‎compiler/rustc_mir_build/src/thir/pattern/check_match.rs‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -491,8 +491,8 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
491491
AdtDefinedHere { adt_def_span, ty, variants }
492492
};
493493

494-
// Emit an extra note if the first uncovered witness is
495-
// visibly uninhabited anywhere in the current crate.
494+
// Emit an extra note if the first uncovered witness would be uninhabited
495+
// if we disregard visibility.
496496
let witness_1_is_privately_uninhabited =
497497
if cx.tcx.features().exhaustive_patterns
498498
&& let Some(witness_1) = witnesses.get(0)

‎compiler/rustc_monomorphize/src/partitioning/default.rs‎

Lines changed: 113 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use std::cmp;
12
use std::collections::hash_map::Entry;
23

34
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
@@ -14,10 +15,7 @@ use rustc_span::symbol::Symbol;
1415

1516
use super::PartitioningCx;
1617
use crate::collector::InliningMap;
17-
use crate::partitioning::merging;
18-
use crate::partitioning::{
19-
MonoItemPlacement, Partition, PostInliningPartitioning, PreInliningPartitioning,
20-
};
18+
use crate::partitioning::{MonoItemPlacement, Partition, PlacedRootMonoItems};
2119

2220
pub struct DefaultPartitioning;
2321

@@ -26,7 +24,7 @@ impl<'tcx> Partition<'tcx> for DefaultPartitioning {
2624
&mut self,
2725
cx: &PartitioningCx<'_, 'tcx>,
2826
mono_items: &mut I,
29-
) -> PreInliningPartitioning<'tcx>
27+
) -> PlacedRootMonoItems<'tcx>
3028
where
3129
I: Iterator<Item = MonoItem<'tcx>>,
3230
{
@@ -91,38 +89,120 @@ impl<'tcx> Partition<'tcx> for DefaultPartitioning {
9189
codegen_units.insert(codegen_unit_name, CodegenUnit::new(codegen_unit_name));
9290
}
9391

94-
PreInliningPartitioning {
95-
codegen_units: codegen_units.into_values().collect(),
96-
roots,
97-
internalization_candidates,
98-
}
92+
let codegen_units = codegen_units.into_values().collect();
93+
PlacedRootMonoItems { codegen_units, roots, internalization_candidates }
9994
}
10095

10196
fn merge_codegen_units(
10297
&mut self,
10398
cx: &PartitioningCx<'_, 'tcx>,
104-
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
99+
codegen_units: &mut Vec<CodegenUnit<'tcx>>,
105100
) {
106-
merging::merge_codegen_units(cx, initial_partitioning);
101+
assert!(cx.target_cgu_count >= 1);
102+
103+
// Note that at this point in time the `codegen_units` here may not be
104+
// in a deterministic order (but we know they're deterministically the
105+
// same set). We want this merging to produce a deterministic ordering
106+
// of codegen units from the input.
107+
//
108+
// Due to basically how we've implemented the merging below (merge the
109+
// two smallest into each other) we're sure to start off with a
110+
// deterministic order (sorted by name). This'll mean that if two cgus
111+
// have the same size the stable sort below will keep everything nice
112+
// and deterministic.
113+
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
114+
115+
// This map keeps track of what got merged into what.
116+
let mut cgu_contents: FxHashMap<Symbol, Vec<Symbol>> =
117+
codegen_units.iter().map(|cgu| (cgu.name(), vec![cgu.name()])).collect();
118+
119+
// Merge the two smallest codegen units until the target size is
120+
// reached.
121+
while codegen_units.len() > cx.target_cgu_count {
122+
// Sort small cgus to the back
123+
codegen_units.sort_by_cached_key(|cgu| cmp::Reverse(cgu.size_estimate()));
124+
let mut smallest = codegen_units.pop().unwrap();
125+
let second_smallest = codegen_units.last_mut().unwrap();
126+
127+
// Move the mono-items from `smallest` to `second_smallest`
128+
second_smallest.modify_size_estimate(smallest.size_estimate());
129+
for (k, v) in smallest.items_mut().drain() {
130+
second_smallest.items_mut().insert(k, v);
131+
}
132+
133+
// Record that `second_smallest` now contains all the stuff that was
134+
// in `smallest` before.
135+
let mut consumed_cgu_names = cgu_contents.remove(&smallest.name()).unwrap();
136+
cgu_contents.get_mut(&second_smallest.name()).unwrap().append(&mut consumed_cgu_names);
137+
138+
debug!(
139+
"CodegenUnit {} merged into CodegenUnit {}",
140+
smallest.name(),
141+
second_smallest.name()
142+
);
143+
}
144+
145+
let cgu_name_builder = &mut CodegenUnitNameBuilder::new(cx.tcx);
146+
147+
if cx.tcx.sess.opts.incremental.is_some() {
148+
// If we are doing incremental compilation, we want CGU names to
149+
// reflect the path of the source level module they correspond to.
150+
// For CGUs that contain the code of multiple modules because of the
151+
// merging done above, we use a concatenation of the names of all
152+
// contained CGUs.
153+
let new_cgu_names: FxHashMap<Symbol, String> = cgu_contents
154+
.into_iter()
155+
// This `filter` makes sure we only update the name of CGUs that
156+
// were actually modified by merging.
157+
.filter(|(_, cgu_contents)| cgu_contents.len() > 1)
158+
.map(|(current_cgu_name, cgu_contents)| {
159+
let mut cgu_contents: Vec<&str> =
160+
cgu_contents.iter().map(|s| s.as_str()).collect();
161+
162+
// Sort the names, so things are deterministic and easy to
163+
// predict. We are sorting primitive `&str`s here so we can
164+
// use unstable sort.
165+
cgu_contents.sort_unstable();
166+
167+
(current_cgu_name, cgu_contents.join("--"))
168+
})
169+
.collect();
170+
171+
for cgu in codegen_units.iter_mut() {
172+
if let Some(new_cgu_name) = new_cgu_names.get(&cgu.name()) {
173+
if cx.tcx.sess.opts.unstable_opts.human_readable_cgu_names {
174+
cgu.set_name(Symbol::intern(&new_cgu_name));
175+
} else {
176+
// If we don't require CGU names to be human-readable,
177+
// we use a fixed length hash of the composite CGU name
178+
// instead.
179+
let new_cgu_name = CodegenUnit::mangle_name(&new_cgu_name);
180+
cgu.set_name(Symbol::intern(&new_cgu_name));
181+
}
182+
}
183+
}
184+
} else {
185+
// If we are compiling non-incrementally we just generate simple CGU
186+
// names containing an index.
187+
for (index, cgu) in codegen_units.iter_mut().enumerate() {
188+
let numbered_codegen_unit_name =
189+
cgu_name_builder.build_cgu_name_no_mangle(LOCAL_CRATE, &["cgu"], Some(index));
190+
cgu.set_name(numbered_codegen_unit_name);
191+
}
192+
}
107193
}
108194

109195
fn place_inlined_mono_items(
110196
&mut self,
111197
cx: &PartitioningCx<'_, 'tcx>,
112-
initial_partitioning: PreInliningPartitioning<'tcx>,
113-
) -> PostInliningPartitioning<'tcx> {
114-
let mut new_partitioning = Vec::new();
198+
codegen_units: &mut [CodegenUnit<'tcx>],
199+
roots: FxHashSet<MonoItem<'tcx>>,
200+
) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
115201
let mut mono_item_placements = FxHashMap::default();
116202

117-
let PreInliningPartitioning {
118-
codegen_units: initial_cgus,
119-
roots,
120-
internalization_candidates,
121-
} = initial_partitioning;
122-
123-
let single_codegen_unit = initial_cgus.len() == 1;
203+
let single_codegen_unit = codegen_units.len() == 1;
124204

125-
for old_codegen_unit in initial_cgus {
205+
for old_codegen_unit in codegen_units.iter_mut() {
126206
// Collect all items that need to be available in this codegen unit.
127207
let mut reachable = FxHashSet::default();
128208
for root in old_codegen_unit.items().keys() {
@@ -174,14 +254,10 @@ impl<'tcx> Partition<'tcx> for DefaultPartitioning {
174254
}
175255
}
176256

177-
new_partitioning.push(new_codegen_unit);
257+
*old_codegen_unit = new_codegen_unit;
178258
}
179259

180-
return PostInliningPartitioning {
181-
codegen_units: new_partitioning,
182-
mono_item_placements,
183-
internalization_candidates,
184-
};
260+
return mono_item_placements;
185261

186262
fn follow_inlining<'tcx>(
187263
mono_item: MonoItem<'tcx>,
@@ -201,14 +277,16 @@ impl<'tcx> Partition<'tcx> for DefaultPartitioning {
201277
fn internalize_symbols(
202278
&mut self,
203279
cx: &PartitioningCx<'_, 'tcx>,
204-
partitioning: &mut PostInliningPartitioning<'tcx>,
280+
codegen_units: &mut [CodegenUnit<'tcx>],
281+
mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
282+
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
205283
) {
206-
if partitioning.codegen_units.len() == 1 {
284+
if codegen_units.len() == 1 {
207285
// Fast path for when there is only one codegen unit. In this case we
208286
// can internalize all candidates, since there is nowhere else they
209287
// could be accessed from.
210-
for cgu in &mut partitioning.codegen_units {
211-
for candidate in &partitioning.internalization_candidates {
288+
for cgu in codegen_units {
289+
for candidate in &internalization_candidates {
212290
cgu.items_mut().insert(*candidate, (Linkage::Internal, Visibility::Default));
213291
}
214292
}
@@ -225,15 +303,13 @@ impl<'tcx> Partition<'tcx> for DefaultPartitioning {
225303
}
226304
});
227305

228-
let mono_item_placements = &partitioning.mono_item_placements;
229-
230306
// For each internalization candidates in each codegen unit, check if it is
231307
// accessed from outside its defining codegen unit.
232-
for cgu in &mut partitioning.codegen_units {
308+
for cgu in codegen_units {
233309
let home_cgu = MonoItemPlacement::SingleCgu { cgu_name: cgu.name() };
234310

235311
for (accessee, linkage_and_visibility) in cgu.items_mut() {
236-
if !partitioning.internalization_candidates.contains(accessee) {
312+
if !internalization_candidates.contains(accessee) {
237313
// This item is no candidate for internalizing, so skip it.
238314
continue;
239315
}

‎compiler/rustc_monomorphize/src/partitioning/merging.rs‎

Lines changed: 0 additions & 111 deletions
This file was deleted.

‎compiler/rustc_monomorphize/src/partitioning/mod.rs‎

Lines changed: 55 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,6 @@
9393
//! inlining, even when they are not marked `#[inline]`.
9494
9595
mod default;
96-
mod merging;
9796

9897
use std::cmp;
9998
use std::fs::{self, File};
@@ -129,7 +128,7 @@ impl<'tcx> Partition<'tcx> for Partitioner {
129128
&mut self,
130129
cx: &PartitioningCx<'_, 'tcx>,
131130
mono_items: &mut I,
132-
) -> PreInliningPartitioning<'tcx>
131+
) -> PlacedRootMonoItems<'tcx>
133132
where
134133
I: Iterator<Item = MonoItem<'tcx>>,
135134
{
@@ -142,24 +141,23 @@ impl<'tcx> Partition<'tcx> for Partitioner {
142141
fn merge_codegen_units(
143142
&mut self,
144143
cx: &PartitioningCx<'_, 'tcx>,
145-
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
144+
codegen_units: &mut Vec<CodegenUnit<'tcx>>,
146145
) {
147146
match self {
148-
Partitioner::Default(partitioner) => {
149-
partitioner.merge_codegen_units(cx, initial_partitioning)
150-
}
147+
Partitioner::Default(partitioner) => partitioner.merge_codegen_units(cx, codegen_units),
151148
Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
152149
}
153150
}
154151

155152
fn place_inlined_mono_items(
156153
&mut self,
157154
cx: &PartitioningCx<'_, 'tcx>,
158-
initial_partitioning: PreInliningPartitioning<'tcx>,
159-
) -> PostInliningPartitioning<'tcx> {
155+
codegen_units: &mut [CodegenUnit<'tcx>],
156+
roots: FxHashSet<MonoItem<'tcx>>,
157+
) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement> {
160158
match self {
161159
Partitioner::Default(partitioner) => {
162-
partitioner.place_inlined_mono_items(cx, initial_partitioning)
160+
partitioner.place_inlined_mono_items(cx, codegen_units, roots)
163161
}
164162
Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
165163
}
@@ -168,48 +166,62 @@ impl<'tcx> Partition<'tcx> for Partitioner {
168166
fn internalize_symbols(
169167
&mut self,
170168
cx: &PartitioningCx<'_, 'tcx>,
171-
post_inlining_partitioning: &mut PostInliningPartitioning<'tcx>,
169+
codegen_units: &mut [CodegenUnit<'tcx>],
170+
mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
171+
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
172172
) {
173173
match self {
174-
Partitioner::Default(partitioner) => {
175-
partitioner.internalize_symbols(cx, post_inlining_partitioning)
176-
}
174+
Partitioner::Default(partitioner) => partitioner.internalize_symbols(
175+
cx,
176+
codegen_units,
177+
mono_item_placements,
178+
internalization_candidates,
179+
),
177180
Partitioner::Unknown => cx.tcx.sess.emit_fatal(UnknownPartitionStrategy),
178181
}
179182
}
180183
}
181184

182-
pub struct PartitioningCx<'a, 'tcx> {
185+
struct PartitioningCx<'a, 'tcx> {
183186
tcx: TyCtxt<'tcx>,
184187
target_cgu_count: usize,
185188
inlining_map: &'a InliningMap<'tcx>,
186189
}
187190

191+
pub struct PlacedRootMonoItems<'tcx> {
192+
codegen_units: Vec<CodegenUnit<'tcx>>,
193+
roots: FxHashSet<MonoItem<'tcx>>,
194+
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
195+
}
196+
188197
trait Partition<'tcx> {
189198
fn place_root_mono_items<I>(
190199
&mut self,
191200
cx: &PartitioningCx<'_, 'tcx>,
192201
mono_items: &mut I,
193-
) -> PreInliningPartitioning<'tcx>
202+
) -> PlacedRootMonoItems<'tcx>
194203
where
195204
I: Iterator<Item = MonoItem<'tcx>>;
196205

197206
fn merge_codegen_units(
198207
&mut self,
199208
cx: &PartitioningCx<'_, 'tcx>,
200-
initial_partitioning: &mut PreInliningPartitioning<'tcx>,
209+
codegen_units: &mut Vec<CodegenUnit<'tcx>>,
201210
);
202211

203212
fn place_inlined_mono_items(
204213
&mut self,
205214
cx: &PartitioningCx<'_, 'tcx>,
206-
initial_partitioning: PreInliningPartitioning<'tcx>,
207-
) -> PostInliningPartitioning<'tcx>;
215+
codegen_units: &mut [CodegenUnit<'tcx>],
216+
roots: FxHashSet<MonoItem<'tcx>>,
217+
) -> FxHashMap<MonoItem<'tcx>, MonoItemPlacement>;
208218

209219
fn internalize_symbols(
210220
&mut self,
211221
cx: &PartitioningCx<'_, 'tcx>,
212-
partitioning: &mut PostInliningPartitioning<'tcx>,
222+
codegen_units: &mut [CodegenUnit<'tcx>],
223+
mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
224+
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
213225
);
214226
}
215227

@@ -225,7 +237,7 @@ fn get_partitioner(tcx: TyCtxt<'_>) -> Partitioner {
225237
}
226238
}
227239

228-
pub fn partition<'tcx, I>(
240+
fn partition<'tcx, I>(
229241
tcx: TyCtxt<'tcx>,
230242
mono_items: &mut I,
231243
max_cgu_count: usize,
@@ -241,52 +253,59 @@ where
241253
// In the first step, we place all regular monomorphizations into their
242254
// respective 'home' codegen unit. Regular monomorphizations are all
243255
// functions and statics defined in the local crate.
244-
let mut initial_partitioning = {
256+
let PlacedRootMonoItems { mut codegen_units, roots, internalization_candidates } = {
245257
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_roots");
246258
partitioner.place_root_mono_items(cx, mono_items)
247259
};
248260

249-
for cgu in &mut initial_partitioning.codegen_units {
261+
for cgu in &mut codegen_units {
250262
cgu.create_size_estimate(tcx);
251263
}
252264

253-
debug_dump(tcx, "INITIAL PARTITIONING", &initial_partitioning.codegen_units);
265+
debug_dump(tcx, "INITIAL PARTITIONING", &codegen_units);
254266

255267
// Merge until we have at most `max_cgu_count` codegen units.
268+
// `merge_codegen_units` is responsible for updating the CGU size
269+
// estimates.
256270
{
257271
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_merge_cgus");
258-
partitioner.merge_codegen_units(cx, &mut initial_partitioning);
259-
debug_dump(tcx, "POST MERGING", &initial_partitioning.codegen_units);
272+
partitioner.merge_codegen_units(cx, &mut codegen_units);
273+
debug_dump(tcx, "POST MERGING", &codegen_units);
260274
}
261275

262276
// In the next step, we use the inlining map to determine which additional
263277
// monomorphizations have to go into each codegen unit. These additional
264278
// monomorphizations can be drop-glue, functions from external crates, and
265279
// local functions the definition of which is marked with `#[inline]`.
266-
let mut post_inlining = {
280+
let mono_item_placements = {
267281
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_place_inline_items");
268-
partitioner.place_inlined_mono_items(cx, initial_partitioning)
282+
partitioner.place_inlined_mono_items(cx, &mut codegen_units, roots)
269283
};
270284

271-
for cgu in &mut post_inlining.codegen_units {
285+
for cgu in &mut codegen_units {
272286
cgu.create_size_estimate(tcx);
273287
}
274288

275-
debug_dump(tcx, "POST INLINING", &post_inlining.codegen_units);
289+
debug_dump(tcx, "POST INLINING", &codegen_units);
276290

277291
// Next we try to make as many symbols "internal" as possible, so LLVM has
278292
// more freedom to optimize.
279293
if !tcx.sess.link_dead_code() {
280294
let _prof_timer = tcx.prof.generic_activity("cgu_partitioning_internalize_symbols");
281-
partitioner.internalize_symbols(cx, &mut post_inlining);
295+
partitioner.internalize_symbols(
296+
cx,
297+
&mut codegen_units,
298+
mono_item_placements,
299+
internalization_candidates,
300+
);
282301
}
283302

284303
let instrument_dead_code =
285304
tcx.sess.instrument_coverage() && !tcx.sess.instrument_coverage_except_unused_functions();
286305

287306
if instrument_dead_code {
288307
assert!(
289-
post_inlining.codegen_units.len() > 0,
308+
codegen_units.len() > 0,
290309
"There must be at least one CGU that code coverage data can be generated in."
291310
);
292311

@@ -297,7 +316,7 @@ where
297316
// the object file (CGU) containing the dead function stubs is included
298317
// in the final binary. This will probably require forcing these
299318
// function symbols to be included via `-u` or `/include` linker args.
300-
let mut cgus: Vec<_> = post_inlining.codegen_units.iter_mut().collect();
319+
let mut cgus: Vec<_> = codegen_units.iter_mut().collect();
301320
cgus.sort_by_key(|cgu| cgu.size_estimate());
302321

303322
let dead_code_cgu =
@@ -308,29 +327,17 @@ where
308327
} else {
309328
// If there are no CGUs that have externally linked items,
310329
// then we just pick the first CGU as a fallback.
311-
&mut post_inlining.codegen_units[0]
330+
&mut codegen_units[0]
312331
};
313332
dead_code_cgu.make_code_coverage_dead_code_cgu();
314333
}
315334

316335
// Finally, sort by codegen unit name, so that we get deterministic results.
317-
let PostInliningPartitioning {
318-
codegen_units: mut result,
319-
mono_item_placements: _,
320-
internalization_candidates: _,
321-
} = post_inlining;
336+
codegen_units.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
322337

323-
result.sort_by(|a, b| a.name().as_str().cmp(b.name().as_str()));
338+
debug_dump(tcx, "FINAL", &codegen_units);
324339

325-
debug_dump(tcx, "FINAL", &result);
326-
327-
result
328-
}
329-
330-
pub struct PreInliningPartitioning<'tcx> {
331-
codegen_units: Vec<CodegenUnit<'tcx>>,
332-
roots: FxHashSet<MonoItem<'tcx>>,
333-
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
340+
codegen_units
334341
}
335342

336343
/// For symbol internalization, we need to know whether a symbol/mono-item is
@@ -342,12 +349,6 @@ enum MonoItemPlacement {
342349
MultipleCgus,
343350
}
344351

345-
struct PostInliningPartitioning<'tcx> {
346-
codegen_units: Vec<CodegenUnit<'tcx>>,
347-
mono_item_placements: FxHashMap<MonoItem<'tcx>, MonoItemPlacement>,
348-
internalization_candidates: FxHashSet<MonoItem<'tcx>>,
349-
}
350-
351352
fn debug_dump<'a, 'tcx: 'a>(tcx: TyCtxt<'tcx>, label: &str, cgus: &[CodegenUnit<'tcx>]) {
352353
let dump = move || {
353354
use std::fmt::Write;

‎compiler/rustc_target/src/spec/aarch64_apple_ios_macabi.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::apple_base::{opts, Arch};
22
use crate::spec::{Cc, FramePointer, LinkerFlavor, Lld, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let llvm_target = "arm64-apple-ios-macabi";
5+
let llvm_target = "arm64-apple-ios14.0-macabi";
66

77
let arch = Arch::Arm64_macabi;
88
let mut base = opts("ios", arch);

‎compiler/rustc_target/src/spec/x86_64_apple_ios_macabi.rs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use super::apple_base::{opts, Arch};
22
use crate::spec::{Cc, LinkerFlavor, Lld, StackProbeType, Target, TargetOptions};
33

44
pub fn target() -> Target {
5-
let llvm_target = "x86_64-apple-ios-macabi";
5+
let llvm_target = "x86_64-apple-ios14.0-macabi";
66

77
let arch = Arch::X86_64_macabi;
88
let mut base = opts("ios", arch);

‎library/std/src/io/mod.rs‎

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,7 +593,8 @@ pub trait Read {
593593
/// This may happen for example because fewer bytes are actually available right now
594594
/// (e. g. being close to end-of-file) or because read() was interrupted by a signal.
595595
///
596-
/// As this trait is safe to implement, callers cannot rely on `n <= buf.len()` for safety.
596+
/// As this trait is safe to implement, callers in unsafe code cannot rely on
597+
/// `n <= buf.len()` for safety.
597598
/// Extra care needs to be taken when `unsafe` functions are used to access the read bytes.
598599
/// Callers have to ensure that no unchecked out-of-bounds accesses are possible even if
599600
/// `n > buf.len()`.
@@ -603,8 +604,8 @@ pub trait Read {
603604
/// contents of `buf` being true. It is recommended that *implementations*
604605
/// only write data to `buf` instead of reading its contents.
605606
///
606-
/// Correspondingly, however, *callers* of this method must not assume any guarantees
607-
/// about how the implementation uses `buf`. The trait is safe to implement,
607+
/// Correspondingly, however, *callers* of this method in unsafe code must not assume
608+
/// any guarantees about how the implementation uses `buf`. The trait is safe to implement,
608609
/// so it is possible that the code that's supposed to write to the buffer might also read
609610
/// from it. It is your responsibility to make sure that `buf` is initialized
610611
/// before calling `read`. Calling `read` with an uninitialized `buf` (of the kind one
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
trait Trait {}
2+
impl Trait for () {}
3+
4+
fn foo<T: Trait, U: Trait>() -> impl Trait {
5+
//~^ WARN function cannot return without recursing [unconditional_recursion]
6+
let a: T = foo::<T, U>();
7+
//~^ ERROR concrete type differs from previous defining opaque type use
8+
loop {}
9+
let _: T = foo::<U, T>();
10+
}
11+
12+
fn main() {}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
warning: function cannot return without recursing
2+
--> $DIR/multiple-defining-usages-in-body.rs:4:1
3+
|
4+
LL | fn foo<T: Trait, U: Trait>() -> impl Trait {
5+
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing
6+
LL |
7+
LL | let a: T = foo::<T, U>();
8+
| ------------- recursive call site
9+
|
10+
= help: a `loop` may express intention better if this is on purpose
11+
= note: `#[warn(unconditional_recursion)]` on by default
12+
13+
error: concrete type differs from previous defining opaque type use
14+
--> $DIR/multiple-defining-usages-in-body.rs:6:16
15+
|
16+
LL | let a: T = foo::<T, U>();
17+
| ^^^^^^^^^^^^^ expected `U`, got `T`
18+
|
19+
note: previous use here
20+
--> $DIR/multiple-defining-usages-in-body.rs:9:16
21+
|
22+
LL | let _: T = foo::<U, T>();
23+
| ^^^^^^^^^^^^^
24+
25+
error: aborting due to previous error; 1 warning emitted
26+

‎tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr‎

Lines changed: 56 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unreachable pattern
2-
--> $DIR/empty-match.rs:37:9
2+
--> $DIR/empty-match.rs:58:9
33
|
44
LL | _ => {},
55
| ^
@@ -11,37 +11,52 @@ LL | #![deny(unreachable_patterns)]
1111
| ^^^^^^^^^^^^^^^^^^^^
1212

1313
error: unreachable pattern
14-
--> $DIR/empty-match.rs:40:9
14+
--> $DIR/empty-match.rs:61:9
1515
|
1616
LL | _ if false => {},
1717
| ^
1818

1919
error: unreachable pattern
20-
--> $DIR/empty-match.rs:47:9
20+
--> $DIR/empty-match.rs:68:9
2121
|
2222
LL | _ => {},
2323
| ^
2424

2525
error: unreachable pattern
26-
--> $DIR/empty-match.rs:50:9
26+
--> $DIR/empty-match.rs:71:9
2727
|
2828
LL | _ if false => {},
2929
| ^
3030

31+
error[E0005]: refutable pattern in local binding
32+
--> $DIR/empty-match.rs:76:9
33+
|
34+
LL | let None = x;
35+
| ^^^^ pattern `Some(_)` not covered
36+
|
37+
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
38+
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
39+
= note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
40+
= note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
41+
help: you might want to use `if let` to ignore the variant that isn't matched
42+
|
43+
LL | if let None = x { todo!() };
44+
| ++ +++++++++++
45+
3146
error: unreachable pattern
32-
--> $DIR/empty-match.rs:57:9
47+
--> $DIR/empty-match.rs:88:9
3348
|
3449
LL | _ => {},
3550
| ^
3651

3752
error: unreachable pattern
38-
--> $DIR/empty-match.rs:60:9
53+
--> $DIR/empty-match.rs:91:9
3954
|
4055
LL | _ if false => {},
4156
| ^
4257

4358
error[E0004]: non-exhaustive patterns: type `u8` is non-empty
44-
--> $DIR/empty-match.rs:78:20
59+
--> $DIR/empty-match.rs:109:20
4560
|
4661
LL | match_no_arms!(0u8);
4762
| ^^^
@@ -50,69 +65,69 @@ LL | match_no_arms!(0u8);
5065
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
5166

5267
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
53-
--> $DIR/empty-match.rs:79:20
68+
--> $DIR/empty-match.rs:111:20
5469
|
5570
LL | match_no_arms!(NonEmptyStruct1);
5671
| ^^^^^^^^^^^^^^^
5772
|
5873
note: `NonEmptyStruct1` defined here
59-
--> $DIR/empty-match.rs:14:8
74+
--> $DIR/empty-match.rs:15:8
6075
|
6176
LL | struct NonEmptyStruct1;
6277
| ^^^^^^^^^^^^^^^
6378
= note: the matched value is of type `NonEmptyStruct1`
6479
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
6580

6681
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
67-
--> $DIR/empty-match.rs:80:20
82+
--> $DIR/empty-match.rs:113:20
6883
|
6984
LL | match_no_arms!(NonEmptyStruct2(true));
7085
| ^^^^^^^^^^^^^^^^^^^^^
7186
|
7287
note: `NonEmptyStruct2` defined here
73-
--> $DIR/empty-match.rs:15:8
88+
--> $DIR/empty-match.rs:18:8
7489
|
7590
LL | struct NonEmptyStruct2(bool);
7691
| ^^^^^^^^^^^^^^^
7792
= note: the matched value is of type `NonEmptyStruct2`
7893
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
7994

8095
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
81-
--> $DIR/empty-match.rs:81:20
96+
--> $DIR/empty-match.rs:115:20
8297
|
8398
LL | match_no_arms!((NonEmptyUnion1 { foo: () }));
8499
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
85100
|
86101
note: `NonEmptyUnion1` defined here
87-
--> $DIR/empty-match.rs:16:7
102+
--> $DIR/empty-match.rs:21:7
88103
|
89104
LL | union NonEmptyUnion1 {
90105
| ^^^^^^^^^^^^^^
91106
= note: the matched value is of type `NonEmptyUnion1`
92107
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
93108

94109
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
95-
--> $DIR/empty-match.rs:82:20
110+
--> $DIR/empty-match.rs:117:20
96111
|
97112
LL | match_no_arms!((NonEmptyUnion2 { foo: () }));
98113
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
99114
|
100115
note: `NonEmptyUnion2` defined here
101-
--> $DIR/empty-match.rs:19:7
116+
--> $DIR/empty-match.rs:26:7
102117
|
103118
LL | union NonEmptyUnion2 {
104119
| ^^^^^^^^^^^^^^
105120
= note: the matched value is of type `NonEmptyUnion2`
106121
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
107122

108123
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
109-
--> $DIR/empty-match.rs:83:20
124+
--> $DIR/empty-match.rs:119:20
110125
|
111126
LL | match_no_arms!(NonEmptyEnum1::Foo(true));
112127
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
113128
|
114129
note: `NonEmptyEnum1` defined here
115-
--> $DIR/empty-match.rs:24:5
130+
--> $DIR/empty-match.rs:33:5
116131
|
117132
LL | enum NonEmptyEnum1 {
118133
| -------------
@@ -122,39 +137,40 @@ LL | Foo(bool),
122137
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
123138

124139
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
125-
--> $DIR/empty-match.rs:84:20
140+
--> $DIR/empty-match.rs:122:20
126141
|
127142
LL | match_no_arms!(NonEmptyEnum2::Foo(true));
128143
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
129144
|
130145
note: `NonEmptyEnum2` defined here
131-
--> $DIR/empty-match.rs:27:5
146+
--> $DIR/empty-match.rs:40:5
132147
|
133148
LL | enum NonEmptyEnum2 {
134149
| -------------
135150
LL | Foo(bool),
136151
| ^^^ not covered
152+
...
137153
LL | Bar,
138154
| ^^^ not covered
139155
= note: the matched value is of type `NonEmptyEnum2`
140156
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
141157

142158
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
143-
--> $DIR/empty-match.rs:85:20
159+
--> $DIR/empty-match.rs:125:20
144160
|
145161
LL | match_no_arms!(NonEmptyEnum5::V1);
146162
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
147163
|
148164
note: `NonEmptyEnum5` defined here
149-
--> $DIR/empty-match.rs:30:6
165+
--> $DIR/empty-match.rs:49:6
150166
|
151167
LL | enum NonEmptyEnum5 {
152168
| ^^^^^^^^^^^^^
153169
= note: the matched value is of type `NonEmptyEnum5`
154170
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
155171

156172
error[E0004]: non-exhaustive patterns: `_` not covered
157-
--> $DIR/empty-match.rs:87:24
173+
--> $DIR/empty-match.rs:129:24
158174
|
159175
LL | match_guarded_arm!(0u8);
160176
| ^^^ pattern `_` not covered
@@ -167,13 +183,13 @@ LL + _ => todo!()
167183
|
168184

169185
error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
170-
--> $DIR/empty-match.rs:88:24
186+
--> $DIR/empty-match.rs:133:24
171187
|
172188
LL | match_guarded_arm!(NonEmptyStruct1);
173189
| ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
174190
|
175191
note: `NonEmptyStruct1` defined here
176-
--> $DIR/empty-match.rs:14:8
192+
--> $DIR/empty-match.rs:15:8
177193
|
178194
LL | struct NonEmptyStruct1;
179195
| ^^^^^^^^^^^^^^^
@@ -185,13 +201,13 @@ LL + NonEmptyStruct1 => todo!()
185201
|
186202

187203
error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
188-
--> $DIR/empty-match.rs:89:24
204+
--> $DIR/empty-match.rs:137:24
189205
|
190206
LL | match_guarded_arm!(NonEmptyStruct2(true));
191207
| ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
192208
|
193209
note: `NonEmptyStruct2` defined here
194-
--> $DIR/empty-match.rs:15:8
210+
--> $DIR/empty-match.rs:18:8
195211
|
196212
LL | struct NonEmptyStruct2(bool);
197213
| ^^^^^^^^^^^^^^^
@@ -203,13 +219,13 @@ LL + NonEmptyStruct2(_) => todo!()
203219
|
204220

205221
error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
206-
--> $DIR/empty-match.rs:90:24
222+
--> $DIR/empty-match.rs:141:24
207223
|
208224
LL | match_guarded_arm!((NonEmptyUnion1 { foo: () }));
209225
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
210226
|
211227
note: `NonEmptyUnion1` defined here
212-
--> $DIR/empty-match.rs:16:7
228+
--> $DIR/empty-match.rs:21:7
213229
|
214230
LL | union NonEmptyUnion1 {
215231
| ^^^^^^^^^^^^^^
@@ -221,13 +237,13 @@ LL + NonEmptyUnion1 { .. } => todo!()
221237
|
222238

223239
error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
224-
--> $DIR/empty-match.rs:91:24
240+
--> $DIR/empty-match.rs:145:24
225241
|
226242
LL | match_guarded_arm!((NonEmptyUnion2 { foo: () }));
227243
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
228244
|
229245
note: `NonEmptyUnion2` defined here
230-
--> $DIR/empty-match.rs:19:7
246+
--> $DIR/empty-match.rs:26:7
231247
|
232248
LL | union NonEmptyUnion2 {
233249
| ^^^^^^^^^^^^^^
@@ -239,13 +255,13 @@ LL + NonEmptyUnion2 { .. } => todo!()
239255
|
240256

241257
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
242-
--> $DIR/empty-match.rs:92:24
258+
--> $DIR/empty-match.rs:149:24
243259
|
244260
LL | match_guarded_arm!(NonEmptyEnum1::Foo(true));
245261
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
246262
|
247263
note: `NonEmptyEnum1` defined here
248-
--> $DIR/empty-match.rs:24:5
264+
--> $DIR/empty-match.rs:33:5
249265
|
250266
LL | enum NonEmptyEnum1 {
251267
| -------------
@@ -259,18 +275,19 @@ LL + NonEmptyEnum1::Foo(_) => todo!()
259275
|
260276

261277
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
262-
--> $DIR/empty-match.rs:93:24
278+
--> $DIR/empty-match.rs:153:24
263279
|
264280
LL | match_guarded_arm!(NonEmptyEnum2::Foo(true));
265281
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
266282
|
267283
note: `NonEmptyEnum2` defined here
268-
--> $DIR/empty-match.rs:27:5
284+
--> $DIR/empty-match.rs:40:5
269285
|
270286
LL | enum NonEmptyEnum2 {
271287
| -------------
272288
LL | Foo(bool),
273289
| ^^^ not covered
290+
...
274291
LL | Bar,
275292
| ^^^ not covered
276293
= note: the matched value is of type `NonEmptyEnum2`
@@ -281,13 +298,13 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
281298
|
282299

283300
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
284-
--> $DIR/empty-match.rs:94:24
301+
--> $DIR/empty-match.rs:157:24
285302
|
286303
LL | match_guarded_arm!(NonEmptyEnum5::V1);
287304
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
288305
|
289306
note: `NonEmptyEnum5` defined here
290-
--> $DIR/empty-match.rs:30:6
307+
--> $DIR/empty-match.rs:49:6
291308
|
292309
LL | enum NonEmptyEnum5 {
293310
| ^^^^^^^^^^^^^
@@ -298,6 +315,7 @@ LL ~ _ if false => {},
298315
LL + _ => todo!()
299316
|
300317

301-
error: aborting due to 22 previous errors
318+
error: aborting due to 23 previous errors
302319

303-
For more information about this error, try `rustc --explain E0004`.
320+
Some errors have detailed explanations: E0004, E0005.
321+
For more information about an error, try `rustc --explain E0004`.

‎tests/ui/pattern/usefulness/empty-match.normal.stderr‎

Lines changed: 55 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
error: unreachable pattern
2-
--> $DIR/empty-match.rs:37:9
2+
--> $DIR/empty-match.rs:58:9
33
|
44
LL | _ => {},
55
| ^
@@ -11,37 +11,51 @@ LL | #![deny(unreachable_patterns)]
1111
| ^^^^^^^^^^^^^^^^^^^^
1212

1313
error: unreachable pattern
14-
--> $DIR/empty-match.rs:40:9
14+
--> $DIR/empty-match.rs:61:9
1515
|
1616
LL | _ if false => {},
1717
| ^
1818

1919
error: unreachable pattern
20-
--> $DIR/empty-match.rs:47:9
20+
--> $DIR/empty-match.rs:68:9
2121
|
2222
LL | _ => {},
2323
| ^
2424

2525
error: unreachable pattern
26-
--> $DIR/empty-match.rs:50:9
26+
--> $DIR/empty-match.rs:71:9
2727
|
2828
LL | _ if false => {},
2929
| ^
3030

31+
error[E0005]: refutable pattern in local binding
32+
--> $DIR/empty-match.rs:76:9
33+
|
34+
LL | let None = x;
35+
| ^^^^ pattern `Some(_)` not covered
36+
|
37+
= note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
38+
= note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
39+
= note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
40+
help: you might want to use `if let` to ignore the variant that isn't matched
41+
|
42+
LL | if let None = x { todo!() };
43+
| ++ +++++++++++
44+
3145
error: unreachable pattern
32-
--> $DIR/empty-match.rs:57:9
46+
--> $DIR/empty-match.rs:88:9
3347
|
3448
LL | _ => {},
3549
| ^
3650

3751
error: unreachable pattern
38-
--> $DIR/empty-match.rs:60:9
52+
--> $DIR/empty-match.rs:91:9
3953
|
4054
LL | _ if false => {},
4155
| ^
4256

4357
error[E0004]: non-exhaustive patterns: type `u8` is non-empty
44-
--> $DIR/empty-match.rs:78:20
58+
--> $DIR/empty-match.rs:109:20
4559
|
4660
LL | match_no_arms!(0u8);
4761
| ^^^
@@ -50,69 +64,69 @@ LL | match_no_arms!(0u8);
5064
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
5165

5266
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
53-
--> $DIR/empty-match.rs:79:20
67+
--> $DIR/empty-match.rs:111:20
5468
|
5569
LL | match_no_arms!(NonEmptyStruct1);
5670
| ^^^^^^^^^^^^^^^
5771
|
5872
note: `NonEmptyStruct1` defined here
59-
--> $DIR/empty-match.rs:14:8
73+
--> $DIR/empty-match.rs:15:8
6074
|
6175
LL | struct NonEmptyStruct1;
6276
| ^^^^^^^^^^^^^^^
6377
= note: the matched value is of type `NonEmptyStruct1`
6478
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
6579

6680
error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
67-
--> $DIR/empty-match.rs:80:20
81+
--> $DIR/empty-match.rs:113:20
6882
|
6983
LL | match_no_arms!(NonEmptyStruct2(true));
7084
| ^^^^^^^^^^^^^^^^^^^^^
7185
|
7286
note: `NonEmptyStruct2` defined here
73-
--> $DIR/empty-match.rs:15:8
87+
--> $DIR/empty-match.rs:18:8
7488
|
7589
LL | struct NonEmptyStruct2(bool);
7690
| ^^^^^^^^^^^^^^^
7791
= note: the matched value is of type `NonEmptyStruct2`
7892
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
7993

8094
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
81-
--> $DIR/empty-match.rs:81:20
95+
--> $DIR/empty-match.rs:115:20
8296
|
8397
LL | match_no_arms!((NonEmptyUnion1 { foo: () }));
8498
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8599
|
86100
note: `NonEmptyUnion1` defined here
87-
--> $DIR/empty-match.rs:16:7
101+
--> $DIR/empty-match.rs:21:7
88102
|
89103
LL | union NonEmptyUnion1 {
90104
| ^^^^^^^^^^^^^^
91105
= note: the matched value is of type `NonEmptyUnion1`
92106
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
93107

94108
error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
95-
--> $DIR/empty-match.rs:82:20
109+
--> $DIR/empty-match.rs:117:20
96110
|
97111
LL | match_no_arms!((NonEmptyUnion2 { foo: () }));
98112
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
99113
|
100114
note: `NonEmptyUnion2` defined here
101-
--> $DIR/empty-match.rs:19:7
115+
--> $DIR/empty-match.rs:26:7
102116
|
103117
LL | union NonEmptyUnion2 {
104118
| ^^^^^^^^^^^^^^
105119
= note: the matched value is of type `NonEmptyUnion2`
106120
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
107121

108122
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
109-
--> $DIR/empty-match.rs:83:20
123+
--> $DIR/empty-match.rs:119:20
110124
|
111125
LL | match_no_arms!(NonEmptyEnum1::Foo(true));
112126
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
113127
|
114128
note: `NonEmptyEnum1` defined here
115-
--> $DIR/empty-match.rs:24:5
129+
--> $DIR/empty-match.rs:33:5
116130
|
117131
LL | enum NonEmptyEnum1 {
118132
| -------------
@@ -122,39 +136,40 @@ LL | Foo(bool),
122136
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
123137

124138
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
125-
--> $DIR/empty-match.rs:84:20
139+
--> $DIR/empty-match.rs:122:20
126140
|
127141
LL | match_no_arms!(NonEmptyEnum2::Foo(true));
128142
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
129143
|
130144
note: `NonEmptyEnum2` defined here
131-
--> $DIR/empty-match.rs:27:5
145+
--> $DIR/empty-match.rs:40:5
132146
|
133147
LL | enum NonEmptyEnum2 {
134148
| -------------
135149
LL | Foo(bool),
136150
| ^^^ not covered
151+
...
137152
LL | Bar,
138153
| ^^^ not covered
139154
= note: the matched value is of type `NonEmptyEnum2`
140155
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
141156

142157
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
143-
--> $DIR/empty-match.rs:85:20
158+
--> $DIR/empty-match.rs:125:20
144159
|
145160
LL | match_no_arms!(NonEmptyEnum5::V1);
146161
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
147162
|
148163
note: `NonEmptyEnum5` defined here
149-
--> $DIR/empty-match.rs:30:6
164+
--> $DIR/empty-match.rs:49:6
150165
|
151166
LL | enum NonEmptyEnum5 {
152167
| ^^^^^^^^^^^^^
153168
= note: the matched value is of type `NonEmptyEnum5`
154169
= help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
155170

156171
error[E0004]: non-exhaustive patterns: `_` not covered
157-
--> $DIR/empty-match.rs:87:24
172+
--> $DIR/empty-match.rs:129:24
158173
|
159174
LL | match_guarded_arm!(0u8);
160175
| ^^^ pattern `_` not covered
@@ -167,13 +182,13 @@ LL + _ => todo!()
167182
|
168183

169184
error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
170-
--> $DIR/empty-match.rs:88:24
185+
--> $DIR/empty-match.rs:133:24
171186
|
172187
LL | match_guarded_arm!(NonEmptyStruct1);
173188
| ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
174189
|
175190
note: `NonEmptyStruct1` defined here
176-
--> $DIR/empty-match.rs:14:8
191+
--> $DIR/empty-match.rs:15:8
177192
|
178193
LL | struct NonEmptyStruct1;
179194
| ^^^^^^^^^^^^^^^
@@ -185,13 +200,13 @@ LL + NonEmptyStruct1 => todo!()
185200
|
186201

187202
error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
188-
--> $DIR/empty-match.rs:89:24
203+
--> $DIR/empty-match.rs:137:24
189204
|
190205
LL | match_guarded_arm!(NonEmptyStruct2(true));
191206
| ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
192207
|
193208
note: `NonEmptyStruct2` defined here
194-
--> $DIR/empty-match.rs:15:8
209+
--> $DIR/empty-match.rs:18:8
195210
|
196211
LL | struct NonEmptyStruct2(bool);
197212
| ^^^^^^^^^^^^^^^
@@ -203,13 +218,13 @@ LL + NonEmptyStruct2(_) => todo!()
203218
|
204219

205220
error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
206-
--> $DIR/empty-match.rs:90:24
221+
--> $DIR/empty-match.rs:141:24
207222
|
208223
LL | match_guarded_arm!((NonEmptyUnion1 { foo: () }));
209224
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
210225
|
211226
note: `NonEmptyUnion1` defined here
212-
--> $DIR/empty-match.rs:16:7
227+
--> $DIR/empty-match.rs:21:7
213228
|
214229
LL | union NonEmptyUnion1 {
215230
| ^^^^^^^^^^^^^^
@@ -221,13 +236,13 @@ LL + NonEmptyUnion1 { .. } => todo!()
221236
|
222237

223238
error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
224-
--> $DIR/empty-match.rs:91:24
239+
--> $DIR/empty-match.rs:145:24
225240
|
226241
LL | match_guarded_arm!((NonEmptyUnion2 { foo: () }));
227242
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
228243
|
229244
note: `NonEmptyUnion2` defined here
230-
--> $DIR/empty-match.rs:19:7
245+
--> $DIR/empty-match.rs:26:7
231246
|
232247
LL | union NonEmptyUnion2 {
233248
| ^^^^^^^^^^^^^^
@@ -239,13 +254,13 @@ LL + NonEmptyUnion2 { .. } => todo!()
239254
|
240255

241256
error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
242-
--> $DIR/empty-match.rs:92:24
257+
--> $DIR/empty-match.rs:149:24
243258
|
244259
LL | match_guarded_arm!(NonEmptyEnum1::Foo(true));
245260
| ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
246261
|
247262
note: `NonEmptyEnum1` defined here
248-
--> $DIR/empty-match.rs:24:5
263+
--> $DIR/empty-match.rs:33:5
249264
|
250265
LL | enum NonEmptyEnum1 {
251266
| -------------
@@ -259,18 +274,19 @@ LL + NonEmptyEnum1::Foo(_) => todo!()
259274
|
260275

261276
error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
262-
--> $DIR/empty-match.rs:93:24
277+
--> $DIR/empty-match.rs:153:24
263278
|
264279
LL | match_guarded_arm!(NonEmptyEnum2::Foo(true));
265280
| ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
266281
|
267282
note: `NonEmptyEnum2` defined here
268-
--> $DIR/empty-match.rs:27:5
283+
--> $DIR/empty-match.rs:40:5
269284
|
270285
LL | enum NonEmptyEnum2 {
271286
| -------------
272287
LL | Foo(bool),
273288
| ^^^ not covered
289+
...
274290
LL | Bar,
275291
| ^^^ not covered
276292
= note: the matched value is of type `NonEmptyEnum2`
@@ -281,13 +297,13 @@ LL + NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
281297
|
282298

283299
error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
284-
--> $DIR/empty-match.rs:94:24
300+
--> $DIR/empty-match.rs:157:24
285301
|
286302
LL | match_guarded_arm!(NonEmptyEnum5::V1);
287303
| ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
288304
|
289305
note: `NonEmptyEnum5` defined here
290-
--> $DIR/empty-match.rs:30:6
306+
--> $DIR/empty-match.rs:49:6
291307
|
292308
LL | enum NonEmptyEnum5 {
293309
| ^^^^^^^^^^^^^
@@ -298,6 +314,7 @@ LL ~ _ if false => {},
298314
LL + _ => todo!()
299315
|
300316

301-
error: aborting due to 22 previous errors
317+
error: aborting due to 23 previous errors
302318

303-
For more information about this error, try `rustc --explain E0004`.
319+
Some errors have detailed explanations: E0004, E0005.
320+
For more information about an error, try `rustc --explain E0004`.

‎tests/ui/pattern/usefulness/empty-match.rs‎

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,28 +6,49 @@
66
#![feature(never_type_fallback)]
77
#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
88
#![deny(unreachable_patterns)]
9+
//~^ NOTE the lint level is defined here
910

1011
extern crate empty;
1112

1213
enum EmptyEnum {}
1314

1415
struct NonEmptyStruct1;
16+
//~^ NOTE `NonEmptyStruct1` defined here
17+
//~| NOTE `NonEmptyStruct1` defined here
1518
struct NonEmptyStruct2(bool);
19+
//~^ NOTE `NonEmptyStruct2` defined here
20+
//~| NOTE `NonEmptyStruct2` defined here
1621
union NonEmptyUnion1 {
22+
//~^ NOTE `NonEmptyUnion1` defined here
23+
//~| NOTE `NonEmptyUnion1` defined here
1724
foo: (),
1825
}
1926
union NonEmptyUnion2 {
27+
//~^ NOTE `NonEmptyUnion2` defined here
28+
//~| NOTE `NonEmptyUnion2` defined here
2029
foo: (),
2130
bar: (),
2231
}
2332
enum NonEmptyEnum1 {
2433
Foo(bool),
34+
//~^ NOTE `NonEmptyEnum1` defined here
35+
//~| NOTE `NonEmptyEnum1` defined here
36+
//~| NOTE not covered
37+
//~| NOTE not covered
2538
}
2639
enum NonEmptyEnum2 {
2740
Foo(bool),
41+
//~^ NOTE `NonEmptyEnum2` defined here
42+
//~| NOTE `NonEmptyEnum2` defined here
43+
//~| NOTE not covered
44+
//~| NOTE not covered
2845
Bar,
46+
//~^ NOTE not covered
47+
//~| NOTE not covered
2948
}
3049
enum NonEmptyEnum5 {
50+
//~^ NOTE `NonEmptyEnum5` defined here
51+
//~| NOTE `NonEmptyEnum5` defined here
3152
V1, V2, V3, V4, V5,
3253
}
3354

@@ -51,6 +72,16 @@ fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
5172
}
5273
}
5374

75+
fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) {
76+
let None = x;
77+
//~^ ERROR refutable pattern in local binding
78+
//~| NOTE `let` bindings require an "irrefutable pattern"
79+
//~| NOTE for more information, visit
80+
//~| NOTE the matched value is of type
81+
//~| NOTE pattern `Some(_)` not covered
82+
//[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields
83+
}
84+
5485
fn never(x: !) {
5586
match x {} // ok
5687
match x {
@@ -76,20 +107,55 @@ macro_rules! match_guarded_arm {
76107

77108
fn main() {
78109
match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
110+
//~| NOTE the matched value is of type
79111
match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty
112+
//~| NOTE the matched value is of type
80113
match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty
114+
//~| NOTE the matched value is of type
81115
match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty
116+
//~| NOTE the matched value is of type
82117
match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty
118+
//~| NOTE the matched value is of type
83119
match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
120+
//~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
121+
//~| NOTE the matched value is of type
84122
match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
123+
//~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
124+
//~| NOTE the matched value is of type
85125
match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
126+
//~| NOTE patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`
127+
//~| NOTE the matched value is of type
86128

87129
match_guarded_arm!(0u8); //~ ERROR `_` not covered
130+
//~| NOTE the matched value is of type
131+
//~| NOTE pattern `_` not covered
132+
//~| NOTE in this expansion of match_guarded_arm!
88133
match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered
134+
//~| NOTE pattern `NonEmptyStruct1` not covered
135+
//~| NOTE the matched value is of type
136+
//~| NOTE in this expansion of match_guarded_arm!
89137
match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered
138+
//~| NOTE the matched value is of type
139+
//~| NOTE pattern `NonEmptyStruct2(_)` not covered
140+
//~| NOTE in this expansion of match_guarded_arm!
90141
match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered
142+
//~| NOTE the matched value is of type
143+
//~| NOTE pattern `NonEmptyUnion1 { .. }` not covered
144+
//~| NOTE in this expansion of match_guarded_arm!
91145
match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered
146+
//~| NOTE the matched value is of type
147+
//~| NOTE pattern `NonEmptyUnion2 { .. }` not covered
148+
//~| NOTE in this expansion of match_guarded_arm!
92149
match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
150+
//~| NOTE the matched value is of type
151+
//~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
152+
//~| NOTE in this expansion of match_guarded_arm!
93153
match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
154+
//~| NOTE the matched value is of type
155+
//~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
156+
//~| NOTE in this expansion of match_guarded_arm!
94157
match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
158+
//~| NOTE the matched value is of type
159+
//~| NOTE patterns `NonEmptyEnum5::V1`,
160+
//~| NOTE in this expansion of match_guarded_arm!
95161
}

0 commit comments

Comments
 (0)
Please sign in to comment.