Auto merge of #100213 - matthiaskrgr:rollup-mqe7t1n, r=matthiaskrgr
Rollup of 5 pull requests Successful merges: - #100071 (deps: dedupe `annotate-snippets` crate versions) - #100127 (Remove Windows function preloading) - #100130 (Avoid pointing out `return` span if it has nothing to do with type error) - #100169 (Optimize `pointer::as_aligned_to`) - #100175 (ascii -> ASCII in code comment) Failed merges: r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
cc71eef498
24 changed files with 264 additions and 217 deletions
12
Cargo.lock
12
Cargo.lock
|
|
@ -82,12 +82,6 @@ dependencies = [
|
|||
"url 2.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d78ea013094e5ea606b1c05fe35f1dd7ea1eb1ea259908d040b25bd5ec677ee5"
|
||||
|
||||
[[package]]
|
||||
name = "annotate-snippets"
|
||||
version = "0.9.1"
|
||||
|
|
@ -3862,7 +3856,7 @@ dependencies = [
|
|||
name = "rustc_errors"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.8.0",
|
||||
"annotate-snippets",
|
||||
"atty",
|
||||
"rustc_data_structures",
|
||||
"rustc_error_messages",
|
||||
|
|
@ -4114,7 +4108,7 @@ dependencies = [
|
|||
name = "rustc_macros"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.8.0",
|
||||
"annotate-snippets",
|
||||
"fluent-bundle",
|
||||
"fluent-syntax",
|
||||
"proc-macro2",
|
||||
|
|
@ -4729,7 +4723,7 @@ dependencies = [
|
|||
name = "rustfmt-nightly"
|
||||
version = "1.5.1"
|
||||
dependencies = [
|
||||
"annotate-snippets 0.9.1",
|
||||
"annotate-snippets",
|
||||
"anyhow",
|
||||
"bytecount",
|
||||
"cargo_metadata 0.14.0",
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ rustc_lint_defs = { path = "../rustc_lint_defs" }
|
|||
unicode-width = "0.1.4"
|
||||
atty = "0.2"
|
||||
termcolor = "1.0"
|
||||
annotate-snippets = "0.8.0"
|
||||
annotate-snippets = "0.9"
|
||||
termize = "0.1.1"
|
||||
serde = { version = "1.0.125", features = ["derive"] }
|
||||
serde_json = "1.0.59"
|
||||
|
|
|
|||
|
|
@ -183,7 +183,11 @@ impl AnnotateSnippetEmitterWriter {
|
|||
annotation_type: annotation_type_for_level(*level),
|
||||
}),
|
||||
footer: vec![],
|
||||
opt: FormatOptions { color: true, anonymized_line_numbers: self.ui_testing },
|
||||
opt: FormatOptions {
|
||||
color: true,
|
||||
anonymized_line_numbers: self.ui_testing,
|
||||
margin: None,
|
||||
},
|
||||
slices: annotated_files
|
||||
.iter()
|
||||
.map(|(source, line_index, annotations)| {
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
annotate-snippets = "0.8.0"
|
||||
annotate-snippets = "0.9"
|
||||
fluent-bundle = "0.15.2"
|
||||
fluent-syntax = "0.11"
|
||||
synstructure = "0.12.1"
|
||||
|
|
|
|||
|
|
@ -1493,6 +1493,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
// type)
|
||||
(self.final_ty.unwrap_or(self.expected_ty), expression_ty)
|
||||
};
|
||||
let (expected, found) = fcx.resolve_vars_if_possible((expected, found));
|
||||
|
||||
let mut err;
|
||||
let mut unsized_return = false;
|
||||
|
|
@ -1695,9 +1696,30 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
|
|||
);
|
||||
}
|
||||
|
||||
if let (Some(sp), Some(fn_output)) = (fcx.ret_coercion_span.get(), fn_output) {
|
||||
let ret_coercion_span = fcx.ret_coercion_span.get();
|
||||
|
||||
if let Some(sp) = ret_coercion_span
|
||||
// If the closure has an explicit return type annotation, or if
|
||||
// the closure's return type has been inferred from outside
|
||||
// requirements (such as an Fn* trait bound), then a type error
|
||||
// may occur at the first return expression we see in the closure
|
||||
// (if it conflicts with the declared return type). Skip adding a
|
||||
// note in this case, since it would be incorrect.
|
||||
&& !fcx.return_type_pre_known
|
||||
{
|
||||
err.span_note(
|
||||
sp,
|
||||
&format!(
|
||||
"return type inferred to be `{}` here",
|
||||
expected
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if let (Some(sp), Some(fn_output)) = (ret_coercion_span, fn_output) {
|
||||
self.add_impl_trait_explanation(&mut err, cause, fcx, expected, sp, fn_output);
|
||||
}
|
||||
|
||||
err
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,7 +45,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
self.note_type_is_not_clone(err, expected, expr_ty, expr);
|
||||
self.note_need_for_fn_pointer(err, expected, expr_ty);
|
||||
self.note_internal_mutation_in_method(err, expr, expected, expr_ty);
|
||||
self.report_closure_inferred_return_type(err, expected);
|
||||
}
|
||||
|
||||
// Requires that the two types unify, and prints an error message if
|
||||
|
|
@ -1418,25 +1417,4 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
|
|||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Report the type inferred by the return statement.
|
||||
fn report_closure_inferred_return_type(&self, err: &mut Diagnostic, expected: Ty<'tcx>) {
|
||||
if let Some(sp) = self.ret_coercion_span.get()
|
||||
// If the closure has an explicit return type annotation, or if
|
||||
// the closure's return type has been inferred from outside
|
||||
// requirements (such as an Fn* trait bound), then a type error
|
||||
// may occur at the first return expression we see in the closure
|
||||
// (if it conflicts with the declared return type). Skip adding a
|
||||
// note in this case, since it would be incorrect.
|
||||
&& !self.return_type_pre_known
|
||||
{
|
||||
err.span_note(
|
||||
sp,
|
||||
&format!(
|
||||
"return type inferred to be `{}` here",
|
||||
self.resolve_vars_if_possible(expected)
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1336,11 +1336,8 @@ impl<T: ?Sized> *const T {
|
|||
panic!("is_aligned_to: align is not a power-of-two");
|
||||
}
|
||||
|
||||
// SAFETY: `is_power_of_two()` will return `false` for zero.
|
||||
unsafe { core::intrinsics::assume(align != 0) };
|
||||
|
||||
// Cast is needed for `T: !Sized`
|
||||
self.cast::<u8>().addr() % align == 0
|
||||
self.cast::<u8>().addr() & align - 1 == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1614,11 +1614,8 @@ impl<T: ?Sized> *mut T {
|
|||
panic!("is_aligned_to: align is not a power-of-two");
|
||||
}
|
||||
|
||||
// SAFETY: `is_power_of_two()` will return `false` for zero.
|
||||
unsafe { core::intrinsics::assume(align != 0) };
|
||||
|
||||
// Cast is needed for `T: !Sized`
|
||||
self.cast::<u8>().addr() % align == 0
|
||||
self.cast::<u8>().addr() & align - 1 == 0
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -2353,7 +2353,7 @@ impl str {
|
|||
#[inline]
|
||||
pub fn is_ascii(&self) -> bool {
|
||||
// We can treat each byte as character here: all multibyte characters
|
||||
// start with a byte that is not in the ascii range, so we will stop
|
||||
// start with a byte that is not in the ASCII range, so we will stop
|
||||
// there already.
|
||||
self.as_bytes().is_ascii()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1250,19 +1250,21 @@ compat_fn_with_fallback! {
|
|||
}
|
||||
}
|
||||
|
||||
compat_fn_optional! {
|
||||
compat_fn_with_fallback! {
|
||||
pub static SYNCH_API: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0");
|
||||
|
||||
// >= Windows 8 / Server 2012
|
||||
// https://docs.microsoft.com/en-us/windows/win32/api/synchapi/nf-synchapi-waitonaddress
|
||||
pub fn WaitOnAddress(
|
||||
Address: LPVOID,
|
||||
CompareAddress: LPVOID,
|
||||
AddressSize: SIZE_T,
|
||||
dwMilliseconds: DWORD
|
||||
) -> BOOL;
|
||||
pub fn WakeByAddressSingle(Address: LPVOID) -> ();
|
||||
#[allow(unused)]
|
||||
fn WakeByAddressSingle(Address: LPVOID) -> () {
|
||||
// This fallback is currently tightly coupled to its use in Parker::unpark.
|
||||
//
|
||||
// FIXME: If `WakeByAddressSingle` needs to be used anywhere other than
|
||||
// Parker::unpark then this fallback will be wrong and will need to be decoupled.
|
||||
crate::sys::windows::thread_parker::unpark_keyed_event(Address)
|
||||
}
|
||||
}
|
||||
pub use crate::sys::compat::WaitOnAddress;
|
||||
// Change exported name of `WakeByAddressSingle` to make the strange fallback
|
||||
// behaviour clear.
|
||||
pub use WakeByAddressSingle::call as wake_by_address_single_or_unpark_keyed_event;
|
||||
|
||||
compat_fn_with_fallback! {
|
||||
pub static NTDLL: &CStr = ansi_str!("ntdll");
|
||||
|
|
|
|||
|
|
@ -7,47 +7,17 @@
|
|||
//! `GetModuleHandle` and `GetProcAddress` to look up DLL entry points at
|
||||
//! runtime.
|
||||
//!
|
||||
//! This implementation uses a static initializer to look up the DLL entry
|
||||
//! points. The CRT (C runtime) executes static initializers before `main`
|
||||
//! is called (for binaries) and before `DllMain` is called (for DLLs).
|
||||
//! This is the ideal time to look up DLL imports, because we are guaranteed
|
||||
//! that no other threads will attempt to call these entry points. Thus,
|
||||
//! we can look up the imports and store them in `static mut` fields
|
||||
//! without any synchronization.
|
||||
//! This is implemented simply by storing a function pointer in an atomic.
|
||||
//! Loading and calling this function will have little or no overhead
|
||||
//! compared with calling any other dynamically imported function.
|
||||
//!
|
||||
//! This has an additional advantage: Because the DLL import lookup happens
|
||||
//! at module initialization, the cost of these lookups is deterministic,
|
||||
//! and is removed from the code paths that actually call the DLL imports.
|
||||
//! That is, there is no unpredictable "cache miss" that occurs when calling
|
||||
//! a DLL import. For applications that benefit from predictable delays,
|
||||
//! this is a benefit. This also eliminates the comparison-and-branch
|
||||
//! from the hot path.
|
||||
//!
|
||||
//! Currently, the standard library uses only a small number of dynamic
|
||||
//! DLL imports. If this number grows substantially, then the cost of
|
||||
//! performing all of the lookups at initialization time might become
|
||||
//! substantial.
|
||||
//!
|
||||
//! The mechanism of registering a static initializer with the CRT is
|
||||
//! documented in
|
||||
//! [CRT Initialization](https://docs.microsoft.com/en-us/cpp/c-runtime-library/crt-initialization?view=msvc-160).
|
||||
//! It works by contributing a global symbol to the `.CRT$XCU` section.
|
||||
//! The linker builds a table of all static initializer functions.
|
||||
//! The CRT startup code then iterates that table, calling each
|
||||
//! initializer function.
|
||||
//!
|
||||
//! # **WARNING!!*
|
||||
//! The environment that a static initializer function runs in is highly
|
||||
//! constrained. There are **many** restrictions on what static initializers
|
||||
//! can safely do. Static initializer functions **MUST NOT** do any of the
|
||||
//! following (this list is not comprehensive):
|
||||
//! * touch any other static field that is used by a different static
|
||||
//! initializer, because the order that static initializers run in
|
||||
//! is not defined.
|
||||
//! * call `LoadLibrary` or any other function that acquires the DLL
|
||||
//! loader lock.
|
||||
//! * call any Rust function or CRT function that touches any static
|
||||
//! (global) state.
|
||||
//! The stored function pointer starts out as an importer function which will
|
||||
//! swap itself with the real function when it's called for the first time. If
|
||||
//! the real function can't be imported then a fallback function is used in its
|
||||
//! place. While this is low cost for the happy path (where the function is
|
||||
//! already loaded) it does mean there's some overhead the first time the
|
||||
//! function is called. In the worst case, multiple threads may all end up
|
||||
//! importing the same function unnecessarily.
|
||||
|
||||
use crate::ffi::{c_void, CStr};
|
||||
use crate::ptr::NonNull;
|
||||
|
|
@ -85,39 +55,6 @@ pub(crate) const fn const_cstr_from_bytes(bytes: &'static [u8]) -> &'static CStr
|
|||
unsafe { crate::ffi::CStr::from_bytes_with_nul_unchecked(bytes) }
|
||||
}
|
||||
|
||||
#[used]
|
||||
#[link_section = ".CRT$XCU"]
|
||||
static INIT_TABLE_ENTRY: unsafe extern "C" fn() = init;
|
||||
|
||||
/// This is where the magic preloading of symbols happens.
|
||||
///
|
||||
/// Note that any functions included here will be unconditionally included in
|
||||
/// the final binary, regardless of whether or not they're actually used.
|
||||
///
|
||||
/// Therefore, this is limited to `compat_fn_optional` functions which must be
|
||||
/// preloaded and any functions which may be more time sensitive, even for the first call.
|
||||
unsafe extern "C" fn init() {
|
||||
// There is no locking here. This code is executed before main() is entered, and
|
||||
// is guaranteed to be single-threaded.
|
||||
//
|
||||
// DO NOT do anything interesting or complicated in this function! DO NOT call
|
||||
// any Rust functions or CRT functions if those functions touch any global state,
|
||||
// because this function runs during global initialization. For example, DO NOT
|
||||
// do any dynamic allocation, don't call LoadLibrary, etc.
|
||||
|
||||
if let Some(synch) = Module::new(c::SYNCH_API) {
|
||||
// These are optional and so we must manually attempt to load them
|
||||
// before they can be used.
|
||||
c::WaitOnAddress::preload(synch);
|
||||
c::WakeByAddressSingle::preload(synch);
|
||||
}
|
||||
|
||||
if let Some(kernel32) = Module::new(c::KERNEL32) {
|
||||
// Preloading this means getting a precise time will be as fast as possible.
|
||||
c::GetSystemTimePreciseAsFileTime::preload(kernel32);
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents a loaded module.
|
||||
///
|
||||
/// Note that the modules std depends on must not be unloaded.
|
||||
|
|
@ -151,7 +88,7 @@ impl Module {
|
|||
macro_rules! compat_fn_with_fallback {
|
||||
(pub static $module:ident: &CStr = $name:expr; $(
|
||||
$(#[$meta:meta])*
|
||||
pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $fallback_body:block
|
||||
$vis:vis fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $fallback_body:block
|
||||
)*) => (
|
||||
pub static $module: &CStr = $name;
|
||||
$(
|
||||
|
|
@ -196,11 +133,6 @@ macro_rules! compat_fn_with_fallback {
|
|||
$fallback_body
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(in crate::sys) fn preload(module: Module) {
|
||||
load_from_module(Some(module));
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn call($($argname: $argtype),*) -> $rettype {
|
||||
let func: F = mem::transmute(PTR.load(Ordering::Relaxed));
|
||||
|
|
@ -208,66 +140,65 @@ macro_rules! compat_fn_with_fallback {
|
|||
}
|
||||
}
|
||||
$(#[$meta])*
|
||||
pub use $symbol::call as $symbol;
|
||||
$vis use $symbol::call as $symbol;
|
||||
)*)
|
||||
}
|
||||
|
||||
/// A function that either exists or doesn't.
|
||||
/// Optionally load `WaitOnAddress`.
|
||||
/// Unlike the dynamic loading described above, this does not have a fallback.
|
||||
///
|
||||
/// NOTE: Optional functions must be preloaded in the `init` function above, or they will always be None.
|
||||
macro_rules! compat_fn_optional {
|
||||
(pub static $module:ident: &CStr = $name:expr; $(
|
||||
$(#[$meta:meta])*
|
||||
pub fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty;
|
||||
)*) => (
|
||||
pub static $module: &CStr = $name;
|
||||
$(
|
||||
$(#[$meta])*
|
||||
pub mod $symbol {
|
||||
#[allow(unused_imports)]
|
||||
use super::*;
|
||||
use crate::mem;
|
||||
use crate::sync::atomic::{AtomicPtr, Ordering};
|
||||
use crate::sys::compat::Module;
|
||||
use crate::ptr::{self, NonNull};
|
||||
/// This is rexported from sys::c. You should prefer to import
|
||||
/// from there in case this changes again in the future.
|
||||
pub mod WaitOnAddress {
|
||||
use super::*;
|
||||
use crate::mem;
|
||||
use crate::ptr;
|
||||
use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
|
||||
use crate::sys::c;
|
||||
|
||||
type F = unsafe extern "system" fn($($argtype),*) -> $rettype;
|
||||
static MODULE_NAME: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0");
|
||||
static SYMBOL_NAME: &CStr = ansi_str!("WaitOnAddress");
|
||||
|
||||
/// `PTR` will either be `null()` or set to the loaded function.
|
||||
static PTR: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
|
||||
// WaitOnAddress function signature.
|
||||
type F = unsafe extern "system" fn(
|
||||
Address: c::LPVOID,
|
||||
CompareAddress: c::LPVOID,
|
||||
AddressSize: c::SIZE_T,
|
||||
dwMilliseconds: c::DWORD,
|
||||
);
|
||||
|
||||
/// Only allow access to the function if it has loaded successfully.
|
||||
#[inline(always)]
|
||||
#[cfg(not(miri))]
|
||||
pub fn option() -> Option<F> {
|
||||
unsafe {
|
||||
NonNull::new(PTR.load(Ordering::Relaxed)).map(|f| mem::transmute(f))
|
||||
}
|
||||
}
|
||||
|
||||
// Miri does not understand the way we do preloading
|
||||
// therefore load the function here instead.
|
||||
#[cfg(miri)]
|
||||
pub fn option() -> Option<F> {
|
||||
let mut func = NonNull::new(PTR.load(Ordering::Relaxed));
|
||||
if func.is_none() {
|
||||
unsafe { Module::new($module).map(preload) };
|
||||
func = NonNull::new(PTR.load(Ordering::Relaxed));
|
||||
}
|
||||
unsafe {
|
||||
func.map(|f| mem::transmute(f))
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
pub(in crate::sys) fn preload(module: Module) {
|
||||
unsafe {
|
||||
static SYMBOL_NAME: &CStr = ansi_str!(sym $symbol);
|
||||
if let Some(f) = module.proc_address(SYMBOL_NAME) {
|
||||
PTR.store(f.as_ptr(), Ordering::Relaxed);
|
||||
}
|
||||
}
|
||||
// A place to store the loaded function atomically.
|
||||
static WAIT_ON_ADDRESS: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
|
||||
|
||||
// We can skip trying to load again if we already tried.
|
||||
static LOAD_MODULE: AtomicBool = AtomicBool::new(true);
|
||||
|
||||
#[inline(always)]
|
||||
pub fn option() -> Option<F> {
|
||||
let f = WAIT_ON_ADDRESS.load(Ordering::Acquire);
|
||||
if !f.is_null() { Some(unsafe { mem::transmute(f) }) } else { try_load() }
|
||||
}
|
||||
|
||||
#[cold]
|
||||
fn try_load() -> Option<F> {
|
||||
if LOAD_MODULE.load(Ordering::Acquire) {
|
||||
// load the module
|
||||
let mut wait_on_address = None;
|
||||
if let Some(func) = try_load_inner() {
|
||||
WAIT_ON_ADDRESS.store(func.as_ptr(), Ordering::Release);
|
||||
wait_on_address = Some(unsafe { mem::transmute(func) });
|
||||
}
|
||||
// Don't try to load the module again even if loading failed.
|
||||
LOAD_MODULE.store(false, Ordering::Release);
|
||||
wait_on_address
|
||||
} else {
|
||||
None
|
||||
}
|
||||
)*)
|
||||
}
|
||||
|
||||
// In the future this could be a `try` block but until then I think it's a
|
||||
// little bit cleaner as a separate function.
|
||||
fn try_load_inner() -> Option<NonNull<c_void>> {
|
||||
unsafe { Module::new(MODULE_NAME)?.proc_address(SYMBOL_NAME) }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -197,21 +197,9 @@ impl Parker {
|
|||
// purpose, to make sure every unpark() has a release-acquire ordering
|
||||
// with park().
|
||||
if self.state.swap(NOTIFIED, Release) == PARKED {
|
||||
if let Some(wake_by_address_single) = c::WakeByAddressSingle::option() {
|
||||
unsafe {
|
||||
wake_by_address_single(self.ptr());
|
||||
}
|
||||
} else {
|
||||
// If we run NtReleaseKeyedEvent before the waiting thread runs
|
||||
// NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up.
|
||||
// If the waiting thread wakes up before we run NtReleaseKeyedEvent
|
||||
// (e.g. due to a timeout), this blocks until we do wake up a thread.
|
||||
// To prevent this thread from blocking indefinitely in that case,
|
||||
// park_impl() will, after seeing the state set to NOTIFIED after
|
||||
// waking up, call NtWaitForKeyedEvent again to unblock us.
|
||||
unsafe {
|
||||
c::NtReleaseKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut());
|
||||
}
|
||||
unsafe {
|
||||
// This calls either WakeByAddressSingle or unpark_keyed_event (see below).
|
||||
c::wake_by_address_single_or_unpark_keyed_event(self.ptr());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -221,6 +209,19 @@ impl Parker {
|
|||
}
|
||||
}
|
||||
|
||||
// This function signature makes it compatible with c::WakeByAddressSingle
|
||||
// so that it can be used as a fallback for that function.
|
||||
pub unsafe extern "C" fn unpark_keyed_event(address: c::LPVOID) {
|
||||
// If we run NtReleaseKeyedEvent before the waiting thread runs
|
||||
// NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up.
|
||||
// If the waiting thread wakes up before we run NtReleaseKeyedEvent
|
||||
// (e.g. due to a timeout), this blocks until we do wake up a thread.
|
||||
// To prevent this thread from blocking indefinitely in that case,
|
||||
// park_impl() will, after seeing the state set to NOTIFIED after
|
||||
// waking up, call NtWaitForKeyedEvent again to unblock us.
|
||||
c::NtReleaseKeyedEvent(keyed_event_handle(), address, 0, ptr::null_mut());
|
||||
}
|
||||
|
||||
fn keyed_event_handle() -> c::HANDLE {
|
||||
const INVALID: c::HANDLE = ptr::invalid_mut(!0);
|
||||
static HANDLE: AtomicPtr<libc::c_void> = AtomicPtr::new(INVALID);
|
||||
|
|
|
|||
|
|
@ -6,11 +6,6 @@ LL | Foo(())
|
|||
| |
|
||||
| arguments to this struct are incorrect
|
||||
|
|
||||
note: return type inferred to be `{integer}` here
|
||||
--> $DIR/issue-84128.rs:10:20
|
||||
|
|
||||
LL | return Foo(0);
|
||||
| ^^^^^^
|
||||
note: tuple struct defined here
|
||||
--> $DIR/issue-84128.rs:5:8
|
||||
|
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@ LL | let x = if true { 10i32 } else { 10u32 };
|
|||
| ----- ^^^^^ expected `i32`, found `u32`
|
||||
| |
|
||||
| expected because of this
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | let x = if true { 10i32 } else { 10i32 };
|
||||
| ~~~
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,11 @@ LL | | 2u32
|
|||
| | ^^^^ expected `i32`, found `u32`
|
||||
LL | | };
|
||||
| |_____- `if` and `else` have incompatible types
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | 2i32
|
||||
| ~~~
|
||||
|
||||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/if-else-type-mismatch.rs:8:38
|
||||
|
|
@ -18,6 +23,11 @@ LL | let _ = if true { 42i32 } else { 42u32 };
|
|||
| ----- ^^^^^ expected `i32`, found `u32`
|
||||
| |
|
||||
| expected because of this
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | let _ = if true { 42i32 } else { 42i32 };
|
||||
| ~~~
|
||||
|
||||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/if-else-type-mismatch.rs:13:9
|
||||
|
|
|
|||
|
|
@ -11,6 +11,12 @@ note: return type inferred to be `Result<{integer}, _>` here
|
|||
|
|
||||
LL | return Ok(6);
|
||||
| ^^^^^
|
||||
help: try wrapping the expression in a variant of `Result`
|
||||
|
|
||||
LL | Ok(5)
|
||||
| +++ +
|
||||
LL | Err(5)
|
||||
| ++++ +
|
||||
|
||||
error[E0271]: type mismatch resolving `<[generator@$DIR/type-mismatch-signature-deduction.rs:7:5: 7:7] as Generator>::Return == i32`
|
||||
--> $DIR/type-mismatch-signature-deduction.rs:5:13
|
||||
|
|
|
|||
|
|
@ -12,10 +12,15 @@ error[E0308]: mismatched types
|
|||
--> $DIR/equality.rs:15:5
|
||||
|
|
||||
LL | fn two(x: bool) -> impl Foo {
|
||||
| -------- expected `_` because of return type
|
||||
| -------- expected `i32` because of return type
|
||||
...
|
||||
LL | 0_u32
|
||||
| ^^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | 0_i32
|
||||
| ~~~
|
||||
|
||||
error[E0277]: cannot add `impl Foo` to `u32`
|
||||
--> $DIR/equality.rs:24:11
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:36:5
|
||||
|
|
||||
LL | fn can() -> impl NotObjectSafe {
|
||||
| ------------------ expected `_` because of return type
|
||||
| ------------------ expected `A` because of return type
|
||||
...
|
||||
LL | B
|
||||
| ^ expected struct `A`, found struct `B`
|
||||
|
|
@ -11,7 +11,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/object-unsafe-trait-in-return-position-impl-trait.rs:43:5
|
||||
|
|
||||
LL | fn cat() -> impl ObjectSafe {
|
||||
| --------------- expected `_` because of return type
|
||||
| --------------- expected `A` because of return type
|
||||
...
|
||||
LL | B
|
||||
| ^ expected struct `A`, found struct `B`
|
||||
|
|
|
|||
|
|
@ -2,28 +2,43 @@ error[E0308]: mismatched types
|
|||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:5:5
|
||||
|
|
||||
LL | fn foo() -> impl std::fmt::Display {
|
||||
| ---------------------- expected `_` because of return type
|
||||
| ---------------------- expected `i32` because of return type
|
||||
...
|
||||
LL | 1u32
|
||||
| ^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | 1i32
|
||||
| ~~~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:12:16
|
||||
|
|
||||
LL | fn bar() -> impl std::fmt::Display {
|
||||
| ---------------------- expected `_` because of return type
|
||||
| ---------------------- expected `i32` because of return type
|
||||
...
|
||||
LL | return 1u32;
|
||||
| ^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | return 1i32;
|
||||
| ~~~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:20:9
|
||||
|
|
||||
LL | fn baz() -> impl std::fmt::Display {
|
||||
| ---------------------- expected `_` because of return type
|
||||
| ---------------------- expected `i32` because of return type
|
||||
...
|
||||
LL | 1u32
|
||||
| ^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
||||
|
|
||||
LL | }.try_into().unwrap()
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:28:9
|
||||
|
|
@ -36,36 +51,56 @@ LL | | 1u32
|
|||
| | ^^^^ expected `i32`, found `u32`
|
||||
LL | | }
|
||||
| |_____- `if` and `else` have incompatible types
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | 1i32
|
||||
| ~~~
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:35:14
|
||||
|
|
||||
LL | fn bat() -> impl std::fmt::Display {
|
||||
| ---------------------- expected `_` because of return type
|
||||
| ---------------------- expected `i32` because of return type
|
||||
...
|
||||
LL | _ => 1u32,
|
||||
| ^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
||||
|
|
||||
LL | }.try_into().unwrap()
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:40:5
|
||||
|
|
||||
LL | fn can() -> impl std::fmt::Display {
|
||||
| ---------------------- expected `_` because of return type
|
||||
| ---------------------- expected `i32` because of return type
|
||||
LL | / match 13 {
|
||||
LL | | 0 => return 0i32,
|
||||
LL | | 1 => 1u32,
|
||||
LL | | _ => 2u32,
|
||||
LL | | }
|
||||
| |_____^ expected `i32`, found `u32`
|
||||
|
|
||||
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
||||
|
|
||||
LL | }.try_into().unwrap()
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:53:13
|
||||
|
|
||||
LL | fn cat() -> impl std::fmt::Display {
|
||||
| ---------------------- expected `_` because of return type
|
||||
| ---------------------- expected `i32` because of return type
|
||||
...
|
||||
LL | 1u32
|
||||
| ^^^^ expected `i32`, found `u32`
|
||||
|
|
||||
help: you can convert a `u32` to an `i32` and panic if the converted value doesn't fit
|
||||
|
|
||||
LL | }.try_into().unwrap()
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0308]: `match` arms have incompatible types
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:61:14
|
||||
|
|
@ -78,6 +113,11 @@ LL | | 1 => 1u32,
|
|||
LL | | _ => 2u32,
|
||||
LL | | }
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | 1 => 1i32,
|
||||
| ~~~
|
||||
|
||||
error[E0308]: `if` and `else` have incompatible types
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:97:9
|
||||
|
|
@ -90,6 +130,11 @@ LL | | 1u32
|
|||
| | ^^^^ expected `i32`, found `u32`
|
||||
LL | | }
|
||||
| |_____- `if` and `else` have incompatible types
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | 1i32
|
||||
| ~~~
|
||||
|
||||
error[E0746]: return type cannot have an unboxed trait object
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:66:13
|
||||
|
|
@ -125,6 +170,11 @@ LL | | 1 => 1u32,
|
|||
LL | | _ => 2u32,
|
||||
LL | | }
|
||||
| |_____- `match` arms have incompatible types
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | 1 => 1i32,
|
||||
| ~~~
|
||||
|
||||
error[E0746]: return type cannot have an unboxed trait object
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:77:13
|
||||
|
|
@ -164,6 +214,11 @@ LL | | 1u32
|
|||
| | ^^^^ expected `i32`, found `u32`
|
||||
LL | | }
|
||||
| |_____- `if` and `else` have incompatible types
|
||||
|
|
||||
help: change the type of the numeric literal from `u32` to `i32`
|
||||
|
|
||||
LL | 1i32
|
||||
| ~~~
|
||||
|
||||
error[E0746]: return type cannot have an unboxed trait object
|
||||
--> $DIR/point-to-type-err-cause-on-impl-trait-return.rs:85:13
|
||||
|
|
|
|||
18
src/test/ui/mismatched_types/dont-point-return-on-E0308.rs
Normal file
18
src/test/ui/mismatched_types/dont-point-return-on-E0308.rs
Normal file
|
|
@ -0,0 +1,18 @@
|
|||
// edition:2021
|
||||
|
||||
async fn f(_: &()) {}
|
||||
//~^ NOTE function defined here
|
||||
//~| NOTE
|
||||
// Second note is the span of the underlined argument, I think...
|
||||
|
||||
fn main() {
|
||||
(|| async {
|
||||
Err::<(), ()>(())?;
|
||||
f(());
|
||||
//~^ ERROR mismatched types
|
||||
//~| NOTE arguments to this function are incorrect
|
||||
//~| NOTE expected `&()`, found `()`
|
||||
//~| HELP consider borrowing here
|
||||
Ok::<(), ()>(())
|
||||
})();
|
||||
}
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
error[E0308]: mismatched types
|
||||
--> $DIR/dont-point-return-on-E0308.rs:11:11
|
||||
|
|
||||
LL | f(());
|
||||
| - ^^
|
||||
| | |
|
||||
| | expected `&()`, found `()`
|
||||
| | help: consider borrowing here: `&()`
|
||||
| arguments to this function are incorrect
|
||||
|
|
||||
note: function defined here
|
||||
--> $DIR/dont-point-return-on-E0308.rs:3:10
|
||||
|
|
||||
LL | async fn f(_: &()) {}
|
||||
| ^ ------
|
||||
|
||||
error: aborting due to previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
||||
|
|
@ -3,6 +3,11 @@ error[E0308]: mismatched types
|
|||
|
|
||||
LL | length = { foo(&length) };
|
||||
| ^^^^^^^^^^^^ expected `u32`, found `i32`
|
||||
|
|
||||
help: you can convert an `i32` to a `u32` and panic if the converted value doesn't fit
|
||||
|
|
||||
LL | length = { foo(&length).try_into().unwrap() };
|
||||
| ++++++++++++++++++++
|
||||
|
||||
error[E0308]: mismatched types
|
||||
--> $DIR/issue-84976.rs:17:14
|
||||
|
|
|
|||
|
|
@ -23,6 +23,9 @@ LL | std::intrinsics::unlikely,
|
|||
|
|
||||
= note: expected fn item `extern "rust-intrinsic" fn(_) -> _ {likely}`
|
||||
found fn item `extern "rust-intrinsic" fn(_) -> _ {unlikely}`
|
||||
= note: different `fn` items always have unique types, even if their signatures are the same
|
||||
= help: change the expected type to be function pointer `extern "rust-intrinsic" fn(bool) -> bool`
|
||||
= help: if the expected type is due to type inference, cast the expected `fn` to a function pointer: `likely as extern "rust-intrinsic" fn(bool) -> bool`
|
||||
|
||||
error: aborting due to 3 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ error[E0308]: mismatched types
|
|||
--> $DIR/issue-74280.rs:9:5
|
||||
|
|
||||
LL | fn test() -> Test {
|
||||
| ---- expected `_` because of return type
|
||||
| ---- expected `()` because of return type
|
||||
LL | let y = || -> Test { () };
|
||||
LL | 7
|
||||
| ^ expected `()`, found integer
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue