Skip to content

Commit

Permalink
Auto merge of #107071 - Mark-Simulacrum:beta-next, r=Mark-Simulacrum
Browse files Browse the repository at this point in the history
[beta] backport rollup

* Revert "Make nested RPITIT inherit the parent opaque's generics." #106759
*  Fix mpsc::SyncSender spinning behavior #106701
*  rustdoc: fix outdated lint section of the book #106605
*  Do not filter substs in remap_generic_params_to_declaration_params. #106503
*  Correct detection of elided lifetimes in impl-trait. #106501
*  Bump rust-installer #106196
*  Don't panic on stable since miri is not available there #105901
  • Loading branch information
bors committed Jan 20, 2023
2 parents 7a9ae0c + 8669f7e commit b7a6d74
Show file tree
Hide file tree
Showing 18 changed files with 127 additions and 71 deletions.
2 changes: 1 addition & 1 deletion compiler/rustc_borrowck/src/region_infer/opaque_types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,7 @@ impl<'tcx> InferCtxtExt<'tcx> for InferCtxt<'tcx> {
}

let definition_ty = instantiated_ty
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false, origin)
.remap_generic_params_to_declaration_params(opaque_type_key, self.tcx, false)
.ty;

if !check_opaque_type_parameter_valid(
Expand Down
16 changes: 15 additions & 1 deletion compiler/rustc_hir_analysis/src/collect/generics_of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use hir::{
GenericParamKind, HirId, Node,
};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::DefId;
use rustc_middle::ty::{self, TyCtxt};
use rustc_session::lint;
Expand Down Expand Up @@ -142,7 +143,20 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: DefId) -> ty::Generics {
Some(tcx.typeck_root_def_id(def_id))
}
Node::Item(item) => match item.kind {
ItemKind::OpaqueTy(hir::OpaqueTy { .. }) => {
ItemKind::OpaqueTy(hir::OpaqueTy {
origin:
hir::OpaqueTyOrigin::FnReturn(fn_def_id) | hir::OpaqueTyOrigin::AsyncFn(fn_def_id),
in_trait,
..
}) => {
if in_trait {
assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn))
} else {
assert!(matches!(tcx.def_kind(fn_def_id), DefKind::AssocFn | DefKind::Fn))
}
Some(fn_def_id.to_def_id())
}
ItemKind::OpaqueTy(hir::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias, .. }) => {
let parent_id = tcx.hir().get_parent_item(hir_id);
assert_ne!(parent_id, hir::CRATE_OWNER_ID);
debug!("generics_of: parent of opaque ty {:?} is {:?}", def_id, parent_id);
Expand Down
6 changes: 4 additions & 2 deletions compiler/rustc_hir_analysis/src/collect/lifetimes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1195,8 +1195,10 @@ impl<'a, 'tcx> LifetimeContext<'a, 'tcx> {
// Fresh lifetimes in APIT used to be allowed in async fns and forbidden in
// regular fns.
if let Some(hir::PredicateOrigin::ImplTrait) = where_bound_origin
&& let hir::LifetimeName::Param(_) = lifetime_ref.res
&& lifetime_ref.is_anonymous()
&& let hir::LifetimeName::Param(param_id) = lifetime_ref.res
&& let Some(generics) = self.tcx.hir().get_generics(self.tcx.local_parent(param_id))
&& let Some(param) = generics.params.iter().find(|p| p.def_id == param_id)
&& param.is_elided_lifetime()
&& let hir::IsAsync::NotAsync = self.tcx.asyncness(lifetime_ref.hir_id.owner.def_id)
&& !self.tcx.features().anonymous_lifetime_in_impl_trait
{
Expand Down
1 change: 0 additions & 1 deletion compiler/rustc_hir_typeck/src/writeback.rs
Original file line number Diff line number Diff line change
Expand Up @@ -565,7 +565,6 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
opaque_type_key,
self.fcx.infcx.tcx,
true,
decl.origin,
);

self.typeck_results.concrete_opaque_types.insert(opaque_type_key.def_id, hidden_type);
Expand Down
27 changes: 1 addition & 26 deletions compiler/rustc_middle/src/ty/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ use crate::ty::util::Discr;
pub use adt::*;
pub use assoc::*;
pub use generics::*;
use hir::OpaqueTyOrigin;
use rustc_ast as ast;
use rustc_ast::node_id::NodeMap;
use rustc_attr as attr;
Expand Down Expand Up @@ -1287,7 +1286,6 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
tcx: TyCtxt<'tcx>,
// typeck errors have subpar spans for opaque types, so delay error reporting until borrowck.
ignore_errors: bool,
origin: OpaqueTyOrigin,
) -> Self {
let OpaqueTypeKey { def_id, substs } = opaque_type_key;

Expand All @@ -1303,30 +1301,7 @@ impl<'tcx> OpaqueHiddenType<'tcx> {
// This zip may have several times the same lifetime in `substs` paired with a different
// lifetime from `id_substs`. Simply `collect`ing the iterator is the correct behaviour:
// it will pick the last one, which is the one we introduced in the impl-trait desugaring.
let map = substs.iter().zip(id_substs);

let map: FxHashMap<GenericArg<'tcx>, GenericArg<'tcx>> = match origin {
// HACK: The HIR lowering for async fn does not generate
// any `+ Captures<'x>` bounds for the `impl Future<...>`, so all async fns with lifetimes
// would now fail to compile. We should probably just make hir lowering fill this in properly.
OpaqueTyOrigin::AsyncFn(_) => map.collect(),
OpaqueTyOrigin::FnReturn(_) | OpaqueTyOrigin::TyAlias => {
// Opaque types may only use regions that are bound. So for
// ```rust
// type Foo<'a, 'b, 'c> = impl Trait<'a> + 'b;
// ```
// we may not use `'c` in the hidden type.
let variances = tcx.variances_of(def_id);
debug!(?variances);

map.filter(|(_, v)| {
let ty::GenericArgKind::Lifetime(lt) = v.unpack() else { return true };
let ty::ReEarlyBound(ebr) = lt.kind() else { bug!() };
variances[ebr.index as usize] == ty::Variance::Invariant
})
.collect()
}
};
let map = substs.iter().zip(id_substs).collect();
debug!("map = {:#?}", map);

// Convert the type from the function into a type valid outside
Expand Down
14 changes: 7 additions & 7 deletions library/std/src/sync/mpmc/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ impl<T> Channel<T> {
return true;
}
Err(_) => {
backoff.spin();
backoff.spin_light();
tail = self.tail.load(Ordering::Relaxed);
}
}
Expand All @@ -182,11 +182,11 @@ impl<T> Channel<T> {
return false;
}

backoff.spin();
backoff.spin_light();
tail = self.tail.load(Ordering::Relaxed);
} else {
// Snooze because we need to wait for the stamp to get updated.
backoff.snooze();
backoff.spin_heavy();
tail = self.tail.load(Ordering::Relaxed);
}
}
Expand Down Expand Up @@ -251,7 +251,7 @@ impl<T> Channel<T> {
return true;
}
Err(_) => {
backoff.spin();
backoff.spin_light();
head = self.head.load(Ordering::Relaxed);
}
}
Expand All @@ -273,11 +273,11 @@ impl<T> Channel<T> {
}
}

backoff.spin();
backoff.spin_light();
head = self.head.load(Ordering::Relaxed);
} else {
// Snooze because we need to wait for the stamp to get updated.
backoff.snooze();
backoff.spin_heavy();
head = self.head.load(Ordering::Relaxed);
}
}
Expand Down Expand Up @@ -330,7 +330,7 @@ impl<T> Channel<T> {
if backoff.is_completed() {
break;
} else {
backoff.spin();
backoff.spin_light();
}
}

Expand Down
16 changes: 8 additions & 8 deletions library/std/src/sync/mpmc/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ impl<T> Slot<T> {
fn wait_write(&self) {
let backoff = Backoff::new();
while self.state.load(Ordering::Acquire) & WRITE == 0 {
backoff.snooze();
backoff.spin_heavy();
}
}
}
Expand Down Expand Up @@ -82,7 +82,7 @@ impl<T> Block<T> {
if !next.is_null() {
return next;
}
backoff.snooze();
backoff.spin_heavy();
}
}

Expand Down Expand Up @@ -191,7 +191,7 @@ impl<T> Channel<T> {

// If we reached the end of the block, wait until the next one is installed.
if offset == BLOCK_CAP {
backoff.snooze();
backoff.spin_heavy();
tail = self.tail.index.load(Ordering::Acquire);
block = self.tail.block.load(Ordering::Acquire);
continue;
Expand Down Expand Up @@ -247,7 +247,7 @@ impl<T> Channel<T> {
return true;
},
Err(_) => {
backoff.spin();
backoff.spin_light();
tail = self.tail.index.load(Ordering::Acquire);
block = self.tail.block.load(Ordering::Acquire);
}
Expand Down Expand Up @@ -286,7 +286,7 @@ impl<T> Channel<T> {

// If we reached the end of the block, wait until the next one is installed.
if offset == BLOCK_CAP {
backoff.snooze();
backoff.spin_heavy();
head = self.head.index.load(Ordering::Acquire);
block = self.head.block.load(Ordering::Acquire);
continue;
Expand Down Expand Up @@ -320,7 +320,7 @@ impl<T> Channel<T> {
// The block can be null here only if the first message is being sent into the channel.
// In that case, just wait until it gets initialized.
if block.is_null() {
backoff.snooze();
backoff.spin_heavy();
head = self.head.index.load(Ordering::Acquire);
block = self.head.block.load(Ordering::Acquire);
continue;
Expand Down Expand Up @@ -351,7 +351,7 @@ impl<T> Channel<T> {
return true;
},
Err(_) => {
backoff.spin();
backoff.spin_light();
head = self.head.index.load(Ordering::Acquire);
block = self.head.block.load(Ordering::Acquire);
}
Expand Down Expand Up @@ -542,7 +542,7 @@ impl<T> Channel<T> {
// New updates to tail will be rejected by MARK_BIT and aborted unless it's
// at boundary. We need to wait for the updates take affect otherwise there
// can be memory leaks.
backoff.snooze();
backoff.spin_heavy();
tail = self.tail.index.load(Ordering::Acquire);
}

Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sync/mpmc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ mod zero;
use crate::fmt;
use crate::panic::{RefUnwindSafe, UnwindSafe};
use crate::time::{Duration, Instant};
use error::*;
pub use error::*;

/// Creates a channel of unbounded capacity.
///
Expand Down
31 changes: 15 additions & 16 deletions library/std/src/sync/mpmc/utils.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,8 @@ impl<T> DerefMut for CachePadded<T> {
}

const SPIN_LIMIT: u32 = 6;
const YIELD_LIMIT: u32 = 10;

/// Performs exponential backoff in spin loops.
/// Performs quadratic backoff in spin loops.
pub struct Backoff {
step: Cell<u32>,
}
Expand All @@ -104,25 +103,27 @@ impl Backoff {
Backoff { step: Cell::new(0) }
}

/// Backs off in a lock-free loop.
/// Backs off using lightweight spinning.
///
/// This method should be used when we need to retry an operation because another thread made
/// progress.
/// This method should be used for:
/// - Retrying an operation because another thread made progress. i.e. on CAS failure.
/// - Waiting for an operation to complete by spinning optimistically for a few iterations
/// before falling back to parking the thread (see `Backoff::is_completed`).
#[inline]
pub fn spin(&self) {
pub fn spin_light(&self) {
let step = self.step.get().min(SPIN_LIMIT);
for _ in 0..step.pow(2) {
crate::hint::spin_loop();
}

if self.step.get() <= SPIN_LIMIT {
self.step.set(self.step.get() + 1);
}
self.step.set(self.step.get() + 1);
}

/// Backs off in a blocking loop.
/// Backs off using heavyweight spinning.
///
/// This method should be used in blocking loops where parking the thread is not an option.
#[inline]
pub fn snooze(&self) {
pub fn spin_heavy(&self) {
if self.step.get() <= SPIN_LIMIT {
for _ in 0..self.step.get().pow(2) {
crate::hint::spin_loop()
Expand All @@ -131,14 +132,12 @@ impl Backoff {
crate::thread::yield_now();
}

if self.step.get() <= YIELD_LIMIT {
self.step.set(self.step.get() + 1);
}
self.step.set(self.step.get() + 1);
}

/// Returns `true` if exponential backoff has completed and blocking the thread is advised.
/// Returns `true` if quadratic backoff has completed and parking the thread is advised.
#[inline]
pub fn is_completed(&self) -> bool {
self.step.get() > YIELD_LIMIT
self.step.get() > SPIN_LIMIT
}
}
2 changes: 1 addition & 1 deletion library/std/src/sync/mpmc/zero.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ impl<T> Packet<T> {
fn wait_ready(&self) {
let backoff = Backoff::new();
while !self.ready.load(Ordering::Acquire) {
backoff.snooze();
backoff.spin_heavy();
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions library/std/src/sync/mpsc/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,15 @@ impl<T> SyncSender<T> {
pub fn try_send(&self, t: T) -> Result<(), TrySendError<T>> {
self.inner.try_send(t)
}

// Attempts to send for a value on this receiver, returning an error if the
// corresponding channel has hung up, or if it waits more than `timeout`.
//
// This method is currently private and only used for tests.
#[allow(unused)]
fn send_timeout(&self, t: T, timeout: Duration) -> Result<(), mpmc::SendTimeoutError<T>> {
self.inner.send_timeout(t, timeout)
}
}

#[stable(feature = "rust1", since = "1.0.0")]
Expand Down
8 changes: 8 additions & 0 deletions library/std/src/sync/mpsc/sync_tests.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use super::*;
use crate::env;
use crate::sync::mpmc::SendTimeoutError;
use crate::thread;
use crate::time::Duration;

Expand Down Expand Up @@ -41,6 +42,13 @@ fn recv_timeout() {
assert_eq!(rx.recv_timeout(Duration::from_millis(1)), Ok(1));
}

#[test]
fn send_timeout() {
let (tx, _rx) = sync_channel::<i32>(1);
assert_eq!(tx.send_timeout(1, Duration::from_millis(1)), Ok(()));
assert_eq!(tx.send_timeout(1, Duration::from_millis(1)), Err(SendTimeoutError::Timeout(1)));
}

#[test]
fn smoke_threads() {
let (tx, rx) = sync_channel::<i32>(0);
Expand Down
12 changes: 8 additions & 4 deletions src/bootstrap/install.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,10 +200,14 @@ install!((self, builder, _config),
install_sh(builder, "clippy", self.compiler.stage, Some(self.target), &tarball);
};
Miri, alias = "miri", Self::should_build(_config), only_hosts: true, {
let tarball = builder
.ensure(dist::Miri { compiler: self.compiler, target: self.target })
.expect("missing miri");
install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
if let Some(tarball) = builder.ensure(dist::Miri { compiler: self.compiler, target: self.target }) {
install_sh(builder, "miri", self.compiler.stage, Some(self.target), &tarball);
} else {
// Miri is only available on nightly
builder.info(
&format!("skipping Install miri stage{} ({})", self.compiler.stage, self.target),
);
}
};
Rustfmt, alias = "rustfmt", Self::should_build(_config), only_hosts: true, {
if let Some(tarball) = builder.ensure(dist::Rustfmt {
Expand Down
2 changes: 1 addition & 1 deletion src/doc/rustdoc/src/lints.md
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ typo mistakes for some common attributes.
## `invalid_html_tags`
This lint is **allowed by default** and is **nightly-only**. It detects unclosed
This lint **warns by default**. It detects unclosed
or invalid HTML tags. For example:
```rust
Expand Down
4 changes: 3 additions & 1 deletion src/test/ui/async-await/in-trait/nested-rpit.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// check-pass
// edition: 2021
// known-bug: #105197
// failure-status:101
// dont-check-compiler-stderr

#![feature(async_fn_in_trait)]
#![feature(return_position_impl_trait_in_trait)]
Expand Down
Loading

0 comments on commit b7a6d74

Please sign in to comment.