Skip to content

Commit 6581dbf

Browse files
committed
Auto merge of rust-lang#120136 - matthiaskrgr:rollup-3zzb0z9, r=matthiaskrgr
Rollup of 9 pull requests Successful merges: - rust-lang#117561 (Stabilize `slice_first_last_chunk`) - rust-lang#117662 ([rustdoc] Allows links in headings) - rust-lang#119815 (Format sources into the error message when loading codegen backends) - rust-lang#119835 (Exhaustiveness: simplify empty pattern logic) - rust-lang#119984 (Change return type of unstable `Waker::noop()` from `Waker` to `&Waker`.) - rust-lang#120009 (never_patterns: typecheck never patterns) - rust-lang#120122 (Don't add needs-triage to A-diagnostics) - rust-lang#120126 (Suggest `.swap()` when encountering conflicting borrows from `mem::swap` on a slice) - rust-lang#120134 (Restrict access to the private field of newtype indexes) Failed merges: - rust-lang#119968 (Remove unused/unnecessary features) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 88189a7 + ee12697 commit 6581dbf

File tree

64 files changed

+745
-593
lines changed

Some content is hidden

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

64 files changed

+745
-593
lines changed

Cargo.lock

+3-13
Original file line numberDiff line numberDiff line change
@@ -2187,16 +2187,6 @@ dependencies = [
21872187
"cc",
21882188
]
21892189

2190-
[[package]]
2191-
name = "libloading"
2192-
version = "0.7.4"
2193-
source = "registry+https://github.com/rust-lang/crates.io-index"
2194-
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
2195-
dependencies = [
2196-
"cfg-if",
2197-
"winapi",
2198-
]
2199-
22002190
[[package]]
22012191
name = "libloading"
22022192
version = "0.8.1"
@@ -2479,7 +2469,7 @@ dependencies = [
24792469
"lazy_static",
24802470
"libc",
24812471
"libffi",
2482-
"libloading 0.8.1",
2472+
"libloading",
24832473
"log",
24842474
"measureme",
24852475
"rand",
@@ -4005,7 +3995,7 @@ dependencies = [
40053995
name = "rustc_interface"
40063996
version = "0.0.0"
40073997
dependencies = [
4008-
"libloading 0.7.4",
3998+
"libloading",
40093999
"rustc-rayon",
40104000
"rustc-rayon-core",
40114001
"rustc_ast",
@@ -4135,7 +4125,7 @@ name = "rustc_metadata"
41354125
version = "0.0.0"
41364126
dependencies = [
41374127
"bitflags 2.4.1",
4138-
"libloading 0.7.4",
4128+
"libloading",
41394129
"odht",
41404130
"rustc_ast",
41414131
"rustc_attr",

compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs

+90-7
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use rustc_span::hygiene::DesugaringKind;
2626
use rustc_span::symbol::{kw, sym, Ident};
2727
use rustc_span::{BytePos, Span, Symbol};
2828
use rustc_trait_selection::infer::InferCtxtExt;
29+
use rustc_trait_selection::traits::error_reporting::FindExprBySpan;
2930
use rustc_trait_selection::traits::ObligationCtxt;
3031
use std::iter;
3132

@@ -1304,14 +1305,96 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
13041305
place: Place<'tcx>,
13051306
borrowed_place: Place<'tcx>,
13061307
) {
1307-
if let ([ProjectionElem::Index(_)], [ProjectionElem::Index(_)]) =
1308-
(&place.projection[..], &borrowed_place.projection[..])
1308+
let tcx = self.infcx.tcx;
1309+
let hir = tcx.hir();
1310+
1311+
if let ([ProjectionElem::Index(index1)], [ProjectionElem::Index(index2)])
1312+
| (
1313+
[ProjectionElem::Deref, ProjectionElem::Index(index1)],
1314+
[ProjectionElem::Deref, ProjectionElem::Index(index2)],
1315+
) = (&place.projection[..], &borrowed_place.projection[..])
13091316
{
1310-
err.help(
1311-
"consider using `.split_at_mut(position)` or similar method to obtain \
1312-
two mutable non-overlapping sub-slices",
1313-
)
1314-
.help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
1317+
let mut note_default_suggestion = || {
1318+
err.help(
1319+
"consider using `.split_at_mut(position)` or similar method to obtain \
1320+
two mutable non-overlapping sub-slices",
1321+
)
1322+
.help("consider using `.swap(index_1, index_2)` to swap elements at the specified indices");
1323+
};
1324+
1325+
let Some(body_id) = tcx.hir_node(self.mir_hir_id()).body_id() else {
1326+
note_default_suggestion();
1327+
return;
1328+
};
1329+
1330+
let mut expr_finder =
1331+
FindExprBySpan::new(self.body.local_decls[*index1].source_info.span);
1332+
expr_finder.visit_expr(hir.body(body_id).value);
1333+
let Some(index1) = expr_finder.result else {
1334+
note_default_suggestion();
1335+
return;
1336+
};
1337+
1338+
expr_finder = FindExprBySpan::new(self.body.local_decls[*index2].source_info.span);
1339+
expr_finder.visit_expr(hir.body(body_id).value);
1340+
let Some(index2) = expr_finder.result else {
1341+
note_default_suggestion();
1342+
return;
1343+
};
1344+
1345+
let sm = tcx.sess.source_map();
1346+
1347+
let Ok(index1_str) = sm.span_to_snippet(index1.span) else {
1348+
note_default_suggestion();
1349+
return;
1350+
};
1351+
1352+
let Ok(index2_str) = sm.span_to_snippet(index2.span) else {
1353+
note_default_suggestion();
1354+
return;
1355+
};
1356+
1357+
let Some(object) = hir.parent_id_iter(index1.hir_id).find_map(|id| {
1358+
if let hir::Node::Expr(expr) = tcx.hir_node(id)
1359+
&& let hir::ExprKind::Index(obj, ..) = expr.kind
1360+
{
1361+
Some(obj)
1362+
} else {
1363+
None
1364+
}
1365+
}) else {
1366+
note_default_suggestion();
1367+
return;
1368+
};
1369+
1370+
let Ok(obj_str) = sm.span_to_snippet(object.span) else {
1371+
note_default_suggestion();
1372+
return;
1373+
};
1374+
1375+
let Some(swap_call) = hir.parent_id_iter(object.hir_id).find_map(|id| {
1376+
if let hir::Node::Expr(call) = tcx.hir_node(id)
1377+
&& let hir::ExprKind::Call(callee, ..) = call.kind
1378+
&& let hir::ExprKind::Path(qpath) = callee.kind
1379+
&& let hir::QPath::Resolved(None, res) = qpath
1380+
&& let hir::def::Res::Def(_, did) = res.res
1381+
&& tcx.is_diagnostic_item(sym::mem_swap, did)
1382+
{
1383+
Some(call)
1384+
} else {
1385+
None
1386+
}
1387+
}) else {
1388+
note_default_suggestion();
1389+
return;
1390+
};
1391+
1392+
err.span_suggestion(
1393+
swap_call.span,
1394+
"use `.swap()` to swap elements at the specified indices instead",
1395+
format!("{obj_str}.swap({index1_str}, {index2_str})"),
1396+
Applicability::MachineApplicable,
1397+
);
13151398
}
13161399
}
13171400

compiler/rustc_codegen_cranelift/Cargo.lock

+3-3
Original file line numberDiff line numberDiff line change
@@ -246,12 +246,12 @@ checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b"
246246

247247
[[package]]
248248
name = "libloading"
249-
version = "0.7.4"
249+
version = "0.8.1"
250250
source = "registry+https://github.com/rust-lang/crates.io-index"
251-
checksum = "b67380fd3b2fbe7527a606e18729d21c6f3951633d0500574c4dc22d2d638b9f"
251+
checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
252252
dependencies = [
253253
"cfg-if",
254-
"winapi",
254+
"windows-sys",
255255
]
256256

257257
[[package]]

compiler/rustc_codegen_cranelift/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ gimli = { version = "0.28", default-features = false, features = ["write"]}
1919
object = { version = "0.32", default-features = false, features = ["std", "read_core", "write", "archive", "coff", "elf", "macho", "pe"] }
2020

2121
indexmap = "2.0.0"
22-
libloading = { version = "0.7.3", optional = true }
22+
libloading = { version = "0.8.0", optional = true }
2323
smallvec = "1.8.1"
2424

2525
[patch.crates-io]

compiler/rustc_hir_typeck/src/pat.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -178,8 +178,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
178178

179179
let ty = match pat.kind {
180180
PatKind::Wild | PatKind::Err(_) => expected,
181-
// FIXME(never_patterns): check the type is uninhabited. If that is not possible within
182-
// typeck, do that in a later phase.
181+
// We allow any type here; we ensure that the type is uninhabited during match checking.
183182
PatKind::Never => expected,
184183
PatKind::Lit(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
185184
PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),

compiler/rustc_index_macros/src/newtype.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl Parse for Newtype {
104104
#gate_rustc_only
105105
impl<E: ::rustc_serialize::Encoder> ::rustc_serialize::Encodable<E> for #name {
106106
fn encode(&self, e: &mut E) {
107-
e.emit_u32(self.private);
107+
e.emit_u32(self.as_u32());
108108
}
109109
}
110110
}
@@ -164,7 +164,7 @@ impl Parse for Newtype {
164164
#[inline]
165165
fn eq(l: &Option<Self>, r: &Option<Self>) -> bool {
166166
if #max_val < u32::MAX {
167-
l.map(|i| i.private).unwrap_or(#max_val+1) == r.map(|i| i.private).unwrap_or(#max_val+1)
167+
l.map(|i| i.as_u32()).unwrap_or(#max_val+1) == r.map(|i| i.as_u32()).unwrap_or(#max_val+1)
168168
} else {
169169
match (l, r) {
170170
(Some(l), Some(r)) => r == l,
@@ -188,7 +188,7 @@ impl Parse for Newtype {
188188
#[cfg_attr(#gate_rustc_only_cfg, rustc_layout_scalar_valid_range_end(#max))]
189189
#[cfg_attr(#gate_rustc_only_cfg, rustc_pass_by_value)]
190190
#vis struct #name {
191-
private: u32,
191+
private_use_as_methods_instead: u32,
192192
}
193193

194194
#(#consts)*
@@ -238,7 +238,7 @@ impl Parse for Newtype {
238238
/// Prefer using `from_u32`.
239239
#[inline]
240240
#vis const unsafe fn from_u32_unchecked(value: u32) -> Self {
241-
Self { private: value }
241+
Self { private_use_as_methods_instead: value }
242242
}
243243

244244
/// Extracts the value of this index as a `usize`.
@@ -250,7 +250,7 @@ impl Parse for Newtype {
250250
/// Extracts the value of this index as a `u32`.
251251
#[inline]
252252
#vis const fn as_u32(self) -> u32 {
253-
self.private
253+
self.private_use_as_methods_instead
254254
}
255255

256256
/// Extracts the value of this index as a `usize`.

compiler/rustc_interface/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ edition = "2021"
55

66
[dependencies]
77
# tidy-alphabetical-start
8-
libloading = "0.7.1"
8+
libloading = "0.8.0"
99
rustc-rayon = { version = "0.5.0", optional = true }
1010
rustc-rayon-core = { version = "0.5.0", optional = true }
1111
rustc_ast = { path = "../rustc_ast" }

compiler/rustc_interface/src/lib.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
#![feature(box_patterns)]
22
#![feature(decl_macro)]
3+
#![feature(error_iter)]
34
#![feature(internal_output_capture)]
4-
#![feature(thread_spawn_unchecked)]
55
#![feature(lazy_cell)]
66
#![feature(let_chains)]
7+
#![feature(thread_spawn_unchecked)]
78
#![feature(try_blocks)]
89
#![recursion_limit = "256"]
910
#![deny(rustc::untranslatable_diagnostic)]

compiler/rustc_interface/src/util.rs

+9-3
Original file line numberDiff line numberDiff line change
@@ -162,15 +162,21 @@ pub(crate) fn run_in_thread_pool_with_globals<F: FnOnce() -> R + Send, R: Send>(
162162
}
163163

164164
fn load_backend_from_dylib(early_dcx: &EarlyDiagCtxt, path: &Path) -> MakeBackendFn {
165+
fn format_err(e: &(dyn std::error::Error + 'static)) -> String {
166+
e.sources().map(|e| format!(": {e}")).collect()
167+
}
165168
let lib = unsafe { Library::new(path) }.unwrap_or_else(|err| {
166-
let err = format!("couldn't load codegen backend {path:?}: {err}");
169+
let err = format!("couldn't load codegen backend {path:?}{}", format_err(&err));
167170
early_dcx.early_fatal(err);
168171
});
169172

170173
let backend_sym = unsafe { lib.get::<MakeBackendFn>(b"__rustc_codegen_backend") }
171174
.unwrap_or_else(|e| {
172-
let err = format!("couldn't load codegen backend: {e}");
173-
early_dcx.early_fatal(err);
175+
let e = format!(
176+
"`__rustc_codegen_backend` symbol lookup in the codegen backend failed{}",
177+
format_err(&e)
178+
);
179+
early_dcx.early_fatal(e);
174180
});
175181

176182
// Intentionally leak the dynamic library. We can't ever unload it

compiler/rustc_metadata/Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ edition = "2021"
66
[dependencies]
77
# tidy-alphabetical-start
88
bitflags = "2.4.1"
9-
libloading = "0.7.1"
9+
libloading = "0.8.0"
1010
odht = { version = "0.3.1", features = ["nightly"] }
1111
rustc_ast = { path = "../rustc_ast" }
1212
rustc_attr = { path = "../rustc_attr" }

compiler/rustc_mir_build/messages.ftl

+5
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,11 @@ mir_build_mutation_of_layout_constrained_field_requires_unsafe_unsafe_op_in_unsa
234234
235235
mir_build_non_const_path = runtime values cannot be referenced in patterns
236236
237+
mir_build_non_empty_never_pattern =
238+
mismatched types
239+
.label = a never pattern must be used on an uninhabited type
240+
.note = the matched value is of type `{$ty}`
241+
237242
mir_build_non_exhaustive_match_all_arms_guarded =
238243
match arms with guards don't count towards exhaustivity
239244

compiler/rustc_mir_build/src/errors.rs

+10
Original file line numberDiff line numberDiff line change
@@ -788,6 +788,16 @@ pub struct FloatPattern;
788788
#[diag(mir_build_pointer_pattern)]
789789
pub struct PointerPattern;
790790

791+
#[derive(Diagnostic)]
792+
#[diag(mir_build_non_empty_never_pattern)]
793+
#[note]
794+
pub struct NonEmptyNeverPattern<'tcx> {
795+
#[primary_span]
796+
#[label]
797+
pub span: Span,
798+
pub ty: Ty<'tcx>,
799+
}
800+
791801
#[derive(LintDiagnostic)]
792802
#[diag(mir_build_indirect_structural_match)]
793803
#[note(mir_build_type_not_structural_tip)]

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

+18-1
Original file line numberDiff line numberDiff line change
@@ -276,10 +276,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
276276
} else {
277277
// Check the pattern for some things unrelated to exhaustiveness.
278278
let refutable = if cx.refutable { Refutable } else { Irrefutable };
279+
let mut err = Ok(());
279280
pat.walk_always(|pat| {
280281
check_borrow_conflicts_in_at_patterns(self, pat);
281282
check_for_bindings_named_same_as_variants(self, pat, refutable);
283+
err = err.and(check_never_pattern(cx, pat));
282284
});
285+
err?;
283286
Ok(cx.pattern_arena.alloc(cx.lower_pat(pat)))
284287
}
285288
}
@@ -289,7 +292,8 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> {
289292
fn is_known_valid_scrutinee(&self, scrutinee: &Expr<'tcx>) -> bool {
290293
use ExprKind::*;
291294
match &scrutinee.kind {
292-
// Both pointers and references can validly point to a place with invalid data.
295+
// Pointers can validly point to a place with invalid data. It is undecided whether
296+
// references can too, so we conservatively assume they can.
293297
Deref { .. } => false,
294298
// Inherit validity of the parent place, unless the parent is an union.
295299
Field { lhs, .. } => {
@@ -811,6 +815,19 @@ fn check_for_bindings_named_same_as_variants(
811815
}
812816
}
813817

818+
/// Check that never patterns are only used on inhabited types.
819+
fn check_never_pattern<'tcx>(
820+
cx: &MatchCheckCtxt<'_, 'tcx>,
821+
pat: &Pat<'tcx>,
822+
) -> Result<(), ErrorGuaranteed> {
823+
if let PatKind::Never = pat.kind {
824+
if !cx.is_uninhabited(pat.ty) {
825+
return Err(cx.tcx.dcx().emit_err(NonEmptyNeverPattern { span: pat.span, ty: pat.ty }));
826+
}
827+
}
828+
Ok(())
829+
}
830+
814831
fn report_irrefutable_let_patterns(
815832
tcx: TyCtxt<'_>,
816833
id: HirId,

compiler/rustc_pattern_analysis/src/constructor.rs

+5-14
Original file line numberDiff line numberDiff line change
@@ -861,12 +861,14 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
861861
/// any) are missing; 2/ split constructors to handle non-trivial intersections e.g. on ranges
862862
/// or slices. This can get subtle; see [`SplitConstructorSet`] for details of this operation
863863
/// and its invariants.
864-
#[instrument(level = "debug", skip(self, pcx, ctors), ret)]
864+
#[instrument(level = "debug", skip(self, ctors), ret)]
865865
pub(crate) fn split<'a>(
866866
&self,
867-
pcx: &PlaceCtxt<'a, Cx>,
868867
ctors: impl Iterator<Item = &'a Constructor<Cx>> + Clone,
869-
) -> SplitConstructorSet<Cx> {
868+
) -> SplitConstructorSet<Cx>
869+
where
870+
Cx: 'a,
871+
{
870872
let mut present: SmallVec<[_; 1]> = SmallVec::new();
871873
// Empty constructors found missing.
872874
let mut missing_empty = Vec::new();
@@ -1006,17 +1008,6 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
10061008
}
10071009
}
10081010

1009-
// We have now grouped all the constructors into 3 buckets: present, missing, missing_empty.
1010-
// In the absence of the `exhaustive_patterns` feature however, we don't count nested empty
1011-
// types as empty. Only non-nested `!` or `enum Foo {}` are considered empty.
1012-
if !pcx.mcx.tycx.is_exhaustive_patterns_feature_on()
1013-
&& !(pcx.is_scrutinee && matches!(self, Self::NoConstructors))
1014-
{
1015-
// Treat all missing constructors as nonempty.
1016-
// This clears `missing_empty`.
1017-
missing.append(&mut missing_empty);
1018-
}
1019-
10201011
SplitConstructorSet { present, missing, missing_empty }
10211012
}
10221013
}

0 commit comments

Comments
 (0)