Skip to content

Rollup of 5 pull requests #121770

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 29, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion compiler/rustc_infer/src/infer/outlives/obligations.rs
Original file line number Diff line number Diff line change
@@ -62,14 +62,17 @@
use crate::infer::outlives::components::{push_outlives_components, Component};
use crate::infer::outlives::env::RegionBoundPairs;
use crate::infer::outlives::verify::VerifyBoundCx;
use crate::infer::resolve::OpportunisticRegionResolver;
use crate::infer::{
self, GenericKind, InferCtxt, RegionObligation, SubregionOrigin, UndoLog, VerifyBound,
};
use crate::traits::{ObligationCause, ObligationCauseCode};
use rustc_data_structures::undo_log::UndoLogs;
use rustc_middle::mir::ConstraintCategory;
use rustc_middle::traits::query::NoSolution;
use rustc_middle::ty::{self, GenericArgsRef, Region, Ty, TyCtxt, TypeVisitableExt};
use rustc_middle::ty::{
self, GenericArgsRef, Region, Ty, TyCtxt, TypeFoldable as _, TypeVisitableExt,
};
use rustc_middle::ty::{GenericArgKind, PolyTypeOutlivesPredicate};
use rustc_span::DUMMY_SP;
use smallvec::smallvec;
@@ -176,6 +179,11 @@ impl<'tcx> InferCtxt<'tcx> {
.map_err(|NoSolution| (outlives, origin.clone()))?
.no_bound_vars()
.expect("started with no bound vars, should end with no bound vars");
// `TypeOutlives` is structural, so we should try to opportunistically resolve all
// region vids before processing regions, so we have a better chance to match clauses
// in our param-env.
let (sup_type, sub_region) =
(sup_type, sub_region).fold_with(&mut OpportunisticRegionResolver::new(self));

debug!(?sup_type, ?sub_region, ?origin);

10 changes: 7 additions & 3 deletions compiler/rustc_parse/src/lexer/mod.rs
Original file line number Diff line number Diff line change
@@ -501,9 +501,11 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
(kind, self.symbol_from_to(start, end))
}
rustc_lexer::LiteralKind::Float { base, empty_exponent } => {
let mut kind = token::Float;
if empty_exponent {
let span = self.mk_sp(start, self.pos);
self.dcx().emit_err(errors::EmptyExponentFloat { span });
let guar = self.dcx().emit_err(errors::EmptyExponentFloat { span });
kind = token::Err(guar);
}
let base = match base {
Base::Hexadecimal => Some("hexadecimal"),
@@ -513,9 +515,11 @@ impl<'sess, 'src> StringReader<'sess, 'src> {
};
if let Some(base) = base {
let span = self.mk_sp(start, end);
self.dcx().emit_err(errors::FloatLiteralUnsupportedBase { span, base });
let guar =
self.dcx().emit_err(errors::FloatLiteralUnsupportedBase { span, base });
kind = token::Err(guar)
}
(token::Float, self.symbol_from_to(start, end))
(kind, self.symbol_from_to(start, end))
}
}
}
8 changes: 4 additions & 4 deletions compiler/rustc_pattern_analysis/src/constructor.rs
Original file line number Diff line number Diff line change
@@ -940,7 +940,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
}
ConstructorSet::Variants { variants, non_exhaustive } => {
let mut seen_set = index::IdxSet::new_empty(variants.len());
for idx in seen.iter().map(|c| c.as_variant().unwrap()) {
for idx in seen.iter().filter_map(|c| c.as_variant()) {
seen_set.insert(idx);
}
let mut skipped_a_hidden_variant = false;
@@ -969,7 +969,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
ConstructorSet::Bool => {
let mut seen_false = false;
let mut seen_true = false;
for b in seen.iter().map(|ctor| ctor.as_bool().unwrap()) {
for b in seen.iter().filter_map(|ctor| ctor.as_bool()) {
if b {
seen_true = true;
} else {
@@ -989,7 +989,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
}
ConstructorSet::Integers { range_1, range_2 } => {
let seen_ranges: Vec<_> =
seen.iter().map(|ctor| *ctor.as_int_range().unwrap()).collect();
seen.iter().filter_map(|ctor| ctor.as_int_range()).copied().collect();
for (seen, splitted_range) in range_1.split(seen_ranges.iter().cloned()) {
match seen {
Presence::Unseen => missing.push(IntRange(splitted_range)),
@@ -1006,7 +1006,7 @@ impl<Cx: TypeCx> ConstructorSet<Cx> {
}
}
ConstructorSet::Slice { array_len, subtype_is_empty } => {
let seen_slices = seen.iter().map(|c| c.as_slice().unwrap());
let seen_slices = seen.iter().filter_map(|c| c.as_slice());
let base_slice = Slice::new(*array_len, VarLen(0, 0));
for (seen, splitted_slice) in base_slice.split(seen_slices) {
let ctor = Slice(splitted_slice);
45 changes: 35 additions & 10 deletions library/std/src/io/stdio.rs
Original file line number Diff line number Diff line change
@@ -11,8 +11,9 @@ use crate::fs::File;
use crate::io::{
self, BorrowedCursor, BufReader, IoSlice, IoSliceMut, LineWriter, Lines, SpecReadByte,
};
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::sync::atomic::{AtomicBool, Ordering};
use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantMutex, ReentrantMutexGuard};
use crate::sync::{Arc, Mutex, MutexGuard, OnceLock, ReentrantLock, ReentrantLockGuard};
use crate::sys::stdio;

type LocalStream = Arc<Mutex<Vec<u8>>>;
@@ -545,7 +546,7 @@ pub struct Stdout {
// FIXME: this should be LineWriter or BufWriter depending on the state of
// stdout (tty or not). Note that if this is not line buffered it
// should also flush-on-panic or some form of flush-on-abort.
inner: &'static ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>,
inner: &'static ReentrantLock<RefCell<LineWriter<StdoutRaw>>>,
}

/// A locked reference to the [`Stdout`] handle.
@@ -567,10 +568,10 @@ pub struct Stdout {
#[must_use = "if unused stdout will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StdoutLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
inner: ReentrantLockGuard<'a, RefCell<LineWriter<StdoutRaw>>>,
}

static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();
static STDOUT: OnceLock<ReentrantLock<RefCell<LineWriter<StdoutRaw>>>> = OnceLock::new();

/// Constructs a new handle to the standard output of the current process.
///
@@ -624,7 +625,7 @@ static STDOUT: OnceLock<ReentrantMutex<RefCell<LineWriter<StdoutRaw>>>> = OnceLo
pub fn stdout() -> Stdout {
Stdout {
inner: STDOUT
.get_or_init(|| ReentrantMutex::new(RefCell::new(LineWriter::new(stdout_raw())))),
.get_or_init(|| ReentrantLock::new(RefCell::new(LineWriter::new(stdout_raw())))),
}
}

@@ -635,7 +636,7 @@ pub fn cleanup() {
let mut initialized = false;
let stdout = STDOUT.get_or_init(|| {
initialized = true;
ReentrantMutex::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
ReentrantLock::new(RefCell::new(LineWriter::with_capacity(0, stdout_raw())))
});

if !initialized {
@@ -678,6 +679,12 @@ impl Stdout {
}
}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl UnwindSafe for Stdout {}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl RefUnwindSafe for Stdout {}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stdout {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -737,6 +744,12 @@ impl Write for &Stdout {
}
}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl UnwindSafe for StdoutLock<'_> {}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl RefUnwindSafe for StdoutLock<'_> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for StdoutLock<'_> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
@@ -786,7 +799,7 @@ impl fmt::Debug for StdoutLock<'_> {
/// standard library or via raw Windows API calls, will fail.
#[stable(feature = "rust1", since = "1.0.0")]
pub struct Stderr {
inner: &'static ReentrantMutex<RefCell<StderrRaw>>,
inner: &'static ReentrantLock<RefCell<StderrRaw>>,
}

/// A locked reference to the [`Stderr`] handle.
@@ -808,7 +821,7 @@ pub struct Stderr {
#[must_use = "if unused stderr will immediately unlock"]
#[stable(feature = "rust1", since = "1.0.0")]
pub struct StderrLock<'a> {
inner: ReentrantMutexGuard<'a, RefCell<StderrRaw>>,
inner: ReentrantLockGuard<'a, RefCell<StderrRaw>>,
}

/// Constructs a new handle to the standard error of the current process.
@@ -862,8 +875,8 @@ pub fn stderr() -> Stderr {
// Note that unlike `stdout()` we don't use `at_exit` here to register a
// destructor. Stderr is not buffered, so there's no need to run a
// destructor for flushing the buffer
static INSTANCE: ReentrantMutex<RefCell<StderrRaw>> =
ReentrantMutex::new(RefCell::new(stderr_raw()));
static INSTANCE: ReentrantLock<RefCell<StderrRaw>> =
ReentrantLock::new(RefCell::new(stderr_raw()));

Stderr { inner: &INSTANCE }
}
@@ -898,6 +911,12 @@ impl Stderr {
}
}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl UnwindSafe for Stderr {}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl RefUnwindSafe for Stderr {}

#[stable(feature = "std_debug", since = "1.16.0")]
impl fmt::Debug for Stderr {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -957,6 +976,12 @@ impl Write for &Stderr {
}
}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl UnwindSafe for StderrLock<'_> {}

#[stable(feature = "catch_unwind", since = "1.9.0")]
impl RefUnwindSafe for StderrLock<'_> {}

#[stable(feature = "rust1", since = "1.0.0")]
impl Write for StderrLock<'_> {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
5 changes: 3 additions & 2 deletions library/std/src/sync/mod.rs
Original file line number Diff line number Diff line change
@@ -184,7 +184,8 @@ pub use self::lazy_lock::LazyLock;
#[stable(feature = "once_cell", since = "1.70.0")]
pub use self::once_lock::OnceLock;

pub(crate) use self::remutex::{ReentrantMutex, ReentrantMutexGuard};
#[unstable(feature = "reentrant_lock", issue = "121440")]
pub use self::reentrant_lock::{ReentrantLock, ReentrantLockGuard};

pub mod mpsc;

@@ -196,5 +197,5 @@ mod mutex;
pub(crate) mod once;
mod once_lock;
mod poison;
mod remutex;
mod reentrant_lock;
mod rwlock;
320 changes: 320 additions & 0 deletions library/std/src/sync/reentrant_lock.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,320 @@
#[cfg(all(test, not(target_os = "emscripten")))]
mod tests;

use crate::cell::UnsafeCell;
use crate::fmt;
use crate::ops::Deref;
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
use crate::sys::locks as sys;

/// A re-entrant mutual exclusion lock
///
/// This lock will block *other* threads waiting for the lock to become
/// available. The thread which has already locked the mutex can lock it
/// multiple times without blocking, preventing a common source of deadlocks.
///
/// # Examples
///
/// Allow recursively calling a function needing synchronization from within
/// a callback (this is how [`StdoutLock`](crate::io::StdoutLock) is currently
/// implemented):
///
/// ```
/// #![feature(reentrant_lock)]
///
/// use std::cell::RefCell;
/// use std::sync::ReentrantLock;
///
/// pub struct Log {
/// data: RefCell<String>,
/// }
///
/// impl Log {
/// pub fn append(&self, msg: &str) {
/// self.data.borrow_mut().push_str(msg);
/// }
/// }
///
/// static LOG: ReentrantLock<Log> = ReentrantLock::new(Log { data: RefCell::new(String::new()) });
///
/// pub fn with_log<R>(f: impl FnOnce(&Log) -> R) -> R {
/// let log = LOG.lock();
/// f(&*log)
/// }
///
/// with_log(|log| {
/// log.append("Hello");
/// with_log(|log| log.append(" there!"));
/// });
/// ```
///
// # Implementation details
//
// The 'owner' field tracks which thread has locked the mutex.
//
// We use current_thread_unique_ptr() as the thread identifier,
// which is just the address of a thread local variable.
//
// If `owner` is set to the identifier of the current thread,
// we assume the mutex is already locked and instead of locking it again,
// we increment `lock_count`.
//
// When unlocking, we decrement `lock_count`, and only unlock the mutex when
// it reaches zero.
//
// `lock_count` is protected by the mutex and only accessed by the thread that has
// locked the mutex, so needs no synchronization.
//
// `owner` can be checked by other threads that want to see if they already
// hold the lock, so needs to be atomic. If it compares equal, we're on the
// same thread that holds the mutex and memory access can use relaxed ordering
// since we're not dealing with multiple threads. If it's not equal,
// synchronization is left to the mutex, making relaxed memory ordering for
// the `owner` field fine in all cases.
#[unstable(feature = "reentrant_lock", issue = "121440")]
pub struct ReentrantLock<T: ?Sized> {
mutex: sys::Mutex,
owner: AtomicUsize,
lock_count: UnsafeCell<u32>,
data: T,
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
unsafe impl<T: Send + ?Sized> Send for ReentrantLock<T> {}
#[unstable(feature = "reentrant_lock", issue = "121440")]
unsafe impl<T: Send + ?Sized> Sync for ReentrantLock<T> {}

// Because of the `UnsafeCell`, these traits are not implemented automatically
#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: UnwindSafe + ?Sized> UnwindSafe for ReentrantLock<T> {}
#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: RefUnwindSafe + ?Sized> RefUnwindSafe for ReentrantLock<T> {}

/// An RAII implementation of a "scoped lock" of a re-entrant lock. When this
/// structure is dropped (falls out of scope), the lock will be unlocked.
///
/// The data protected by the mutex can be accessed through this guard via its
/// [`Deref`] implementation.
///
/// This structure is created by the [`lock`](ReentrantLock::lock) method on
/// [`ReentrantLock`].
///
/// # Mutability
///
/// Unlike [`MutexGuard`](super::MutexGuard), `ReentrantLockGuard` does not
/// implement [`DerefMut`](crate::ops::DerefMut), because implementation of
/// the trait would violate Rust’s reference aliasing rules. Use interior
/// mutability (usually [`RefCell`](crate::cell::RefCell)) in order to mutate
/// the guarded data.
#[must_use = "if unused the ReentrantLock will immediately unlock"]
#[unstable(feature = "reentrant_lock", issue = "121440")]
pub struct ReentrantLockGuard<'a, T: ?Sized + 'a> {
lock: &'a ReentrantLock<T>,
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: ?Sized> !Send for ReentrantLockGuard<'_, T> {}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T> ReentrantLock<T> {
/// Creates a new re-entrant lock in an unlocked state ready for use.
///
/// # Examples
///
/// ```
/// #![feature(reentrant_lock)]
/// use std::sync::ReentrantLock;
///
/// let lock = ReentrantLock::new(0);
/// ```
pub const fn new(t: T) -> ReentrantLock<T> {
ReentrantLock {
mutex: sys::Mutex::new(),
owner: AtomicUsize::new(0),
lock_count: UnsafeCell::new(0),
data: t,
}
}

/// Consumes this lock, returning the underlying data.
///
/// # Examples
///
/// ```
/// #![feature(reentrant_lock)]
///
/// use std::sync::ReentrantLock;
///
/// let lock = ReentrantLock::new(0);
/// assert_eq!(lock.into_inner(), 0);
/// ```
pub fn into_inner(self) -> T {
self.data
}
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: ?Sized> ReentrantLock<T> {
/// Acquires the lock, blocking the current thread until it is able to do
/// so.
///
/// This function will block the caller until it is available to acquire
/// the lock. Upon returning, the thread is the only thread with the lock
/// held. When the thread calling this method already holds the lock, the
/// call succeeds without blocking.
///
/// # Examples
///
/// ```
/// #![feature(reentrant_lock)]
/// use std::cell::Cell;
/// use std::sync::{Arc, ReentrantLock};
/// use std::thread;
///
/// let lock = Arc::new(ReentrantLock::new(Cell::new(0)));
/// let c_lock = Arc::clone(&lock);
///
/// thread::spawn(move || {
/// c_lock.lock().set(10);
/// }).join().expect("thread::spawn failed");
/// assert_eq!(lock.lock().get(), 10);
/// ```
pub fn lock(&self) -> ReentrantLockGuard<'_, T> {
let this_thread = current_thread_unique_ptr();
// Safety: We only touch lock_count when we own the lock.
unsafe {
if self.owner.load(Relaxed) == this_thread {
self.increment_lock_count().expect("lock count overflow in reentrant mutex");
} else {
self.mutex.lock();
self.owner.store(this_thread, Relaxed);
debug_assert_eq!(*self.lock_count.get(), 0);
*self.lock_count.get() = 1;
}
}
ReentrantLockGuard { lock: self }
}

/// Returns a mutable reference to the underlying data.
///
/// Since this call borrows the `ReentrantLock` mutably, no actual locking
/// needs to take place -- the mutable borrow statically guarantees no locks
/// exist.
///
/// # Examples
///
/// ```
/// #![feature(reentrant_lock)]
/// use std::sync::ReentrantLock;
///
/// let mut lock = ReentrantLock::new(0);
/// *lock.get_mut() = 10;
/// assert_eq!(*lock.lock(), 10);
/// ```
pub fn get_mut(&mut self) -> &mut T {
&mut self.data
}

/// Attempts to acquire this lock.
///
/// If the lock could not be acquired at this time, then `None` is returned.
/// Otherwise, an RAII guard is returned.
///
/// This function does not block.
pub(crate) fn try_lock(&self) -> Option<ReentrantLockGuard<'_, T>> {
let this_thread = current_thread_unique_ptr();
// Safety: We only touch lock_count when we own the lock.
unsafe {
if self.owner.load(Relaxed) == this_thread {
self.increment_lock_count()?;
Some(ReentrantLockGuard { lock: self })
} else if self.mutex.try_lock() {
self.owner.store(this_thread, Relaxed);
debug_assert_eq!(*self.lock_count.get(), 0);
*self.lock_count.get() = 1;
Some(ReentrantLockGuard { lock: self })
} else {
None
}
}
}

unsafe fn increment_lock_count(&self) -> Option<()> {
*self.lock_count.get() = (*self.lock_count.get()).checked_add(1)?;
Some(())
}
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for ReentrantLock<T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut d = f.debug_struct("ReentrantLock");
match self.try_lock() {
Some(v) => d.field("data", &&*v),
None => d.field("data", &format_args!("<locked>")),
};
d.finish_non_exhaustive()
}
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: Default> Default for ReentrantLock<T> {
fn default() -> Self {
Self::new(T::default())
}
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T> From<T> for ReentrantLock<T> {
fn from(t: T) -> Self {
Self::new(t)
}
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: ?Sized> Deref for ReentrantLockGuard<'_, T> {
type Target = T;

fn deref(&self) -> &T {
&self.lock.data
}
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: fmt::Debug + ?Sized> fmt::Debug for ReentrantLockGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: fmt::Display + ?Sized> fmt::Display for ReentrantLockGuard<'_, T> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
(**self).fmt(f)
}
}

#[unstable(feature = "reentrant_lock", issue = "121440")]
impl<T: ?Sized> Drop for ReentrantLockGuard<'_, T> {
#[inline]
fn drop(&mut self) {
// Safety: We own the lock.
unsafe {
*self.lock.lock_count.get() -= 1;
if *self.lock.lock_count.get() == 0 {
self.lock.owner.store(0, Relaxed);
self.lock.mutex.unlock();
}
}
}
}

/// Get an address that is unique per running thread.
///
/// This can be used as a non-null usize-sized ID.
pub(crate) fn current_thread_unique_ptr() -> usize {
// Use a non-drop type to make sure it's still available during thread destruction.
thread_local! { static X: u8 = const { 0 } }
X.with(|x| <*const _>::addr(x))
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
use super::{ReentrantMutex, ReentrantMutexGuard};
use super::{ReentrantLock, ReentrantLockGuard};
use crate::cell::RefCell;
use crate::sync::Arc;
use crate::thread;

#[test]
fn smoke() {
let m = ReentrantMutex::new(());
let l = ReentrantLock::new(());
{
let a = m.lock();
let a = l.lock();
{
let b = m.lock();
let b = l.lock();
{
let c = m.lock();
let c = l.lock();
assert_eq!(*c, ());
}
assert_eq!(*b, ());
@@ -22,15 +22,15 @@ fn smoke() {

#[test]
fn is_mutex() {
let m = Arc::new(ReentrantMutex::new(RefCell::new(0)));
let m2 = m.clone();
let lock = m.lock();
let l = Arc::new(ReentrantLock::new(RefCell::new(0)));
let l2 = l.clone();
let lock = l.lock();
let child = thread::spawn(move || {
let lock = m2.lock();
let lock = l2.lock();
assert_eq!(*lock.borrow(), 4950);
});
for i in 0..100 {
let lock = m.lock();
let lock = l.lock();
*lock.borrow_mut() += i;
}
drop(lock);
@@ -39,20 +39,20 @@ fn is_mutex() {

#[test]
fn trylock_works() {
let m = Arc::new(ReentrantMutex::new(()));
let m2 = m.clone();
let _lock = m.try_lock();
let _lock2 = m.try_lock();
let l = Arc::new(ReentrantLock::new(()));
let l2 = l.clone();
let _lock = l.try_lock();
let _lock2 = l.try_lock();
thread::spawn(move || {
let lock = m2.try_lock();
let lock = l2.try_lock();
assert!(lock.is_none());
})
.join()
.unwrap();
let _lock3 = m.try_lock();
let _lock3 = l.try_lock();
}

pub struct Answer<'a>(pub ReentrantMutexGuard<'a, RefCell<u32>>);
pub struct Answer<'a>(pub ReentrantLockGuard<'a, RefCell<u32>>);
impl Drop for Answer<'_> {
fn drop(&mut self) {
*self.0.borrow_mut() = 42;
178 changes: 0 additions & 178 deletions library/std/src/sync/remutex.rs

This file was deleted.

1 change: 1 addition & 0 deletions src/librustdoc/html/highlight.rs
Original file line number Diff line number Diff line change
@@ -136,6 +136,7 @@ fn can_merge(class1: Option<Class>, class2: Option<Class>, text: &str) -> bool {
match (class1, class2) {
(Some(c1), Some(c2)) => c1.is_equal_to(c2),
(Some(Class::Ident(_)), None) | (None, Some(Class::Ident(_))) => true,
(Some(Class::Macro(_)), _) => false,
(Some(_), None) | (None, Some(_)) => text.trim().is_empty(),
(None, None) => true,
}
2 changes: 1 addition & 1 deletion src/librustdoc/html/highlight/fixtures/sample.html
Original file line number Diff line number Diff line change
@@ -32,7 +32,7 @@
}
}

<span class="macro">macro_rules! </span>bar {
<span class="macro">macro_rules!</span> bar {
(<span class="macro-nonterminal">$foo</span>:tt) =&gt; {};
}
</code></pre>
2 changes: 0 additions & 2 deletions src/tools/clippy/tests/ui/crashes/ice-10912.rs
Original file line number Diff line number Diff line change
@@ -2,7 +2,5 @@
//@no-rustfix
fn f2() -> impl Sized { && 3.14159265358979323846E }
//~^ ERROR: expected at least one digit in exponent
//~| ERROR: long literal lacking separators
//~| NOTE: `-D clippy::unreadable-literal` implied by `-D warnings`

fn main() {}
11 changes: 1 addition & 10 deletions src/tools/clippy/tests/ui/crashes/ice-10912.stderr
Original file line number Diff line number Diff line change
@@ -4,14 +4,5 @@ error: expected at least one digit in exponent
LL | fn f2() -> impl Sized { && 3.14159265358979323846E }
| ^^^^^^^^^^^^^^^^^^^^^^^

error: long literal lacking separators
--> tests/ui/crashes/ice-10912.rs:3:28
|
LL | fn f2() -> impl Sized { && 3.14159265358979323846E }
| ^^^^^^^^^^^^^^^^^^^^^^^ help: consider: `3.141_592_653_589_793_238_46`
|
= note: `-D clippy::unreadable-literal` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::unreadable_literal)]`

error: aborting due to 2 previous errors
error: aborting due to 1 previous error

29 changes: 29 additions & 0 deletions tests/rustdoc/source-code-highlight.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// We need this option to be enabled for the `foo` macro declaration to ensure
// that the link on the ident is not including whitespace characters.

//@ compile-flags: -Zunstable-options --generate-link-to-definition
#![crate_name = "foo"]

// @has 'src/foo/source-code-highlight.rs.html'

// @hasraw - '<a href="../../foo/macro.foo.html">foo</a>'
#[macro_export]
macro_rules! foo {
() => {}
}

// @hasraw - '<span class="macro">foo!</span>'
foo! {}

// @hasraw - '<a href="../../foo/fn.f.html">f</a>'
#[rustfmt::skip]
pub fn f () {}
// @hasraw - '<a href="../../foo/struct.Bar.html">Bar</a>'
// @hasraw - '<a href="../../foo/struct.Bar.html">Bar</a>'
// @hasraw - '<a href="{{channel}}/std/primitive.u32.html">u32</a>'
#[rustfmt::skip]
pub struct Bar ( u32 );
// @hasraw - '<a href="../../foo/enum.Foo.html">Foo</a>'
pub enum Foo {
A,
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻²
//~^ ERROR expected at least one digit in exponent
//~| ERROR unknown start of token: \u{2212}
//~| ERROR cannot subtract `{integer}` from `{float}`

fn main() {}
Original file line number Diff line number Diff line change
@@ -15,24 +15,5 @@ help: Unicode character '−' (Minus Sign) looks like '-' (Minus/Hyphen), but it
LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e-11; // m³⋅kg⁻¹⋅s⁻²
| ~

error[E0277]: cannot subtract `{integer}` from `{float}`
--> $DIR/issue-49746-unicode-confusable-in-float-literal-expt.rs:1:53
|
LL | const UNIVERSAL_GRAVITATIONAL_CONSTANT: f64 = 6.674e−11; // m³⋅kg⁻¹⋅s⁻²
| ^ no implementation for `{float} - {integer}`
|
= help: the trait `Sub<{integer}>` is not implemented for `{float}`
= help: the following other types implement trait `Sub<Rhs>`:
<isize as Sub>
<isize as Sub<&isize>>
<i8 as Sub>
<i8 as Sub<&i8>>
<i16 as Sub>
<i16 as Sub<&i16>>
<i32 as Sub>
<i32 as Sub<&i32>>
and 48 others

error: aborting due to 3 previous errors
error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0277`.
Original file line number Diff line number Diff line change
@@ -10,7 +10,7 @@ pub trait MessageListenersInterface {

impl<'a> MessageListenersInterface for MessageListeners<'a> {
fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
//~^ ERROR cannot infer an appropriate lifetime for lifetime parameter 'b in generic type due to conflicting requirements
//~^ ERROR in type `&'a MessageListeners<'_>`, reference has a longer lifetime than the data it references
self
}
}
20 changes: 4 additions & 16 deletions tests/ui/implied-bounds/impl-implied-bounds-compatibility.stderr
Original file line number Diff line number Diff line change
@@ -1,32 +1,20 @@
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter 'b in generic type due to conflicting requirements
error[E0491]: in type `&'a MessageListeners<'_>`, reference has a longer lifetime than the data it references
--> $DIR/impl-implied-bounds-compatibility.rs:12:5
|
LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
note: first, the lifetime cannot outlive the lifetime `'c` as defined here...
--> $DIR/impl-implied-bounds-compatibility.rs:12:5
|
LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
note: ...so that the method type is compatible with trait
--> $DIR/impl-implied-bounds-compatibility.rs:12:5
|
LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
= note: expected `fn(&'c MessageListeners<'_>) -> &'c MessageListeners<'c>`
found `fn(&MessageListeners<'_>) -> &'a MessageListeners<'_>`
note: but, the lifetime must be valid for the lifetime `'a` as defined here...
note: the pointer is valid for the lifetime `'a` as defined here
--> $DIR/impl-implied-bounds-compatibility.rs:11:6
|
LL | impl<'a> MessageListenersInterface for MessageListeners<'a> {
| ^^
note: ...so that the reference type `&'a MessageListeners<'_>` does not outlive the data it points at
note: but the referenced data is only valid for the lifetime `'c` as defined here
--> $DIR/impl-implied-bounds-compatibility.rs:12:5
|
LL | fn listeners<'b>(&'b self) -> &'a MessageListeners<'b> {
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0495`.
For more information about this error, try `rustc --explain E0491`.
71 changes: 51 additions & 20 deletions tests/ui/parser/float-field.rs
Original file line number Diff line number Diff line change
@@ -3,60 +3,91 @@ struct S(u8, (u8, u8));
fn main() {
let s = S(0, (0, 0));

s.1e1; //~ ERROR no field `1e1` on type `S`
s.1.; //~ ERROR unexpected token: `;`
s.1.1;
s.1.1e1; //~ ERROR no field `1e1` on type `(u8, u8)`
{ s.1e1; } //~ ERROR no field `1e1` on type `S`

{ s.1.; } //~ ERROR unexpected token: `;`

{ s.1.1; }

{ s.1.1e1; } //~ ERROR no field `1e1` on type `(u8, u8)`

{ s.1e+; } //~ ERROR unexpected token: `1e+`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+`
//~| ERROR expected at least one digit in exponent

{ s.1e-; } //~ ERROR unexpected token: `1e-`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-`
//~| ERROR expected at least one digit in exponent

{ s.1e+1; } //~ ERROR unexpected token: `1e+1`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1`

{ s.1e-1; } //~ ERROR unexpected token: `1e-1`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1`

{ s.1.1e+1; } //~ ERROR unexpected token: `1.1e+1`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1`

{ s.1.1e-1; } //~ ERROR unexpected token: `1.1e-1`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1`
s.0x1e1; //~ ERROR no field `0x1e1` on type `S`
s.0x1.; //~ ERROR no field `0x1` on type `S`
//~| ERROR hexadecimal float literal is not supported
//~| ERROR unexpected token: `;`
s.0x1.1; //~ ERROR no field `0x1` on type `S`
//~| ERROR hexadecimal float literal is not supported
s.0x1.1e1; //~ ERROR no field `0x1` on type `S`
//~| ERROR hexadecimal float literal is not supported

{ s.0x1e1; } //~ ERROR no field `0x1e1` on type `S`

{ s.0x1.; } //~ ERROR hexadecimal float literal is not supported
//~| ERROR unexpected token: `0x1.`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.`

{ s.0x1.1; } //~ ERROR hexadecimal float literal is not supported
//~| ERROR unexpected token: `0x1.1`
//~| expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1`

{ s.0x1.1e1; } //~ ERROR hexadecimal float literal is not supported
//~| ERROR unexpected token: `0x1.1e1`
//~| expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e1`

{ s.0x1e+; } //~ ERROR expected expression, found `;`

{ s.0x1e-; } //~ ERROR expected expression, found `;`
s.0x1e+1; //~ ERROR no field `0x1e` on type `S`
s.0x1e-1; //~ ERROR no field `0x1e` on type `S`

{ s.0x1e+1; } //~ ERROR no field `0x1e` on type `S`

{ s.0x1e-1; } //~ ERROR no field `0x1e` on type `S`

{ s.0x1.1e+1; } //~ ERROR unexpected token: `0x1.1e+1`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e+1`
//~| ERROR hexadecimal float literal is not supported

{ s.0x1.1e-1; } //~ ERROR unexpected token: `0x1.1e-1`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `0x1.1e-1`
//~| ERROR hexadecimal float literal is not supported
s.1e1f32; //~ ERROR no field `1e1` on type `S`
//~| ERROR suffixes on a tuple index are invalid
s.1.f32; //~ ERROR no field `f32` on type `(u8, u8)`
s.1.1f32; //~ ERROR suffixes on a tuple index are invalid
s.1.1e1f32; //~ ERROR no field `1e1` on type `(u8, u8)`
//~| ERROR suffixes on a tuple index are invalid

{ s.1e1f32; } //~ ERROR no field `1e1` on type `S`
//~| ERROR suffixes on a tuple index are invalid

{ s.1.f32; } //~ ERROR no field `f32` on type `(u8, u8)`

{ s.1.1f32; } //~ ERROR suffixes on a tuple index are invalid

{ s.1.1e1f32; } //~ ERROR no field `1e1` on type `(u8, u8)`
//~| ERROR suffixes on a tuple index are invalid

{ s.1e+f32; } //~ ERROR unexpected token: `1e+f32`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+f32`
//~| ERROR expected at least one digit in exponent

{ s.1e-f32; } //~ ERROR unexpected token: `1e-f32`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-f32`
//~| ERROR expected at least one digit in exponent

{ s.1e+1f32; } //~ ERROR unexpected token: `1e+1f32`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e+1f32`

{ s.1e-1f32; } //~ ERROR unexpected token: `1e-1f32`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1e-1f32`

{ s.1.1e+1f32; } //~ ERROR unexpected token: `1.1e+1f32`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e+1f32`

{ s.1.1e-1f32; } //~ ERROR unexpected token: `1.1e-1f32`
//~| ERROR expected one of `.`, `;`, `?`, `}`, or an operator, found `1.1e-1f32`
}
226 changes: 116 additions & 110 deletions tests/ui/parser/float-field.stderr

Large diffs are not rendered by default.