mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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
This commit is contained in:
commit
58420a065b
@ -882,7 +882,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||||||
let ty = self.lowerer().lower_ty(hir_ty);
|
let ty = self.lowerer().lower_ty(hir_ty);
|
||||||
debug!(?ty, "return type (lowered)");
|
debug!(?ty, "return type (lowered)");
|
||||||
debug!(?expected, "expected type");
|
debug!(?expected, "expected type");
|
||||||
let bound_vars = self.tcx.late_bound_vars(hir_ty.hir_id.owner.into());
|
let bound_vars =
|
||||||
|
self.tcx.late_bound_vars(self.tcx.local_def_id_to_hir_id(fn_id));
|
||||||
let ty = Binder::bind_with_vars(ty, bound_vars);
|
let ty = Binder::bind_with_vars(ty, bound_vars);
|
||||||
let ty = self.normalize(hir_ty.span, ty);
|
let ty = self.normalize(hir_ty.span, ty);
|
||||||
let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
|
let ty = self.tcx.instantiate_bound_regions_with_erased(ty);
|
||||||
|
@ -531,7 +531,7 @@ lint_non_binding_let_multi_suggestion =
|
|||||||
consider immediately dropping the value
|
consider immediately dropping the value
|
||||||
|
|
||||||
lint_non_binding_let_on_drop_type =
|
lint_non_binding_let_on_drop_type =
|
||||||
non-binding let on a type that implements `Drop`
|
non-binding let on a type that has a destructor
|
||||||
|
|
||||||
lint_non_binding_let_on_sync_lock = non-binding let on a synchronization lock
|
lint_non_binding_let_on_sync_lock = non-binding let on a synchronization lock
|
||||||
.label = this lock is not assigned to a binding and is immediately dropped
|
.label = this lock is not assigned to a binding and is immediately dropped
|
||||||
|
@ -51,7 +51,7 @@ declare_lint! {
|
|||||||
/// intent.
|
/// intent.
|
||||||
pub LET_UNDERSCORE_DROP,
|
pub LET_UNDERSCORE_DROP,
|
||||||
Allow,
|
Allow,
|
||||||
"non-binding let on a type that implements `Drop`"
|
"non-binding let on a type that has a destructor"
|
||||||
}
|
}
|
||||||
|
|
||||||
declare_lint! {
|
declare_lint! {
|
||||||
|
@ -732,12 +732,7 @@ extern "C" LLVMRustResult LLVMRustOptimize(
|
|||||||
PTO.SLPVectorization = SLPVectorize;
|
PTO.SLPVectorization = SLPVectorize;
|
||||||
PTO.MergeFunctions = MergeFunctions;
|
PTO.MergeFunctions = MergeFunctions;
|
||||||
|
|
||||||
// FIXME: We may want to expose this as an option.
|
|
||||||
bool DebugPassManager = false;
|
|
||||||
|
|
||||||
PassInstrumentationCallbacks PIC;
|
PassInstrumentationCallbacks PIC;
|
||||||
StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
|
|
||||||
SI.registerCallbacks(PIC);
|
|
||||||
|
|
||||||
if (LlvmSelfProfiler) {
|
if (LlvmSelfProfiler) {
|
||||||
LLVMSelfProfileInitializeCallbacks(PIC, LlvmSelfProfiler,
|
LLVMSelfProfileInitializeCallbacks(PIC, LlvmSelfProfiler,
|
||||||
@ -784,6 +779,12 @@ extern "C" LLVMRustResult LLVMRustOptimize(
|
|||||||
CGSCCAnalysisManager CGAM;
|
CGSCCAnalysisManager CGAM;
|
||||||
ModuleAnalysisManager MAM;
|
ModuleAnalysisManager MAM;
|
||||||
|
|
||||||
|
// FIXME: We may want to expose this as an option.
|
||||||
|
bool DebugPassManager = false;
|
||||||
|
|
||||||
|
StandardInstrumentations SI(TheModule->getContext(), DebugPassManager);
|
||||||
|
SI.registerCallbacks(PIC, &MAM);
|
||||||
|
|
||||||
if (LLVMPluginsLen) {
|
if (LLVMPluginsLen) {
|
||||||
auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen);
|
auto PluginsStr = StringRef(LLVMPlugins, LLVMPluginsLen);
|
||||||
SmallVector<StringRef> Plugins;
|
SmallVector<StringRef> Plugins;
|
||||||
|
@ -6,9 +6,8 @@ pub(crate) fn target() -> Target {
|
|||||||
base.endian = Endian::Big;
|
base.endian = Endian::Big;
|
||||||
// z10 is the oldest CPU supported by LLVM
|
// z10 is the oldest CPU supported by LLVM
|
||||||
base.cpu = "z10".into();
|
base.cpu = "z10".into();
|
||||||
// FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
|
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
|
||||||
// ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
|
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
|
||||||
// also strip v128 from the data_layout below to match the older LLVM's expectation.
|
|
||||||
base.features = "-vector".into();
|
base.features = "-vector".into();
|
||||||
base.max_atomic_width = Some(128);
|
base.max_atomic_width = Some(128);
|
||||||
base.min_global_align = Some(16);
|
base.min_global_align = Some(16);
|
||||||
|
@ -6,9 +6,8 @@ pub(crate) fn target() -> Target {
|
|||||||
base.endian = Endian::Big;
|
base.endian = Endian::Big;
|
||||||
// z10 is the oldest CPU supported by LLVM
|
// z10 is the oldest CPU supported by LLVM
|
||||||
base.cpu = "z10".into();
|
base.cpu = "z10".into();
|
||||||
// FIXME: The ABI implementation in cabi_s390x.rs is for now hard-coded to assume the no-vector
|
// FIXME: The ABI implementation in abi/call/s390x.rs is for now hard-coded to assume the no-vector
|
||||||
// ABI. Pass the -vector feature string to LLVM to respect this assumption. On LLVM < 16, we
|
// ABI. Pass the -vector feature string to LLVM to respect this assumption.
|
||||||
// also strip v128 from the data_layout below to match the older LLVM's expectation.
|
|
||||||
base.features = "-vector".into();
|
base.features = "-vector".into();
|
||||||
base.max_atomic_width = Some(128);
|
base.max_atomic_width = Some(128);
|
||||||
base.min_global_align = Some(16);
|
base.min_global_align = Some(16);
|
||||||
|
@ -2635,49 +2635,47 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
|
|||||||
// This shouldn't be common unless manually implementing one of the
|
// This shouldn't be common unless manually implementing one of the
|
||||||
// traits manually, but don't make it more confusing when it does
|
// traits manually, but don't make it more confusing when it does
|
||||||
// happen.
|
// happen.
|
||||||
Ok(
|
if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait() && not_tupled
|
||||||
if Some(expected_trait_ref.def_id) != self.tcx.lang_items().coroutine_trait()
|
{
|
||||||
&& not_tupled
|
return Ok(self.report_and_explain_type_error(
|
||||||
{
|
TypeTrace::trait_refs(&obligation.cause, true, expected_trait_ref, found_trait_ref),
|
||||||
self.report_and_explain_type_error(
|
ty::error::TypeError::Mismatch,
|
||||||
TypeTrace::trait_refs(
|
));
|
||||||
&obligation.cause,
|
}
|
||||||
true,
|
if found.len() != expected.len() {
|
||||||
expected_trait_ref,
|
let (closure_span, closure_arg_span, found) = found_did
|
||||||
found_trait_ref,
|
.and_then(|did| {
|
||||||
),
|
let node = self.tcx.hir().get_if_local(did)?;
|
||||||
ty::error::TypeError::Mismatch,
|
let (found_span, closure_arg_span, found) = self.get_fn_like_arguments(node)?;
|
||||||
)
|
Some((Some(found_span), closure_arg_span, found))
|
||||||
} else if found.len() == expected.len() {
|
})
|
||||||
self.report_closure_arg_mismatch(
|
.unwrap_or((found_span, None, found));
|
||||||
span,
|
|
||||||
found_span,
|
|
||||||
found_trait_ref,
|
|
||||||
expected_trait_ref,
|
|
||||||
obligation.cause.code(),
|
|
||||||
found_node,
|
|
||||||
obligation.param_env,
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
let (closure_span, closure_arg_span, found) = found_did
|
|
||||||
.and_then(|did| {
|
|
||||||
let node = self.tcx.hir().get_if_local(did)?;
|
|
||||||
let (found_span, closure_arg_span, found) =
|
|
||||||
self.get_fn_like_arguments(node)?;
|
|
||||||
Some((Some(found_span), closure_arg_span, found))
|
|
||||||
})
|
|
||||||
.unwrap_or((found_span, None, found));
|
|
||||||
|
|
||||||
self.report_arg_count_mismatch(
|
// If the coroutine take a single () as its argument,
|
||||||
|
// the trait argument would found the coroutine take 0 arguments,
|
||||||
|
// but get_fn_like_arguments would give 1 argument.
|
||||||
|
// This would result in "Expected to take 1 argument, but it takes 1 argument".
|
||||||
|
// Check again to avoid this.
|
||||||
|
if found.len() != expected.len() {
|
||||||
|
return Ok(self.report_arg_count_mismatch(
|
||||||
span,
|
span,
|
||||||
closure_span,
|
closure_span,
|
||||||
expected,
|
expected,
|
||||||
found,
|
found,
|
||||||
found_trait_ty.is_closure(),
|
found_trait_ty.is_closure(),
|
||||||
closure_arg_span,
|
closure_arg_span,
|
||||||
)
|
));
|
||||||
},
|
}
|
||||||
)
|
}
|
||||||
|
Ok(self.report_closure_arg_mismatch(
|
||||||
|
span,
|
||||||
|
found_span,
|
||||||
|
found_trait_ref,
|
||||||
|
expected_trait_ref,
|
||||||
|
obligation.cause.code(),
|
||||||
|
found_node,
|
||||||
|
obligation.param_env,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given some node representing a fn-like thing in the HIR map,
|
/// Given some node representing a fn-like thing in the HIR map,
|
||||||
|
@ -1,22 +1,21 @@
|
|||||||
use crate::ops::{Deref, DerefMut, DerefPure};
|
use crate::ops::{Deref, DerefMut, DerefPure};
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
|
|
||||||
/// A wrapper to inhibit the compiler from automatically calling `T`’s destructor.
|
/// A wrapper to inhibit the compiler from automatically calling `T`’s
|
||||||
/// This wrapper is 0-cost.
|
/// destructor. This wrapper is 0-cost.
|
||||||
///
|
///
|
||||||
/// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
|
/// `ManuallyDrop<T>` is guaranteed to have the same layout and bit validity as
|
||||||
/// `T`, and is subject to the same layout optimizations as `T`. As a consequence,
|
/// `T`, and is subject to the same layout optimizations as `T`. As a
|
||||||
/// it has *no effect* on the assumptions that the compiler makes about its
|
/// consequence, it has *no effect* on the assumptions that the compiler makes
|
||||||
/// contents. For example, initializing a `ManuallyDrop<&mut T>` with [`mem::zeroed`]
|
/// about its contents. For example, initializing a `ManuallyDrop<&mut T>` with
|
||||||
/// is undefined behavior. If you need to handle uninitialized data, use
|
/// [`mem::zeroed`] is undefined behavior. If you need to handle uninitialized
|
||||||
/// [`MaybeUninit<T>`] instead.
|
/// data, use [`MaybeUninit<T>`] instead.
|
||||||
///
|
///
|
||||||
/// Note that accessing the value inside a `ManuallyDrop<T>` is safe.
|
/// Note that accessing the value inside a `ManuallyDrop<T>` is safe. This means
|
||||||
/// This means that a `ManuallyDrop<T>` whose content has been dropped must not
|
/// that a `ManuallyDrop<T>` whose content has been dropped must not be exposed
|
||||||
/// be exposed through a public safe API.
|
/// through a public safe API. Correspondingly, `ManuallyDrop::drop` is unsafe.
|
||||||
/// Correspondingly, `ManuallyDrop::drop` is unsafe.
|
|
||||||
///
|
///
|
||||||
/// # `ManuallyDrop` and drop order.
|
/// # `ManuallyDrop` and drop order
|
||||||
///
|
///
|
||||||
/// Rust has a well-defined [drop order] of values. To make sure that fields or
|
/// Rust has a well-defined [drop order] of values. To make sure that fields or
|
||||||
/// locals are dropped in a specific order, reorder the declarations such that
|
/// locals are dropped in a specific order, reorder the declarations such that
|
||||||
@ -40,9 +39,116 @@ use crate::ptr;
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
///
|
///
|
||||||
|
/// # Interaction with `Box`
|
||||||
|
///
|
||||||
|
/// Currently, if you have a `ManuallyDrop<T>`, where the type `T` is a `Box` or
|
||||||
|
/// contains a `Box` inside, then dropping the `T` followed by moving the
|
||||||
|
/// `ManuallyDrop<T>` is [considered to be undefined
|
||||||
|
/// behavior](https://github.com/rust-lang/unsafe-code-guidelines/issues/245).
|
||||||
|
/// That is, the following code causes undefined behavior:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use std::mem::ManuallyDrop;
|
||||||
|
///
|
||||||
|
/// let mut x = ManuallyDrop::new(Box::new(42));
|
||||||
|
/// unsafe {
|
||||||
|
/// ManuallyDrop::drop(&mut x);
|
||||||
|
/// }
|
||||||
|
/// let y = x; // Undefined behavior!
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// This is [likely to change in the
|
||||||
|
/// future](https://rust-lang.github.io/rfcs/3336-maybe-dangling.html). In the
|
||||||
|
/// meantime, consider using [`MaybeUninit`] instead.
|
||||||
|
///
|
||||||
|
/// # Safety hazards when storing `ManuallyDrop` in a struct or an enum.
|
||||||
|
///
|
||||||
|
/// Special care is needed when all of the conditions below are met:
|
||||||
|
/// * A struct or enum contains a `ManuallyDrop`.
|
||||||
|
/// * The `ManuallyDrop` is not inside a `union`.
|
||||||
|
/// * The struct or enum is part of public API, or is stored in a struct or an
|
||||||
|
/// enum that is part of public API.
|
||||||
|
/// * There is code that drops the contents of the `ManuallyDrop` field, and
|
||||||
|
/// this code is outside the struct or enum's `Drop` implementation.
|
||||||
|
///
|
||||||
|
/// In particular, the following hazards may occur:
|
||||||
|
///
|
||||||
|
/// #### Storing generic types
|
||||||
|
///
|
||||||
|
/// If the `ManuallyDrop` contains a client-supplied generic type, the client
|
||||||
|
/// might provide a `Box` as that type. This would cause undefined behavior when
|
||||||
|
/// the struct or enum is later moved, as mentioned in the previous section. For
|
||||||
|
/// example, the following code causes undefined behavior:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use std::mem::ManuallyDrop;
|
||||||
|
///
|
||||||
|
/// pub struct BadOption<T> {
|
||||||
|
/// // Invariant: Has been dropped iff `is_some` is false.
|
||||||
|
/// value: ManuallyDrop<T>,
|
||||||
|
/// is_some: bool,
|
||||||
|
/// }
|
||||||
|
/// impl<T> BadOption<T> {
|
||||||
|
/// pub fn new(value: T) -> Self {
|
||||||
|
/// Self { value: ManuallyDrop::new(value), is_some: true }
|
||||||
|
/// }
|
||||||
|
/// pub fn change_to_none(&mut self) {
|
||||||
|
/// if self.is_some {
|
||||||
|
/// self.is_some = false;
|
||||||
|
/// unsafe {
|
||||||
|
/// // SAFETY: `value` hasn't been dropped yet, as per the invariant
|
||||||
|
/// // (This is actually unsound!)
|
||||||
|
/// ManuallyDrop::drop(&mut self.value);
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // In another crate:
|
||||||
|
///
|
||||||
|
/// let mut option = BadOption::new(Box::new(42));
|
||||||
|
/// option.change_to_none();
|
||||||
|
/// let option2 = option; // Undefined behavior!
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
|
/// #### Deriving traits
|
||||||
|
///
|
||||||
|
/// Deriving `Debug`, `Clone`, `PartialEq`, `PartialOrd`, `Ord`, or `Hash` on
|
||||||
|
/// the struct or enum could be unsound, since the derived implementations of
|
||||||
|
/// these traits would access the `ManuallyDrop` field. For example, the
|
||||||
|
/// following code causes undefined behavior:
|
||||||
|
///
|
||||||
|
/// ```no_run
|
||||||
|
/// use std::mem::ManuallyDrop;
|
||||||
|
///
|
||||||
|
/// // This derive is unsound in combination with the `ManuallyDrop::drop` call.
|
||||||
|
/// #[derive(Debug)]
|
||||||
|
/// pub struct Foo {
|
||||||
|
/// value: ManuallyDrop<String>,
|
||||||
|
/// }
|
||||||
|
/// impl Foo {
|
||||||
|
/// pub fn new() -> Self {
|
||||||
|
/// let mut temp = Self {
|
||||||
|
/// value: ManuallyDrop::new(String::from("Unsafe rust is hard."))
|
||||||
|
/// };
|
||||||
|
/// unsafe {
|
||||||
|
/// // SAFETY: `value` hasn't been dropped yet.
|
||||||
|
/// ManuallyDrop::drop(&mut temp.value);
|
||||||
|
/// }
|
||||||
|
/// temp
|
||||||
|
/// }
|
||||||
|
/// }
|
||||||
|
///
|
||||||
|
/// // In another crate:
|
||||||
|
///
|
||||||
|
/// let foo = Foo::new();
|
||||||
|
/// println!("{:?}", foo); // Undefined behavior!
|
||||||
|
/// ```
|
||||||
|
///
|
||||||
/// [drop order]: https://doc.rust-lang.org/reference/destructors.html
|
/// [drop order]: https://doc.rust-lang.org/reference/destructors.html
|
||||||
/// [`mem::zeroed`]: crate::mem::zeroed
|
/// [`mem::zeroed`]: crate::mem::zeroed
|
||||||
/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
|
/// [`MaybeUninit<T>`]: crate::mem::MaybeUninit
|
||||||
|
/// [`MaybeUninit`]: crate::mem::MaybeUninit
|
||||||
#[stable(feature = "manually_drop", since = "1.20.0")]
|
#[stable(feature = "manually_drop", since = "1.20.0")]
|
||||||
#[lang = "manually_drop"]
|
#[lang = "manually_drop"]
|
||||||
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
@ -155,7 +155,7 @@ impl Alignment {
|
|||||||
!(unsafe { self.as_usize().unchecked_sub(1) })
|
!(unsafe { self.as_usize().unchecked_sub(1) })
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove me once `Ord::max` is usable in const
|
// FIXME(const-hack) Remove me once `Ord::max` is usable in const
|
||||||
pub(crate) const fn max(a: Self, b: Self) -> Self {
|
pub(crate) const fn max(a: Self, b: Self) -> Self {
|
||||||
if a.as_usize() > b.as_usize() { a } else { b }
|
if a.as_usize() > b.as_usize() { a } else { b }
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,8 @@ impl [u8] {
|
|||||||
/// Creates an iterator over the contiguous valid UTF-8 ranges of this
|
/// Creates an iterator over the contiguous valid UTF-8 ranges of this
|
||||||
/// slice, and the non-UTF-8 fragments in between.
|
/// slice, and the non-UTF-8 fragments in between.
|
||||||
///
|
///
|
||||||
|
/// See the [`Utf8Chunk`] type for documenation of the items yielded by this iterator.
|
||||||
|
///
|
||||||
/// # Examples
|
/// # Examples
|
||||||
///
|
///
|
||||||
/// This function formats arbitrary but mostly-UTF-8 bytes into Rust source
|
/// This function formats arbitrary but mostly-UTF-8 bytes into Rust source
|
||||||
@ -148,6 +150,8 @@ impl fmt::Debug for Debug<'_> {
|
|||||||
/// If you want a simple conversion from UTF-8 byte slices to string slices,
|
/// If you want a simple conversion from UTF-8 byte slices to string slices,
|
||||||
/// [`from_utf8`] is easier to use.
|
/// [`from_utf8`] is easier to use.
|
||||||
///
|
///
|
||||||
|
/// See the [`Utf8Chunk`] type for documenation of the items yielded by this iterator.
|
||||||
|
///
|
||||||
/// [byteslice]: slice
|
/// [byteslice]: slice
|
||||||
/// [`from_utf8`]: super::from_utf8
|
/// [`from_utf8`]: super::from_utf8
|
||||||
///
|
///
|
||||||
|
@ -15,15 +15,12 @@ mod libc {
|
|||||||
pub type socklen_t = u32;
|
pub type socklen_t = u32;
|
||||||
pub struct sockaddr;
|
pub struct sockaddr;
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct sockaddr_un;
|
pub struct sockaddr_un {
|
||||||
|
pub sun_path: [u8; 1],
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn sun_path_offset(addr: &libc::sockaddr_un) -> usize {
|
const SUN_PATH_OFFSET: usize = mem::offset_of!(libc::sockaddr_un, sun_path);
|
||||||
// Work with an actual instance of the type since using a null pointer is UB
|
|
||||||
let base = (addr as *const libc::sockaddr_un).addr();
|
|
||||||
let path = core::ptr::addr_of!(addr.sun_path).addr();
|
|
||||||
path - base
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
|
pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
|
||||||
// SAFETY: All zeros is a valid representation for `sockaddr_un`.
|
// SAFETY: All zeros is a valid representation for `sockaddr_un`.
|
||||||
@ -53,7 +50,7 @@ pub(super) fn sockaddr_un(path: &Path) -> io::Result<(libc::sockaddr_un, libc::s
|
|||||||
ptr::copy_nonoverlapping(bytes.as_ptr(), addr.sun_path.as_mut_ptr().cast(), bytes.len())
|
ptr::copy_nonoverlapping(bytes.as_ptr(), addr.sun_path.as_mut_ptr().cast(), bytes.len())
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut len = sun_path_offset(&addr) + bytes.len();
|
let mut len = SUN_PATH_OFFSET + bytes.len();
|
||||||
match bytes.get(0) {
|
match bytes.get(0) {
|
||||||
Some(&0) | None => {}
|
Some(&0) | None => {}
|
||||||
Some(_) => len += 1,
|
Some(_) => len += 1,
|
||||||
@ -114,13 +111,13 @@ impl SocketAddr {
|
|||||||
let sun_path: &[u8] =
|
let sun_path: &[u8] =
|
||||||
unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&addr.sun_path) };
|
unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&addr.sun_path) };
|
||||||
len = core::slice::memchr::memchr(0, sun_path)
|
len = core::slice::memchr::memchr(0, sun_path)
|
||||||
.map_or(len, |new_len| (new_len + sun_path_offset(&addr)) as libc::socklen_t);
|
.map_or(len, |new_len| (new_len + SUN_PATH_OFFSET) as libc::socklen_t);
|
||||||
}
|
}
|
||||||
|
|
||||||
if len == 0 {
|
if len == 0 {
|
||||||
// When there is a datagram from unnamed unix socket
|
// When there is a datagram from unnamed unix socket
|
||||||
// linux returns zero bytes of address
|
// linux returns zero bytes of address
|
||||||
len = sun_path_offset(&addr) as libc::socklen_t; // i.e., zero-length address
|
len = SUN_PATH_OFFSET as libc::socklen_t; // i.e., zero-length address
|
||||||
} else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
|
} else if addr.sun_family != libc::AF_UNIX as libc::sa_family_t {
|
||||||
return Err(io::const_io_error!(
|
return Err(io::const_io_error!(
|
||||||
io::ErrorKind::InvalidInput,
|
io::ErrorKind::InvalidInput,
|
||||||
@ -238,7 +235,7 @@ impl SocketAddr {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn address(&self) -> AddressKind<'_> {
|
fn address(&self) -> AddressKind<'_> {
|
||||||
let len = self.len as usize - sun_path_offset(&self.addr);
|
let len = self.len as usize - SUN_PATH_OFFSET;
|
||||||
let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
|
let path = unsafe { mem::transmute::<&[libc::c_char], &[u8]>(&self.addr.sun_path) };
|
||||||
|
|
||||||
// macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
|
// macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
|
||||||
@ -287,7 +284,7 @@ impl linux_ext::addr::SocketAddrExt for SocketAddr {
|
|||||||
addr.sun_path.as_mut_ptr().add(1) as *mut u8,
|
addr.sun_path.as_mut_ptr().add(1) as *mut u8,
|
||||||
name.len(),
|
name.len(),
|
||||||
);
|
);
|
||||||
let len = (sun_path_offset(&addr) + 1 + name.len()) as libc::socklen_t;
|
let len = (SUN_PATH_OFFSET + 1 + name.len()) as libc::socklen_t;
|
||||||
SocketAddr::from_parts(addr, len)
|
SocketAddr::from_parts(addr, len)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,6 +46,7 @@ static SETTINGS_HASHES: &[&str] = &[
|
|||||||
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
|
"47d227f424bf889b0d899b9cc992d5695e1b78c406e183cd78eafefbe5488923",
|
||||||
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
|
"b526bd58d0262dd4dda2bff5bc5515b705fb668a46235ace3e057f807963a11a",
|
||||||
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
|
"828666b021d837a33e78d870b56d34c88a5e2c85de58b693607ec574f0c27000",
|
||||||
|
"811fb3b063c739d261fd8590dd30242e117908f5a095d594fa04585daa18ec4d",
|
||||||
];
|
];
|
||||||
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json");
|
static RUST_ANALYZER_SETTINGS: &str = include_str!("../../../../etc/rust_analyzer_settings.json");
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
],
|
],
|
||||||
"rust-analyzer.linkedProjects": [
|
"rust-analyzer.linkedProjects": [
|
||||||
"Cargo.toml",
|
"Cargo.toml",
|
||||||
|
"library/Cargo.toml",
|
||||||
"src/tools/x/Cargo.toml",
|
"src/tools/x/Cargo.toml",
|
||||||
"src/bootstrap/Cargo.toml",
|
"src/bootstrap/Cargo.toml",
|
||||||
"src/tools/rust-analyzer/Cargo.toml",
|
"src/tools/rust-analyzer/Cargo.toml",
|
||||||
|
@ -1687,7 +1687,6 @@ instead, we check that it's not a "finger" cursor.
|
|||||||
padding-right: 3px;
|
padding-right: 3px;
|
||||||
background-color: var(--target-background-color);
|
background-color: var(--target-background-color);
|
||||||
border-right: 3px solid var(--target-border-color);
|
border-right: 3px solid var(--target-border-color);
|
||||||
animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.code-header a.tooltip {
|
.code-header a.tooltip {
|
||||||
@ -1712,12 +1711,18 @@ a.tooltip:hover::after {
|
|||||||
content: "\00a0";
|
content: "\00a0";
|
||||||
}
|
}
|
||||||
|
|
||||||
/* This animation is layered onto the mistake-proofing delay for dismissing
|
@media not (prefers-reduced-motion) {
|
||||||
a hovered tooltip, to ensure it feels responsive even with the delay.
|
:target {
|
||||||
*/
|
animation: 0.65s cubic-bezier(0, 0, 0.1, 1.0) 0.1s targetfadein;
|
||||||
.fade-out {
|
}
|
||||||
opacity: 0;
|
|
||||||
transition: opacity 0.45s cubic-bezier(0, 0, 0.1, 1.0);
|
/* This animation is layered onto the mistake-proofing delay for dismissing
|
||||||
|
a hovered tooltip, to ensure it feels responsive even with the delay.
|
||||||
|
*/
|
||||||
|
.fade-out {
|
||||||
|
opacity: 0;
|
||||||
|
transition: opacity 0.45s cubic-bezier(0, 0, 0.1, 1.0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.popover.tooltip .content {
|
.popover.tooltip .content {
|
||||||
|
@ -1,8 +0,0 @@
|
|||||||
//@ known-bug: rust-lang/rust#125655
|
|
||||||
|
|
||||||
fn main() {
|
|
||||||
static foo: dyn Fn() -> u32 = || -> u32 {
|
|
||||||
...
|
|
||||||
0
|
|
||||||
};
|
|
||||||
}
|
|
15
tests/ui/closures/binder/closure-return-type-mismatch.rs
Normal file
15
tests/ui/closures/binder/closure-return-type-mismatch.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
// We used to bind the closure return type `&'a ()` with the late-bound vars of
|
||||||
|
// the owner (here `main` & `env` resp.) instead of the ones of the enclosing
|
||||||
|
// function-like / closure inside diagnostic code which was incorrect.
|
||||||
|
|
||||||
|
#![feature(closure_lifetime_binder)]
|
||||||
|
|
||||||
|
// issue: rust-lang/rust#130391
|
||||||
|
fn main() {
|
||||||
|
let _ = for<'a> |x: &'a u8| -> &'a () { x }; //~ ERROR mismatched types
|
||||||
|
}
|
||||||
|
|
||||||
|
// issue: rust-lang/rust#130663
|
||||||
|
fn env<'r>() {
|
||||||
|
let _ = for<'a> |x: &'a u8| -> &'a () { x }; //~ ERROR mismatched types
|
||||||
|
}
|
25
tests/ui/closures/binder/closure-return-type-mismatch.stderr
Normal file
25
tests/ui/closures/binder/closure-return-type-mismatch.stderr
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/closure-return-type-mismatch.rs:9:45
|
||||||
|
|
|
||||||
|
LL | let _ = for<'a> |x: &'a u8| -> &'a () { x };
|
||||||
|
| ------ ^ expected `&()`, found `&u8`
|
||||||
|
| |
|
||||||
|
| expected `&'a ()` because of return type
|
||||||
|
|
|
||||||
|
= note: expected reference `&'a ()`
|
||||||
|
found reference `&'a u8`
|
||||||
|
|
||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/closure-return-type-mismatch.rs:14:45
|
||||||
|
|
|
||||||
|
LL | let _ = for<'a> |x: &'a u8| -> &'a () { x };
|
||||||
|
| ------ ^ expected `&()`, found `&u8`
|
||||||
|
| |
|
||||||
|
| expected `&'a ()` because of return type
|
||||||
|
|
|
||||||
|
= note: expected reference `&'a ()`
|
||||||
|
found reference `&'a u8`
|
||||||
|
|
||||||
|
error: aborting due to 2 previous errors
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0308`.
|
@ -15,3 +15,7 @@ fn main() {
|
|||||||
b
|
b
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// issue: rust-lang/rust#130858 rust-lang/rust#125655
|
||||||
|
static FOO: fn() -> bool = || -> bool { 1 };
|
||||||
|
//~^ ERROR mismatched types
|
||||||
|
@ -1,3 +1,11 @@
|
|||||||
|
error[E0308]: mismatched types
|
||||||
|
--> $DIR/closure-return-type-mismatch.rs:20:41
|
||||||
|
|
|
||||||
|
LL | static FOO: fn() -> bool = || -> bool { 1 };
|
||||||
|
| ---- ^ expected `bool`, found integer
|
||||||
|
| |
|
||||||
|
| expected `bool` because of return type
|
||||||
|
|
||||||
error[E0308]: mismatched types
|
error[E0308]: mismatched types
|
||||||
--> $DIR/closure-return-type-mismatch.rs:7:9
|
--> $DIR/closure-return-type-mismatch.rs:7:9
|
||||||
|
|
|
|
||||||
@ -19,6 +27,6 @@ LL | if false {
|
|||||||
LL | return "hello"
|
LL | return "hello"
|
||||||
| ^^^^^^^ expected `bool`, found `&str`
|
| ^^^^^^^ expected `bool`, found `&str`
|
||||||
|
|
||||||
error: aborting due to 2 previous errors
|
error: aborting due to 3 previous errors
|
||||||
|
|
||||||
For more information about this error, try `rustc --explain E0308`.
|
For more information about this error, try `rustc --explain E0308`.
|
||||||
|
11
tests/ui/coroutine/arg-count-mismatch-on-unit-input.rs
Normal file
11
tests/ui/coroutine/arg-count-mismatch-on-unit-input.rs
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#![feature(coroutines, coroutine_trait, stmt_expr_attributes)]
|
||||||
|
|
||||||
|
use std::ops::Coroutine;
|
||||||
|
|
||||||
|
fn foo() -> impl Coroutine<u8> {
|
||||||
|
//~^ ERROR type mismatch in coroutine arguments
|
||||||
|
#[coroutine]
|
||||||
|
|_: ()| {}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() { }
|
15
tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr
Normal file
15
tests/ui/coroutine/arg-count-mismatch-on-unit-input.stderr
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
error[E0631]: type mismatch in coroutine arguments
|
||||||
|
--> $DIR/arg-count-mismatch-on-unit-input.rs:5:13
|
||||||
|
|
|
||||||
|
LL | fn foo() -> impl Coroutine<u8> {
|
||||||
|
| ^^^^^^^^^^^^^^^^^^ expected due to this
|
||||||
|
...
|
||||||
|
LL | |_: ()| {}
|
||||||
|
| ------- found signature defined here
|
||||||
|
|
|
||||||
|
= note: expected coroutine signature `fn(u8) -> _`
|
||||||
|
found coroutine signature `fn(()) -> _`
|
||||||
|
|
||||||
|
error: aborting due to 1 previous error
|
||||||
|
|
||||||
|
For more information about this error, try `rustc --explain E0631`.
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
#![deny(let_underscore_drop)]
|
#![deny(let_underscore_drop)]
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = foo(); //~ ERROR non-binding let on a type that implements `Drop`
|
let _ = foo(); //~ ERROR non-binding let on a type that has a destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn from_config(_: Config) {}
|
async fn from_config(_: Config) {}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: non-binding let on a type that implements `Drop`
|
error: non-binding let on a type that has a destructor
|
||||||
--> $DIR/issue-119696-err-on-fn.rs:5:5
|
--> $DIR/issue-119696-err-on-fn.rs:5:5
|
||||||
|
|
|
|
||||||
LL | let _ = foo();
|
LL | let _ = foo();
|
||||||
|
@ -12,9 +12,9 @@ pub fn ice_cold(beverage: Tait) {
|
|||||||
// Must destructure at least one field of `Foo`
|
// Must destructure at least one field of `Foo`
|
||||||
let Foo { field } = beverage;
|
let Foo { field } = beverage;
|
||||||
// boom
|
// boom
|
||||||
_ = field; //~ ERROR non-binding let on a type that implements `Drop`
|
_ = field; //~ ERROR non-binding let on a type that has a destructor
|
||||||
|
|
||||||
let _ = field; //~ ERROR non-binding let on a type that implements `Drop`
|
let _ = field; //~ ERROR non-binding let on a type that has a destructor
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
error: non-binding let on a type that implements `Drop`
|
error: non-binding let on a type that has a destructor
|
||||||
--> $DIR/issue-119697-extra-let.rs:15:5
|
--> $DIR/issue-119697-extra-let.rs:15:5
|
||||||
|
|
|
|
||||||
LL | _ = field;
|
LL | _ = field;
|
||||||
@ -18,7 +18,7 @@ help: consider immediately dropping the value
|
|||||||
LL | drop(field);
|
LL | drop(field);
|
||||||
| ~~~~~ +
|
| ~~~~~ +
|
||||||
|
|
||||||
error: non-binding let on a type that implements `Drop`
|
error: non-binding let on a type that has a destructor
|
||||||
--> $DIR/issue-119697-extra-let.rs:17:5
|
--> $DIR/issue-119697-extra-let.rs:17:5
|
||||||
|
|
|
|
||||||
LL | let _ = field;
|
LL | let _ = field;
|
||||||
|
@ -10,7 +10,7 @@ impl Drop for NontrivialDrop {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
let _ = NontrivialDrop; //~WARNING non-binding let on a type that implements `Drop`
|
let _ = NontrivialDrop; //~WARNING non-binding let on a type that has a destructor
|
||||||
|
|
||||||
let (_, _) = (NontrivialDrop, NontrivialDrop); // This should be ignored.
|
let (_, _) = (NontrivialDrop, NontrivialDrop); // This should be ignored.
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
warning: non-binding let on a type that implements `Drop`
|
warning: non-binding let on a type that has a destructor
|
||||||
--> $DIR/let_underscore_drop.rs:13:5
|
--> $DIR/let_underscore_drop.rs:13:5
|
||||||
|
|
|
|
||||||
LL | let _ = NontrivialDrop;
|
LL | let _ = NontrivialDrop;
|
||||||
|
Loading…
Reference in New Issue
Block a user