Skip to content

Commit 86853ee

Browse files
committed
Auto merge of rust-lang#130569 - cuviper:beta-next, r=cuviper
[beta] backports - Don't warn empty branches unreachable for now rust-lang#129103 - Win: Add dbghelp to the list of import libraries rust-lang#130047 - `RepeatN`: use MaybeUninit rust-lang#130145 - Update LLVM to 19 327ca6c rust-lang#130212 - Revert rust-lang#129749 to fix segfault in LLVM rust-lang#130477 - Check params for unsafety in THIR rust-lang#130531 r? cuviper
2 parents 4976ae4 + 49891df commit 86853ee

25 files changed

+212
-470
lines changed

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

+3-7
Original file line numberDiff line numberDiff line change
@@ -1212,11 +1212,7 @@ struct LLVMRustThinLTOData {
12121212
// Not 100% sure what these are, but they impact what's internalized and
12131213
// what's inlined across modules, I believe.
12141214
#if LLVM_VERSION_GE(18, 0)
1215-
#if LLVM_VERSION_GE(20, 0)
1216-
FunctionImporter::ImportListsTy ImportLists;
1217-
#else
12181215
DenseMap<StringRef, FunctionImporter::ImportMapTy> ImportLists;
1219-
#endif
12201216
DenseMap<StringRef, FunctionImporter::ExportSetTy> ExportLists;
12211217
DenseMap<StringRef, GVSummaryMapTy> ModuleToDefinedGVSummaries;
12221218
#else
@@ -1425,13 +1421,13 @@ LLVMRustPrepareThinLTOInternalize(const LLVMRustThinLTOData *Data,
14251421
return true;
14261422
}
14271423

1428-
extern "C" bool LLVMRustPrepareThinLTOImport(LLVMRustThinLTOData *Data,
1424+
extern "C" bool LLVMRustPrepareThinLTOImport(const LLVMRustThinLTOData *Data,
14291425
LLVMModuleRef M,
14301426
LLVMTargetMachineRef TM) {
14311427
Module &Mod = *unwrap(M);
14321428
TargetMachine &Target = *unwrap(TM);
14331429

1434-
const auto &ImportList = Data->ImportLists[Mod.getModuleIdentifier()];
1430+
const auto &ImportList = Data->ImportLists.lookup(Mod.getModuleIdentifier());
14351431
auto Loader = [&](StringRef Identifier) {
14361432
const auto &Memory = Data->ModuleMap.lookup(Identifier);
14371433
auto &Context = Mod.getContext();
@@ -1614,7 +1610,7 @@ extern "C" void LLVMRustComputeLTOCacheKey(RustStringRef KeyOut,
16141610
LLVMRustThinLTOData *Data) {
16151611
SmallString<40> Key;
16161612
llvm::lto::Config conf;
1617-
const auto &ImportList = Data->ImportLists[ModId];
1613+
const auto &ImportList = Data->ImportLists.lookup(ModId);
16181614
const auto &ExportList = Data->ExportLists.lookup(ModId);
16191615
const auto &ResolvedODR = Data->ResolvedODR.lookup(ModId);
16201616
const auto &DefinedGlobals = Data->ModuleToDefinedGVSummaries.lookup(ModId);

compiler/rustc_mir_build/src/check_unsafety.rs

+14
Original file line numberDiff line numberDiff line change
@@ -218,6 +218,13 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
218218
warnings: self.warnings,
219219
suggest_unsafe_block: self.suggest_unsafe_block,
220220
};
221+
// params in THIR may be unsafe, e.g. a union pattern.
222+
for param in &inner_thir.params {
223+
if let Some(param_pat) = param.pat.as_deref() {
224+
inner_visitor.visit_pat(param_pat);
225+
}
226+
}
227+
// Visit the body.
221228
inner_visitor.visit_expr(&inner_thir[expr]);
222229
// Unsafe blocks can be used in the inner body, make sure to take it into account
223230
self.safety_context = inner_visitor.safety_context;
@@ -1066,6 +1073,13 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) {
10661073
warnings: &mut warnings,
10671074
suggest_unsafe_block: true,
10681075
};
1076+
// params in THIR may be unsafe, e.g. a union pattern.
1077+
for param in &thir.params {
1078+
if let Some(param_pat) = param.pat.as_deref() {
1079+
visitor.visit_pat(param_pat);
1080+
}
1081+
}
1082+
// Visit the body.
10691083
visitor.visit_expr(&thir[expr]);
10701084

10711085
warnings.sort_by_key(|w| w.block_span);

compiler/rustc_pattern_analysis/src/usefulness.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -951,7 +951,11 @@ impl<Cx: PatCx> PlaceInfo<Cx> {
951951
self.is_scrutinee && matches!(ctors_for_ty, ConstructorSet::NoConstructors);
952952
// Whether empty patterns are counted as useful or not. We only warn an empty arm unreachable if
953953
// it is guaranteed unreachable by the opsem (i.e. if the place is `known_valid`).
954-
let empty_arms_are_unreachable = self.validity.is_known_valid();
954+
// We don't want to warn empty patterns as unreachable by default just yet. We will in a
955+
// later version of rust or under a different lint name, see
956+
// https://github.com/rust-lang/rust/pull/129103.
957+
let empty_arms_are_unreachable = self.validity.is_known_valid()
958+
&& (is_toplevel_exception || cx.is_exhaustive_patterns_feature_on());
955959
// Whether empty patterns can be omitted for exhaustiveness. We ignore place validity in the
956960
// toplevel exception and `exhaustive_patterns` cases for backwards compatibility.
957961
let can_omit_empty_arms = self.validity.is_known_valid()

library/core/src/iter/sources/repeat_n.rs

+45-15
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1+
use crate::fmt;
12
use crate::iter::{FusedIterator, TrustedLen, UncheckedIterator};
2-
use crate::mem::ManuallyDrop;
3+
use crate::mem::{self, MaybeUninit};
34
use crate::num::NonZero;
45

56
/// Creates a new iterator that repeats a single element a given number of times.
@@ -58,14 +59,12 @@ use crate::num::NonZero;
5859
#[inline]
5960
#[stable(feature = "iter_repeat_n", since = "1.82.0")]
6061
pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
61-
let mut element = ManuallyDrop::new(element);
62-
63-
if count == 0 {
64-
// SAFETY: we definitely haven't dropped it yet, since we only just got
65-
// passed it in, and because the count is zero the instance we're about
66-
// to create won't drop it, so to avoid leaking we need to now.
67-
unsafe { ManuallyDrop::drop(&mut element) };
68-
}
62+
let element = if count == 0 {
63+
// `element` gets dropped eagerly.
64+
MaybeUninit::uninit()
65+
} else {
66+
MaybeUninit::new(element)
67+
};
6968

7069
RepeatN { element, count }
7170
}
@@ -74,31 +73,60 @@ pub fn repeat_n<T: Clone>(element: T, count: usize) -> RepeatN<T> {
7473
///
7574
/// This `struct` is created by the [`repeat_n()`] function.
7675
/// See its documentation for more.
77-
#[derive(Clone, Debug)]
7876
#[stable(feature = "iter_repeat_n", since = "1.82.0")]
7977
pub struct RepeatN<A> {
8078
count: usize,
81-
// Invariant: has been dropped iff count == 0.
82-
element: ManuallyDrop<A>,
79+
// Invariant: uninit iff count == 0.
80+
element: MaybeUninit<A>,
8381
}
8482

8583
impl<A> RepeatN<A> {
84+
/// Returns the element if it hasn't been dropped already.
85+
fn element_ref(&self) -> Option<&A> {
86+
if self.count > 0 {
87+
// SAFETY: The count is non-zero, so it must be initialized.
88+
Some(unsafe { self.element.assume_init_ref() })
89+
} else {
90+
None
91+
}
92+
}
8693
/// If we haven't already dropped the element, return it in an option.
8794
///
8895
/// Clears the count so it won't be dropped again later.
8996
#[inline]
9097
fn take_element(&mut self) -> Option<A> {
9198
if self.count > 0 {
9299
self.count = 0;
100+
let element = mem::replace(&mut self.element, MaybeUninit::uninit());
93101
// SAFETY: We just set count to zero so it won't be dropped again,
94102
// and it used to be non-zero so it hasn't already been dropped.
95-
unsafe { Some(ManuallyDrop::take(&mut self.element)) }
103+
unsafe { Some(element.assume_init()) }
96104
} else {
97105
None
98106
}
99107
}
100108
}
101109

110+
#[stable(feature = "iter_repeat_n", since = "1.82.0")]
111+
impl<A: Clone> Clone for RepeatN<A> {
112+
fn clone(&self) -> RepeatN<A> {
113+
RepeatN {
114+
count: self.count,
115+
element: self.element_ref().cloned().map_or_else(MaybeUninit::uninit, MaybeUninit::new),
116+
}
117+
}
118+
}
119+
120+
#[stable(feature = "iter_repeat_n", since = "1.82.0")]
121+
impl<A: fmt::Debug> fmt::Debug for RepeatN<A> {
122+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123+
f.debug_struct("RepeatN")
124+
.field("count", &self.count)
125+
.field("element", &self.element_ref())
126+
.finish()
127+
}
128+
}
129+
102130
#[stable(feature = "iter_repeat_n", since = "1.82.0")]
103131
impl<A> Drop for RepeatN<A> {
104132
fn drop(&mut self) {
@@ -194,9 +222,11 @@ impl<A: Clone> UncheckedIterator for RepeatN<A> {
194222
// SAFETY: the check above ensured that the count used to be non-zero,
195223
// so element hasn't been dropped yet, and we just lowered the count to
196224
// zero so it won't be dropped later, and thus it's okay to take it here.
197-
unsafe { ManuallyDrop::take(&mut self.element) }
225+
unsafe { mem::replace(&mut self.element, MaybeUninit::uninit()).assume_init() }
198226
} else {
199-
A::clone(&self.element)
227+
// SAFETY: the count is non-zero, so it must have not been dropped yet.
228+
let element = unsafe { self.element.assume_init_ref() };
229+
A::clone(element)
200230
}
201231
}
202232
}

library/core/tests/iter/sources.rs

+24
Original file line numberDiff line numberDiff line change
@@ -156,3 +156,27 @@ fn test_repeat_n_drop() {
156156
drop((x0, x1, x2));
157157
assert_eq!(count.get(), 3);
158158
}
159+
160+
#[test]
161+
fn test_repeat_n_soundness() {
162+
let x = std::iter::repeat_n(String::from("use after free"), 0);
163+
println!("{x:?}");
164+
165+
pub struct PanicOnClone;
166+
167+
impl Clone for PanicOnClone {
168+
fn clone(&self) -> Self {
169+
unreachable!()
170+
}
171+
}
172+
173+
// `repeat_n` should drop the element immediately if `count` is zero.
174+
// `Clone` should then not try to clone the element.
175+
let x = std::iter::repeat_n(PanicOnClone, 0);
176+
let _ = x.clone();
177+
178+
let mut y = std::iter::repeat_n(Box::new(0), 1);
179+
let x = y.next().unwrap();
180+
let _z = y;
181+
assert_eq!(0, *x);
182+
}

library/windows_targets/src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,5 @@ pub macro link {
3838
#[link(name = "ntdll")]
3939
#[link(name = "userenv")]
4040
#[link(name = "ws2_32")]
41+
#[link(name = "dbghelp")] // required for backtrace-rs symbolization
4142
extern "C" {}

src/llvm-project

Submodule llvm-project updated 188 files

0 commit comments

Comments
 (0)