Skip to content

Commit 58420a0

Browse files
committed
Auto merge of #130907 - GuillaumeGomez:rollup-423r4i4, r=GuillaumeGomez
Rollup of 11 pull requests Successful merges: - #130279 (Document subtleties of `ManuallyDrop`) - #130517 (Add the library workspace to the suggested rust-analyzer config) - #130820 (Fix diagnostics for coroutines with () as input.) - #130833 (Fix the misleading diagnostic for `let_underscore_drop` on type without `Drop` implementation) - #130845 (Utf8Chunks: add link to Utf8Chunk) - #130850 (Pass Module Analysis Manager to Standard Instrumentations) - #130861 (Use `mem::offset_of!` for `sockaddr_un.sun_path`) - #130862 (rustdoc: do not animate :target when user prefers reduced motion) - #130868 (Update FIXME comment in s390x_unknown_linux_*.rs) - #130879 (Pass correct HirId to late_bound_vars in diagnostic code) - #130880 (add missing FIXME(const-hack)) r? `@ghost` `@rustbot` modify labels: rollup
2 parents 2bd1e89 + 3d4d45f commit 58420a0

27 files changed

+282
-100
lines changed

compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -882,7 +882,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
882882
let ty = self.lowerer().lower_ty(hir_ty);
883883
debug!(?ty, "return type (lowered)");
884884
debug!(?expected, "expected type");
885-
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
885+
let bound_vars =
886+
self.tcx.late_bound_vars(self.tcx.local_def_id_to_hir_id(fn_id));
886887
let ty = Binder::bind_with_vars(ty, bound_vars);
887888
let ty = self.normalize(hir_ty.span, ty);
888889
let ty = self.tcx.instantiate_bound_regions_with_erased(ty);

compiler/rustc_lint/messages.ftl

+1-1
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,7 @@ lint_non_binding_let_multi_suggestion =
531531
consider immediately dropping the value
532532
533533
lint_non_binding_let_on_drop_type =
534-
non-binding let on a type that implements `Drop`
534+
non-binding let on a type that has a destructor
535535
536536
lint_non_binding_let_on_sync_lock = non-binding let on a synchronization lock
537537
.label = this lock is not assigned to a binding and is immediately dropped

compiler/rustc_lint/src/let_underscore.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ declare_lint! {
5151
/// intent.
5252
pub LET_UNDERSCORE_DROP,
5353
Allow,
54-
"non-binding let on a type that implements `Drop`"
54+
"non-binding let on a type that has a destructor"
5555
}
5656

5757
declare_lint! {

compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp

+6-5
Original file line numberDiff line numberDiff line change
@@ -732,12 +732,7 @@ extern "C" LLVMRustResult LLVMRustOptimize(
732732
PTO.SLPVectorization = SLPVectorize;
733733
PTO.MergeFunctions = MergeFunctions;
734734

735-
// FIXME: We may want to expose this as an option.
736-
bool DebugPassManager = false;
737-
738735
PassInstrumentationCallbacks PIC;
739-
StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
740-
SI.registerCallbacks(PIC);
741736

742737
if (LlvmSelfProfiler) {
743738
LLVMSelfProfileInitializeCallbacks(PIC, LlvmSelfProfiler,
@@ -784,6 +779,12 @@ extern "C" LLVMRustResult LLVMRustOptimize(
784779
CGSCCAnalysisManager CGAM;
785780
ModuleAnalysisManager MAM;
786781

782+
// FIXME: We may want to expose this as an option.
783+
bool DebugPassManager = false;
784+
785+
StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
786+
SI.registerCallbacks(PIC, &MAM);
787+
787788
if (LLVMPluginsLen) {
788789
auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen);
789790
SmallVector<StringRef> Plugins;

compiler/rustc_target/src/spec/targets/s390x_unknown_linux_gnu.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ pub(crate) fn target() -> Target {
66
base.endian = Endian::Big;
77
// z10 is the oldest CPU supported by LLVM
88
base.cpu = "z10".into();
9-
// FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
10-
// ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
11-
// also strip v128 from the data_layout below to match the older LLVM's expectation.
9+
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
10+
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
1211
base.features = "-vector".into();
1312
base.max_atomic_width = Some(128);
1413
base.min_global_align = Some(16);

compiler/rustc_target/src/spec/targets/s390x_unknown_linux_musl.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,8 @@ pub(crate) fn target() -> Target {
66
base.endian = Endian::Big;
77
// z10 is the oldest CPU supported by LLVM
88
base.cpu = "z10".into();
9-
// FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
10-
// ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
11-
// also strip v128 from the data_layout below to match the older LLVM's expectation.
9+
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
10+
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
1211
base.features = "-vector".into();
1312
base.max_atomic_width = Some(128);
1413
base.min_global_align = Some(16);

compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs

+35-37
Original file line numberDiff line numberDiff line change
@@ -2635,49 +2635,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
26352635
// This shouldn't be common unless manually implementing one of the
26362636
// traits manually, but don't make it more confusing when it does
26372637
// happen.
2638-
Ok(
2639-
if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait()
2640-
&& not_tupled
2641-
{
2642-
self.report_and_explain_type_error(
2643-
TypeTrace::trait_refs(
2644-
&obligation.cause,
2645-
true,
2646-
expected_trait_ref,
2647-
found_trait_ref,
2648-
),
2649-
ty::error::TypeError::Mismatch,
2650-
)
2651-
} else if found.len() == expected.len() {
2652-
self.report_closure_arg_mismatch(
2653-
span,
2654-
found_span,
2655-
found_trait_ref,
2656-
expected_trait_ref,
2657-
obligation.cause.code(),
2658-
found_node,
2659-
obligation.param_env,
2660-
)
2661-
} else {
2662-
let (closure_span, closure_arg_span, found) = found_did
2663-
.and_then(|did| {
2664-
let node = self.tcx.hir().get_if_local(did)?;
2665-
let (found_span, closure_arg_span, found) =
2666-
self.get_fn_like_arguments(node)?;
2667-
Some((Some(found_span), closure_arg_span, found))
2668-
})
2669-
.unwrap_or((found_span, None, found));
2670-
2671-
self.report_arg_count_mismatch(
2638+
if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled
2639+
{
2640+
return Ok(self.report_and_explain_type_error(
2641+
TypeTrace::trait_refs(&obligation.cause, true, expected_trait_ref, found_trait_ref),
2642+
ty::error::TypeError::Mismatch,
2643+
));
2644+
}
2645+
if found.len() != expected.len() {
2646+
let (closure_span, closure_arg_span, found) = found_did
2647+
.and_then(|did| {
2648+
let node = self.tcx.hir().get_if_local(did)?;
2649+
let (found_span, closure_arg_span, found) = self.get_fn_like_arguments(node)?;
2650+
Some((Some(found_span), closure_arg_span, found))
2651+
})
2652+
.unwrap_or((found_span, None, found));
2653+
2654+
// If the coroutine take a single () as its argument,
2655+
// the trait argument would found the coroutine take 0 arguments,
2656+
// but get_fn_like_arguments would give 1 argument.
2657+
// This would result in "Expected to take 1 argument, but it takes 1 argument".
2658+
// Check again to avoid this.
2659+
if found.len() != expected.len() {
2660+
return Ok(self.report_arg_count_mismatch(
26722661
span,
26732662
closure_span,
26742663
expected,
26752664
found,
26762665
found_trait_ty.is_closure(),
26772666
closure_arg_span,
2678-
)
2679-
},
2680-
)
2667+
));
2668+
}
2669+
}
2670+
Ok(self.report_closure_arg_mismatch(
2671+
span,
2672+
found_span,
2673+
found_trait_ref,
2674+
expected_trait_ref,
2675+
obligation.cause.code(),
2676+
found_node,
2677+
obligation.param_env,
2678+
))
26812679
}
26822680

26832681
/// Given some node representing a fn-like thing in the HIR map,

library/core/src/mem/manually_drop.rs

+118-12
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
use crate::ops::{Deref, DerefMut, DerefPure};
22
use crate::ptr;
33

4-
/// A wrapper to inhibit the compiler from automatically calling `T`’s destructor.
5-
/// This wrapper is 0-cost.
4+
/// A wrapper to inhibit the compiler from automatically calling `T`’s
5+
/// destructor. This wrapper is 0-cost.
66
///
77
/// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
8-
/// `T`, and is subject to the same layout optimizations as `T`. As a consequence,
9-
/// it has *no effect* on the assumptions that the compiler makes about its
10-
/// contents. For example, initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`]
11-
/// is undefined behavior. If you need to handle uninitialized data, use
12-
/// [`MaybeUninit<T>`] instead.
8+
/// `T`, and is subject to the same layout optimizations as `T`. As a
9+
/// consequence, it has *no effect* on the assumptions that the compiler makes
10+
/// about its contents. For example, initializing a `ManuallyDrop<&mut T>` with
11+
/// [`mem::zeroed`] is undefined behavior. If you need to handle uninitialized
12+
/// data, use [`MaybeUninit<T>`] instead.
1313
///
14-
/// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
15-
/// This means that a `ManuallyDrop<T>` whose content has been dropped must not
16-
/// be exposed through a public safe API.
17-
/// Correspondingly, `ManuallyDrop::drop` is unsafe.
14+
/// Note that accessing the value inside a `ManuallyDrop<T>` is safe. This means
15+
/// that a `ManuallyDrop<T>` whose content has been dropped must not be exposed
16+
/// through a public safe API. Correspondingly, `ManuallyDrop::drop` is unsafe.
1817
///
19-
/// # `ManuallyDrop` and drop order.
18+
/// # `ManuallyDrop` and drop order
2019
///
2120
/// Rust has a well-defined [drop order] of values. To make sure that fields or
2221
/// locals are dropped in a specific order, reorder the declarations such that
@@ -40,9 +39,116 @@ use crate::ptr;
4039
/// }
4140
/// ```
4241
///
42+
/// # Interaction with `Box`
43+
///
44+
/// Currently, if you have a `ManuallyDrop<T>`, where the type `T` is a `Box` or
45+
/// contains a `Box` inside, then dropping the `T` followed by moving the
46+
/// `ManuallyDrop<T>` is [considered to be undefined
47+
/// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245).
48+
/// That is, the following code causes undefined behavior:
49+
///
50+
/// ```no_run
51+
/// use std::mem::ManuallyDrop;
52+
///
53+
/// let mut x = ManuallyDrop::new(Box::new(42));
54+
/// unsafe {
55+
/// ManuallyDrop::drop(&mut x);
56+
/// }
57+
/// let y = x; // Undefined behavior!
58+
/// ```
59+
///
60+
/// This is [likely to change in the
61+
/// future](https://rust-lang.github.io/rfcs/3336-maybe-dangling.html). In the
62+
/// meantime, consider using [`MaybeUninit`] instead.
63+
///
64+
/// # Safety hazards when storing `ManuallyDrop` in a struct or an enum.
65+
///
66+
/// Special care is needed when all of the conditions below are met:
67+
/// * A struct or enum contains a `ManuallyDrop`.
68+
/// * The `ManuallyDrop` is not inside a `union`.
69+
/// * The struct or enum is part of public API, or is stored in a struct or an
70+
/// enum that is part of public API.
71+
/// * There is code that drops the contents of the `ManuallyDrop` field, and
72+
/// this code is outside the struct or enum's `Drop` implementation.
73+
///
74+
/// In particular, the following hazards may occur:
75+
///
76+
/// #### Storing generic types
77+
///
78+
/// If the `ManuallyDrop` contains a client-supplied generic type, the client
79+
/// might provide a `Box` as that type. This would cause undefined behavior when
80+
/// the struct or enum is later moved, as mentioned in the previous section. For
81+
/// example, the following code causes undefined behavior:
82+
///
83+
/// ```no_run
84+
/// use std::mem::ManuallyDrop;
85+
///
86+
/// pub struct BadOption<T> {
87+
/// // Invariant: Has been dropped iff `is_some` is false.
88+
/// value: ManuallyDrop<T>,
89+
/// is_some: bool,
90+
/// }
91+
/// impl<T> BadOption<T> {
92+
/// pub fn new(value: T) -> Self {
93+
/// Self { value: ManuallyDrop::new(value), is_some: true }
94+
/// }
95+
/// pub fn change_to_none(&mut self) {
96+
/// if self.is_some {
97+
/// self.is_some = false;
98+
/// unsafe {
99+
/// // SAFETY: `value` hasn't been dropped yet, as per the invariant
100+
/// // (This is actually unsound!)
101+
/// ManuallyDrop::drop(&mut self.value);
102+
/// }
103+
/// }
104+
/// }
105+
/// }
106+
///
107+
/// // In another crate:
108+
///
109+
/// let mut option = BadOption::new(Box::new(42));
110+
/// option.change_to_none();
111+
/// let option2 = option; // Undefined behavior!
112+
/// ```
113+
///
114+
/// #### Deriving traits
115+
///
116+
/// Deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`, or `Hash` on
117+
/// the struct or enum could be unsound, since the derived implementations of
118+
/// these traits would access the `ManuallyDrop` field. For example, the
119+
/// following code causes undefined behavior:
120+
///
121+
/// ```no_run
122+
/// use std::mem::ManuallyDrop;
123+
///
124+
/// // This derive is unsound in combination with the `ManuallyDrop::drop` call.
125+
/// #[derive(Debug)]
126+
/// pub struct Foo {
127+
/// value: ManuallyDrop<String>,
128+
/// }
129+
/// impl Foo {
130+
/// pub fn new() -> Self {
131+
/// let mut temp = Self {
132+
/// value: ManuallyDrop::new(String::from("Unsafe rust is hard."))
133+
/// };
134+
/// unsafe {
135+
/// // SAFETY: `value` hasn't been dropped yet.
136+
/// ManuallyDrop::drop(&mut temp.value);
137+
/// }
138+
/// temp
139+
/// }
140+
/// }
141+
///
142+
/// // In another crate:
143+
///
144+
/// let foo = Foo::new();
145+
/// println!("{:?}", foo); // Undefined behavior!
146+
/// ```
147+
///
43148
/// [drop order]: https://doc.rust-lang.org/reference/destructors.html
44149
/// [`mem::zeroed`]: crate::mem::zeroed
45150
/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
151+
/// [`MaybeUninit`]: crate::mem::MaybeUninit
46152
#[stable(feature = "manually_drop", since = "1.20.0")]
47153
#[lang = "manually_drop"]
48154
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]

library/core/src/ptr/alignment.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ impl Alignment {
155155
!(unsafe { self.as_usize().unchecked_sub(1) })
156156
}
157157

158-
// Remove me once `Ord::max` is usable in const
158+
// FIXME(const-hack) Remove me once `Ord::max` is usable in const
159159
pub(crate) const fn max(a: Self, b: Self) -> Self {
160160
if a.as_usize() > b.as_usize() { a } else { b }
161161
}

library/core/src/str/lossy.rs

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ impl [u8] {
88
/// Creates an iterator over the contiguous valid UTF-8 ranges of this
99
/// slice, and the non-UTF-8 fragments in between.
1010
///
11+
/// See the [`Utf8Chunk`] type for documenation of the items yielded by this iterator.
12+
///
1113
/// # Examples
1214
///
1315
/// This function formats arbitrary but mostly-UTF-8 bytes into Rust source
@@ -148,6 +150,8 @@ impl fmt::Debug for Debug<'_> {
148150
/// If you want a simple conversion from UTF-8 byte slices to string slices,
149151
/// [`from_utf8`] is easier to use.
150152
///
153+
/// See the [`Utf8Chunk`] type for documenation of the items yielded by this iterator.
154+
///
151155
/// [byteslice]: slice
152156
/// [`from_utf8`]: super::from_utf8
153157
///

0 commit comments

Comments
 (0)