Skip to content

Rollup of 9 pull requests #140726

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 22 commits into from
May 7, 2025
Merged
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
8e599b0
de-stabilize bench attribute
RalfJung Dec 13, 2024
f5c63b9
the soft_unstable lint cannot have an example that will keep working
RalfJung Dec 13, 2024
ea68445
Move `in_external_macro` to `SyntaxContext`
Jarcho Apr 29, 2025
dd20225
Update rc.rs docs
baumanj Apr 29, 2025
e4272d1
feat: Added capability to add multiple dependencies for an LLVMFeature
madhav-madhusoodanan Apr 9, 2025
7845c01
collect all Fuchsia bindings into the `fuchsia` module
joboet May 5, 2025
cdf4143
Implement `VecDeque::truncate_front()`
vkrivopalov Mar 3, 2025
431f02d
support duplicates in the opaque_types_storage
lcnr May 3, 2025
e648e5b
rustdoc: remove unportable markdown lint and old parser
notriddle May 6, 2025
43357b4
Added `apxf` target feature support, under flag `apx_target_feature`
madhav-madhusoodanan Apr 21, 2025
c32dc2d
Added apxf target feature test
madhav-madhusoodanan Apr 21, 2025
636a138
Structurally resolve in check_ref_cast
compiler-errors May 6, 2025
6a4af82
Update rc.rs docs
baumanj May 6, 2025
60a4b93
Rollup merge of #134273 - RalfJung:de-stabilize-bench, r=ibraheemdev,…
jhpratt May 7, 2025
4a8dbe0
Rollup merge of #139534 - madhav-madhusoodanan:apx-target-feature-add…
jhpratt May 7, 2025
b7199a6
Rollup merge of #140419 - Jarcho:ctxt_external, r=Nadrieril
jhpratt May 7, 2025
25631ff
Rollup merge of #140483 - baumanj:patch-1, r=workingjubilee
jhpratt May 7, 2025
bda326f
Rollup merge of #140607 - lcnr:opaque-type-storage, r=compiler-errors
jhpratt May 7, 2025
fe97fe4
Rollup merge of #140656 - joboet:fuchsia_pal, r=workingjubilee
jhpratt May 7, 2025
5b165aa
Rollup merge of #140668 - vkrivopalov:vecdeque-truncate-front, r=jhpratt
jhpratt May 7, 2025
8984d65
Rollup merge of #140709 - notriddle:rm-unportable-markdown, r=Guillau…
jhpratt May 7, 2025
3d8ef7a
Rollup merge of #140713 - compiler-errors:check_ref_cast, r=lcnr
jhpratt May 7, 2025
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
17 changes: 2 additions & 15 deletions Cargo.lock
Original file line number Diff line number Diff line change
@@ -558,7 +558,7 @@ dependencies = [
"if_chain",
"itertools",
"parking_lot",
"pulldown-cmark 0.11.3",
"pulldown-cmark",
"quote",
"regex",
"rustc_tools_util 0.4.2",
@@ -2849,17 +2849,6 @@ dependencies = [
"cc",
]

[[package]]
name = "pulldown-cmark"
version = "0.9.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "57206b407293d2bcd3af849ce869d52068623f19e1b5ff8e8778e3309439682b"
dependencies = [
"bitflags",
"memchr",
"unicase",
]

[[package]]
name = "pulldown-cmark"
version = "0.11.3"
@@ -4337,7 +4326,7 @@ version = "0.0.0"
dependencies = [
"bitflags",
"itertools",
"pulldown-cmark 0.11.3",
"pulldown-cmark",
"rustc_arena",
"rustc_ast",
"rustc_ast_pretty",
@@ -4516,7 +4505,6 @@ dependencies = [
"rustc_session",
"rustc_span",
"rustc_transmute",
"rustc_type_ir",
"smallvec",
"thin-vec",
"tracing",
@@ -4622,7 +4610,6 @@ dependencies = [
"indexmap",
"itertools",
"minifier",
"pulldown-cmark 0.9.6",
"pulldown-cmark-escape",
"regex",
"rustdoc-json-types",
49 changes: 32 additions & 17 deletions compiler/rustc_codegen_llvm/src/llvm_util.rs
Original file line number Diff line number Diff line change
@@ -19,6 +19,7 @@ use rustc_session::config::{PrintKind, PrintRequest};
use rustc_span::Symbol;
use rustc_target::spec::{MergeFunctions, PanicStrategy, SmallDataThresholdSupport};
use rustc_target::target_features::{RUSTC_SPECIAL_FEATURES, RUSTC_SPECIFIC_FEATURES};
use smallvec::{SmallVec, smallvec};

use crate::back::write::create_informational_target_machine;
use crate::errors::{
@@ -180,27 +181,27 @@ impl<'a> TargetFeatureFoldStrength<'a> {

pub(crate) struct LLVMFeature<'a> {
llvm_feature_name: &'a str,
dependency: Option<TargetFeatureFoldStrength<'a>>,
dependencies: SmallVec<[TargetFeatureFoldStrength<'a>; 1]>,
}

impl<'a> LLVMFeature<'a> {
fn new(llvm_feature_name: &'a str) -> Self {
Self { llvm_feature_name, dependency: None }
Self { llvm_feature_name, dependencies: SmallVec::new() }
}

fn with_dependency(
fn with_dependencies(
llvm_feature_name: &'a str,
dependency: TargetFeatureFoldStrength<'a>,
dependencies: SmallVec<[TargetFeatureFoldStrength<'a>; 1]>,
) -> Self {
Self { llvm_feature_name, dependency: Some(dependency) }
Self { llvm_feature_name, dependencies }
}

fn contains(&self, feat: &str) -> bool {
fn contains(&'a self, feat: &str) -> bool {
self.iter().any(|dep| dep == feat)
}

fn iter(&'a self) -> impl Iterator<Item = &'a str> {
let dependencies = self.dependency.iter().map(|feat| feat.as_str());
let dependencies = self.dependencies.iter().map(|feat| feat.as_str());
std::iter::once(self.llvm_feature_name).chain(dependencies)
}
}
@@ -210,7 +211,7 @@ impl<'a> IntoIterator for LLVMFeature<'a> {
type IntoIter = impl Iterator<Item = &'a str>;

fn into_iter(self) -> Self::IntoIter {
let dependencies = self.dependency.into_iter().map(|feat| feat.as_str());
let dependencies = self.dependencies.into_iter().map(|feat| feat.as_str());
std::iter::once(self.llvm_feature_name).chain(dependencies)
}
}
@@ -240,9 +241,9 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
&*sess.target.arch
};
match (arch, s) {
("x86", "sse4.2") => Some(LLVMFeature::with_dependency(
("x86", "sse4.2") => Some(LLVMFeature::with_dependencies(
"sse4.2",
TargetFeatureFoldStrength::EnableOnly("crc32"),
smallvec![TargetFeatureFoldStrength::EnableOnly("crc32")],
)),
("x86", "pclmulqdq") => Some(LLVMFeature::new("pclmul")),
("x86", "rdrand") => Some(LLVMFeature::new("rdrnd")),
@@ -262,9 +263,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
("aarch64", "sme-b16b16") if get_version().0 < 20 => Some(LLVMFeature::new("b16b16")),
("aarch64", "flagm2") => Some(LLVMFeature::new("altnzcv")),
// Rust ties fp and neon together.
("aarch64", "neon") => {
Some(LLVMFeature::with_dependency("neon", TargetFeatureFoldStrength::Both("fp-armv8")))
}
("aarch64", "neon") => Some(LLVMFeature::with_dependencies(
"neon",
smallvec![TargetFeatureFoldStrength::Both("fp-armv8")],
)),
// In LLVM neon implicitly enables fp, but we manually enable
// neon when a feature only implicitly enables fp
("aarch64", "fhm") => Some(LLVMFeature::new("fp16fml")),
@@ -281,9 +283,10 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
// Filter out features that are not supported by the current LLVM version
("riscv32" | "riscv64", "zacas") if get_version().0 < 20 => None,
// Enable the evex512 target feature if an avx512 target feature is enabled.
("x86", s) if s.starts_with("avx512") => {
Some(LLVMFeature::with_dependency(s, TargetFeatureFoldStrength::EnableOnly("evex512")))
}
("x86", s) if s.starts_with("avx512") => Some(LLVMFeature::with_dependencies(
s,
smallvec![TargetFeatureFoldStrength::EnableOnly("evex512")],
)),
// Support for `wide-arithmetic` will first land in LLVM 20 as part of
// llvm/llvm-project#111598
("wasm32" | "wasm64", "wide-arithmetic") if get_version() < (20, 0, 0) => None,
@@ -304,6 +307,18 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
("x86", "avx10.1") => Some(LLVMFeature::new("avx10.1-512")),
("x86", "avx10.2") if get_version().0 < 20 => None,
("x86", "avx10.2") if get_version().0 >= 20 => Some(LLVMFeature::new("avx10.2-512")),
("x86", "apxf") => Some(LLVMFeature::with_dependencies(
"egpr",
smallvec![
TargetFeatureFoldStrength::Both("push2pop2"),
TargetFeatureFoldStrength::Both("ppx"),
TargetFeatureFoldStrength::Both("ndd"),
TargetFeatureFoldStrength::Both("ccmp"),
TargetFeatureFoldStrength::Both("cf"),
TargetFeatureFoldStrength::Both("nf"),
TargetFeatureFoldStrength::Both("zu"),
],
)),
(_, s) => Some(LLVMFeature::new(s)),
}
}
@@ -853,7 +868,7 @@ pub(crate) fn global_llvm_features(
"{}{}",
enable_disable, llvm_feature.llvm_feature_name
))
.chain(llvm_feature.dependency.into_iter().filter_map(
.chain(llvm_feature.dependencies.into_iter().filter_map(
move |feat| match (enable, feat) {
(_, TargetFeatureFoldStrength::Both(f))
| (true, TargetFeatureFoldStrength::EnableOnly(f)) => {
1 change: 1 addition & 0 deletions compiler/rustc_feature/src/unstable.rs
Original file line number Diff line number Diff line change
@@ -316,6 +316,7 @@ declare_features! (
// Unstable `#[target_feature]` directives.
(unstable, aarch64_unstable_target_feature, "1.82.0", Some(44839)),
(unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
(unstable, apx_target_feature, "CURRENT_RUSTC_VERSION", Some(139284)),
(unstable, arm_target_feature, "1.27.0", Some(44839)),
(unstable, avx512_target_feature, "1.27.0", Some(44839)),
(unstable, bpf_target_feature, "1.54.0", Some(44839)),
3 changes: 2 additions & 1 deletion compiler/rustc_hir_typeck/src/_match.rs
Original file line number Diff line number Diff line change
@@ -603,7 +603,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
// FIXME(-Znext-solver): Remove this branch once `replace_opaque_types_with_infer` is gone.
ty::Infer(ty::TyVar(_)) => self
.inner
.borrow()
.borrow_mut()
.opaque_types()
.iter_opaque_types()
.find(|(_, v)| v.ty == expected_ty)
.map(|(k, _)| (k.def_id, k.args))?,
15 changes: 7 additions & 8 deletions compiler/rustc_hir_typeck/src/cast.rs
Original file line number Diff line number Diff line change
@@ -1051,20 +1051,19 @@ impl<'a, 'tcx> CastCheck<'tcx> {
fn check_ref_cast(
&self,
fcx: &FnCtxt<'a, 'tcx>,
m_expr: ty::TypeAndMut<'tcx>,
m_cast: ty::TypeAndMut<'tcx>,
mut m_expr: ty::TypeAndMut<'tcx>,
mut m_cast: ty::TypeAndMut<'tcx>,
) -> Result<CastKind, CastError<'tcx>> {
// array-ptr-cast: allow mut-to-mut, mut-to-const, const-to-const
m_expr.ty = fcx.try_structurally_resolve_type(self.expr_span, m_expr.ty);
m_cast.ty = fcx.try_structurally_resolve_type(self.cast_span, m_cast.ty);

if m_expr.mutbl >= m_cast.mutbl
&& let ty::Array(ety, _) = m_expr.ty.kind()
&& fcx.can_eq(fcx.param_env, *ety, m_cast.ty)
{
// Due to the limitations of LLVM global constants,
// region pointers end up pointing at copies of
// vector elements instead of the original values.
// To allow raw pointers to work correctly, we
// need to special-case obtaining a raw pointer
// from a region pointer to a vector.
// Due to historical reasons we allow directly casting references of
// arrays into raw pointers of their element type.

// Coerce to a raw pointer so that we generate RawPtr in MIR.
let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr.ty, m_expr.mutbl);
26 changes: 7 additions & 19 deletions compiler/rustc_infer/src/infer/canonical/query_response.rs
Original file line number Diff line number Diff line change
@@ -132,7 +132,13 @@ impl<'tcx> InferCtxt<'tcx> {

let certainty = if errors.is_empty() { Certainty::Proven } else { Certainty::Ambiguous };

let opaque_types = self.take_opaque_types_for_query_response();
let opaque_types = self
.inner
.borrow_mut()
.opaque_type_storage
.take_opaque_types()
.map(|(k, v)| (k, v.ty))
.collect();

Ok(QueryResponse {
var_values: inference_vars,
@@ -143,24 +149,6 @@ impl<'tcx> InferCtxt<'tcx> {
})
}

/// Used by the new solver as that one takes the opaque types at the end of a probe
/// to deal with multiple candidates without having to recompute them.
pub fn clone_opaque_types_for_query_response(
&self,
) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
self.inner
.borrow()
.opaque_type_storage
.opaque_types
.iter()
.map(|(k, v)| (*k, v.ty))
.collect()
}

fn take_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
self.take_opaque_types().into_iter().map(|(k, v)| (k, v.ty)).collect()
}

/// Given the (canonicalized) result to a canonical query,
/// instantiates the result so it can be used, plugging in the
/// values from the canonical query. (Note that the result may
25 changes: 8 additions & 17 deletions compiler/rustc_infer/src/infer/mod.rs
Original file line number Diff line number Diff line change
@@ -31,9 +31,9 @@ use rustc_middle::traits::solve::Goal;
use rustc_middle::ty::error::{ExpectedFound, TypeError};
use rustc_middle::ty::{
self, BoundVarReplacerDelegate, ConstVid, FloatVid, GenericArg, GenericArgKind, GenericArgs,
GenericArgsRef, GenericParamDefKind, InferConst, IntVid, PseudoCanonicalInput, Term, TermKind,
Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitable,
TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
GenericArgsRef, GenericParamDefKind, InferConst, IntVid, OpaqueHiddenType, OpaqueTypeKey,
PseudoCanonicalInput, Term, TermKind, Ty, TyCtxt, TyVid, TypeFoldable, TypeFolder,
TypeSuperFoldable, TypeVisitable, TypeVisitableExt, TypingEnv, TypingMode, fold_regions,
};
use rustc_span::{Span, Symbol};
use snapshot::undo_log::InferCtxtUndoLogs;
@@ -198,7 +198,7 @@ impl<'tcx> InferCtxtInner<'tcx> {
}

#[inline]
fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
pub fn opaque_types(&mut self) -> opaque_types::OpaqueTypeTable<'_, 'tcx> {
self.opaque_type_storage.with_log(&mut self.undo_log)
}

@@ -224,15 +224,6 @@ impl<'tcx> InferCtxtInner<'tcx> {
.expect("region constraints already solved")
.with_log(&mut self.undo_log)
}

// Iterates through the opaque type definitions without taking them; this holds the
// `InferCtxtInner` lock, so make sure to not do anything with `InferCtxt` side-effects
// while looping through this.
pub fn iter_opaque_types(
&self,
) -> impl Iterator<Item = (ty::OpaqueTypeKey<'tcx>, ty::OpaqueHiddenType<'tcx>)> {
self.opaque_type_storage.opaque_types.iter().map(|(&k, &v)| (k, v))
}
}

pub struct InferCtxt<'tcx> {
@@ -954,13 +945,13 @@ impl<'tcx> InferCtxt<'tcx> {
}

#[instrument(level = "debug", skip(self), ret)]
pub fn take_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
std::mem::take(&mut self.inner.borrow_mut().opaque_type_storage.opaque_types)
pub fn take_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
self.inner.borrow_mut().opaque_type_storage.take_opaque_types().collect()
}

#[instrument(level = "debug", skip(self), ret)]
pub fn clone_opaque_types(&self) -> opaque_types::OpaqueTypeMap<'tcx> {
self.inner.borrow().opaque_type_storage.opaque_types.clone()
pub fn clone_opaque_types(&self) -> Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
self.inner.borrow_mut().opaque_type_storage.iter_opaque_types().collect()
}

#[inline(always)]
2 changes: 0 additions & 2 deletions compiler/rustc_infer/src/infer/opaque_types/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
use hir::def_id::{DefId, LocalDefId};
use rustc_data_structures::fx::FxIndexMap;
use rustc_hir as hir;
use rustc_middle::bug;
use rustc_middle::traits::ObligationCause;
@@ -19,7 +18,6 @@ use crate::traits::{self, Obligation, PredicateObligations};

mod table;

pub(crate) type OpaqueTypeMap<'tcx> = FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>;
pub(crate) use table::{OpaqueTypeStorage, OpaqueTypeTable};

impl<'tcx> InferCtxt<'tcx> {
76 changes: 66 additions & 10 deletions compiler/rustc_infer/src/infer/opaque_types/table.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
use std::ops::Deref;

use rustc_data_structures::fx::FxIndexMap;
use rustc_data_structures::undo_log::UndoLogs;
use rustc_middle::bug;
use rustc_middle::ty::{self, OpaqueHiddenType, OpaqueTypeKey, Ty};
use tracing::instrument;

use super::OpaqueTypeMap;
use crate::infer::snapshot::undo_log::{InferCtxtUndoLogs, UndoLog};

#[derive(Default, Debug, Clone)]
pub(crate) struct OpaqueTypeStorage<'tcx> {
/// Opaque types found in explicit return types and their
/// associated fresh inference variable. Writeback resolves these
/// variables to get the concrete type, which can be used to
/// 'de-opaque' OpaqueHiddenType, after typeck is done with all functions.
pub opaque_types: OpaqueTypeMap<'tcx>,
pub struct OpaqueTypeStorage<'tcx> {
opaque_types: FxIndexMap<OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>>,
duplicate_entries: Vec<(OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)>,
}

impl<'tcx> OpaqueTypeStorage<'tcx> {
@@ -33,6 +32,52 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {
}
}

pub(crate) fn pop_duplicate_entry(&mut self) {
let entry = self.duplicate_entries.pop();
assert!(entry.is_some());
}

pub(crate) fn is_empty(&self) -> bool {
let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
opaque_types.is_empty() && duplicate_entries.is_empty()
}

pub(crate) fn take_opaque_types(
&mut self,
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
std::mem::take(opaque_types).into_iter().chain(std::mem::take(duplicate_entries))
}

/// Only returns the opaque types from the lookup table. These are used
/// when normalizing opaque types and have a unique key.
///
/// Outside of canonicalization one should generally use `iter_opaque_types`
/// to also consider duplicate entries.
pub fn iter_lookup_table(
&self,
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
self.opaque_types.iter().map(|(k, v)| (*k, *v))
}

/// Only returns the opaque types which are stored in `duplicate_entries`.
///
/// These have to considered when checking all opaque type uses but are e.g.
/// irrelevant for canonical inputs as nested queries never meaningfully
/// accesses them.
pub fn iter_duplicate_entries(
&self,
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
self.duplicate_entries.iter().copied()
}

pub fn iter_opaque_types(
&self,
) -> impl Iterator<Item = (OpaqueTypeKey<'tcx>, OpaqueHiddenType<'tcx>)> {
let OpaqueTypeStorage { opaque_types, duplicate_entries } = self;
opaque_types.iter().map(|(k, v)| (*k, *v)).chain(duplicate_entries.iter().copied())
}

#[inline]
pub(crate) fn with_log<'a>(
&'a mut self,
@@ -44,21 +89,27 @@ impl<'tcx> OpaqueTypeStorage<'tcx> {

impl<'tcx> Drop for OpaqueTypeStorage<'tcx> {
fn drop(&mut self) {
if !self.opaque_types.is_empty() {
if !self.is_empty() {
ty::tls::with(|tcx| tcx.dcx().delayed_bug(format!("{:?}", self.opaque_types)));
}
}
}

pub(crate) struct OpaqueTypeTable<'a, 'tcx> {
pub struct OpaqueTypeTable<'a, 'tcx> {
storage: &'a mut OpaqueTypeStorage<'tcx>,

undo_log: &'a mut InferCtxtUndoLogs<'tcx>,
}
impl<'tcx> Deref for OpaqueTypeTable<'_, 'tcx> {
type Target = OpaqueTypeStorage<'tcx>;
fn deref(&self) -> &Self::Target {
self.storage
}
}

impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
#[instrument(skip(self), level = "debug")]
pub(crate) fn register(
pub fn register(
&mut self,
key: OpaqueTypeKey<'tcx>,
hidden_type: OpaqueHiddenType<'tcx>,
@@ -72,4 +123,9 @@ impl<'a, 'tcx> OpaqueTypeTable<'a, 'tcx> {
self.undo_log.push(UndoLog::OpaqueTypes(key, None));
None
}

pub fn add_duplicate(&mut self, key: OpaqueTypeKey<'tcx>, hidden_type: OpaqueHiddenType<'tcx>) {
self.storage.duplicate_entries.push((key, hidden_type));
self.undo_log.push(UndoLog::DuplicateOpaqueType);
}
}
2 changes: 2 additions & 0 deletions compiler/rustc_infer/src/infer/snapshot/undo_log.rs
Original file line number Diff line number Diff line change
@@ -17,6 +17,7 @@ pub struct Snapshot<'tcx> {
/// Records the "undo" data for a single operation that affects some form of inference variable.
#[derive(Clone)]
pub(crate) enum UndoLog<'tcx> {
DuplicateOpaqueType,
OpaqueTypes(OpaqueTypeKey<'tcx>, Option<OpaqueHiddenType<'tcx>>),
TypeVariables(sv::UndoLog<ut::Delegate<type_variable::TyVidEqKey<'tcx>>>),
ConstUnificationTable(sv::UndoLog<ut::Delegate<ConstVidKey<'tcx>>>),
@@ -58,6 +59,7 @@ impl_from! {
impl<'tcx> Rollback<UndoLog<'tcx>> for InferCtxtInner<'tcx> {
fn reverse(&mut self, undo: UndoLog<'tcx>) {
match undo {
UndoLog::DuplicateOpaqueType => self.opaque_type_storage.pop_duplicate_entry(),
UndoLog::OpaqueTypes(key, idx) => self.opaque_type_storage.remove(key, idx),
UndoLog::TypeVariables(undo) => self.type_variable_storage.reverse(undo),
UndoLog::ConstUnificationTable(undo) => self.const_unification_storage.reverse(undo),
32 changes: 3 additions & 29 deletions compiler/rustc_lint_defs/src/builtin.rs
Original file line number Diff line number Diff line change
@@ -2352,37 +2352,11 @@ declare_lint! {
}

declare_lint! {
/// The `soft_unstable` lint detects unstable features that were
/// unintentionally allowed on stable.
///
/// ### Example
///
/// ```rust,compile_fail
/// #[cfg(test)]
/// extern crate test;
///
/// #[bench]
/// fn name(b: &mut test::Bencher) {
/// b.iter(|| 123)
/// }
/// ```
///
/// {{produces}}
///
/// ### Explanation
///
/// The [`bench` attribute] was accidentally allowed to be specified on
/// the [stable release channel]. Turning this to a hard error would have
/// broken some projects. This lint allows those projects to continue to
/// build correctly when [`--cap-lints`] is used, but otherwise signal an
/// error that `#[bench]` should not be used on the stable channel. This
/// is a [future-incompatible] lint to transition this to a hard error in
/// the future. See [issue #64266] for more details.
/// The `soft_unstable` lint detects unstable features that were unintentionally allowed on
/// stable. This is a [future-incompatible] lint to transition this to a hard error in the
/// future. See [issue #64266] for more details.
///
/// [issue #64266]: https://github.com/rust-lang/rust/issues/64266
/// [`bench` attribute]: https://doc.rust-lang.org/nightly/unstable-book/library-features/test.html
/// [stable release channel]: https://doc.rust-lang.org/book/appendix-07-nightly-rust.html
/// [`--cap-lints`]: https://doc.rust-lang.org/rustc/lints/levels.html#capping-lints
/// [future-incompatible]: ../index.md#future-incompatible-lints
pub SOFT_UNSTABLE,
Deny,
11 changes: 10 additions & 1 deletion compiler/rustc_next_trait_solver/src/delegate.rs
Original file line number Diff line number Diff line change
@@ -39,7 +39,10 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
term: <Self::Interner as Interner>::Term,
) -> Option<Vec<Goal<Self::Interner, <Self::Interner as Interner>::Predicate>>>;

fn clone_opaque_types_for_query_response(
fn clone_opaque_types_lookup_table(
&self,
) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;
fn clone_duplicate_opaque_types(
&self,
) -> Vec<(ty::OpaqueTypeKey<Self::Interner>, <Self::Interner as Interner>::Ty)>;

@@ -68,6 +71,12 @@ pub trait SolverDelegate: Deref<Target = Self::Infcx> + Sized {
hidden_ty: <Self::Interner as Interner>::Ty,
span: <Self::Interner as Interner>::Span,
) -> Option<<Self::Interner as Interner>::Ty>;
fn add_duplicate_opaque_type(
&self,
opaque_type_key: ty::OpaqueTypeKey<Self::Interner>,
hidden_ty: <Self::Interner as Interner>::Ty,
span: <Self::Interner as Interner>::Span,
);

fn add_item_bounds_for_hidden_type(
&self,
44 changes: 29 additions & 15 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
Original file line number Diff line number Diff line change
@@ -56,7 +56,10 @@ where
&self,
goal: Goal<I, T>,
) -> (Vec<I::GenericArg>, CanonicalInput<I, T>) {
let opaque_types = self.delegate.clone_opaque_types_for_query_response();
// We only care about one entry per `OpaqueTypeKey` here,
// so we only canonicalize the lookup table and ignore
// duplicate entries.
let opaque_types = self.delegate.clone_opaque_types_lookup_table();
let (goal, opaque_types) =
(goal, opaque_types).fold_with(&mut EagerResolver::new(self.delegate));

@@ -241,19 +244,21 @@ where
Default::default()
};

ExternalConstraintsData {
region_constraints,
opaque_types: self
.delegate
.clone_opaque_types_for_query_response()
.into_iter()
// Only return *newly defined* opaque types.
.filter(|(a, _)| {
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
})
.collect(),
normalization_nested_goals,
}
// We only return *newly defined* opaque types from canonical queries.
//
// Constraints for any existing opaque types are already tracked by changes
// to the `var_values`.
let opaque_types = self
.delegate
.clone_opaque_types_lookup_table()
.into_iter()
.filter(|(a, _)| {
self.predefined_opaques_in_body.opaque_types.iter().all(|(pa, _)| pa != a)
})
.chain(self.delegate.clone_duplicate_opaque_types())
.collect();

ExternalConstraintsData { region_constraints, opaque_types, normalization_nested_goals }
}

/// After calling a canonical query, we apply the constraints returned
@@ -432,7 +437,16 @@ where
fn register_new_opaque_types(&mut self, opaque_types: &[(ty::OpaqueTypeKey<I>, I::Ty)]) {
for &(key, ty) in opaque_types {
let prev = self.delegate.register_hidden_type_in_storage(key, ty, self.origin_span);
assert_eq!(prev, None);
// We eagerly resolve inference variables when computing the query response.
// This can cause previously distinct opaque type keys to now be structurally equal.
//
// To handle this, we store any duplicate entries in a separate list to check them
// at the end of typeck/borrowck. We could alternatively eagerly equate the hidden
// types here. However, doing so is difficult as it may result in nested goals and
// any errors may make it harder to track the control flow for diagnostics.
if let Some(prev) = prev {
self.delegate.add_duplicate_opaque_type(key, prev, self.origin_span);
}
}
}
}
36 changes: 26 additions & 10 deletions compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
Original file line number Diff line number Diff line change
@@ -14,7 +14,7 @@ use rustc_type_ir::{
TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor,
TypingMode,
};
use tracing::{instrument, trace};
use tracing::{debug, instrument, trace};

use super::has_only_region_constraints;
use crate::coherence;
@@ -361,7 +361,20 @@ where

for &(key, ty) in &input.predefined_opaques_in_body.opaque_types {
let prev = ecx.delegate.register_hidden_type_in_storage(key, ty, ecx.origin_span);
assert_eq!(prev, None);
// It may be possible that two entries in the opaque type storage end up
// with the same key after resolving contained inference variables.
//
// We could put them in the duplicate list but don't have to. The opaques we
// encounter here are already tracked in the caller, so there's no need to
// also store them here. We'd take them out when computing the query response
// and then discard them, as they're already present in the input.
//
// Ideally we'd drop duplicate opaque type definitions when computing
// the canonical input. This is more annoying to implement and may cause a
// perf regression, so we do it inside of the query for now.
if let Some(prev) = prev {
debug!(?key, ?ty, ?prev, "ignore duplicate in `opaque_type_storage`");
}
}

if !ecx.nested_goals.is_empty() {
@@ -1065,14 +1078,17 @@ where
&mut self,
key: ty::OpaqueTypeKey<I>,
) -> Option<(ty::OpaqueTypeKey<I>, I::Ty)> {
let mut matching =
self.delegate.clone_opaque_types_for_query_response().into_iter().filter(
|(candidate_key, _)| {
candidate_key.def_id == key.def_id
&& DeepRejectCtxt::relate_rigid_rigid(self.cx())
.args_may_unify(candidate_key.args, key.args)
},
);
// We shouldn't have any duplicate entries when using
// this function during `TypingMode::Analysis`.
let duplicate_entries = self.delegate.clone_duplicate_opaque_types();
assert!(duplicate_entries.is_empty(), "unexpected duplicates: {duplicate_entries:?}");
let mut matching = self.delegate.clone_opaque_types_lookup_table().into_iter().filter(
|(candidate_key, _)| {
candidate_key.def_id == key.def_id
&& DeepRejectCtxt::relate_rigid_rigid(self.cx())
.args_may_unify(candidate_key.args, key.args)
},
);
let first = matching.next();
let second = matching.next();
assert_eq!(second, None);
25 changes: 25 additions & 0 deletions compiler/rustc_span/src/hygiene.rs
Original file line number Diff line number Diff line change
@@ -41,6 +41,7 @@ use tracing::{debug, trace};

use crate::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, StableCrateId};
use crate::edition::Edition;
use crate::source_map::SourceMap;
use crate::symbol::{Symbol, kw, sym};
use crate::{DUMMY_SP, HashStableContext, Span, SpanDecoder, SpanEncoder, with_session_globals};

@@ -907,6 +908,30 @@ impl SyntaxContext {
pub fn edition(self) -> Edition {
HygieneData::with(|data| data.expn_data(data.outer_expn(self)).edition)
}

/// Returns whether this context originates in a foreign crate's external macro.
///
/// This is used to test whether a lint should not even begin to figure out whether it should
/// be reported on the current node.
pub fn in_external_macro(self, sm: &SourceMap) -> bool {
let expn_data = self.outer_expn_data();
match expn_data.kind {
ExpnKind::Root
| ExpnKind::Desugaring(
DesugaringKind::ForLoop
| DesugaringKind::WhileLoop
| DesugaringKind::OpaqueTy
| DesugaringKind::Async
| DesugaringKind::Await,
) => false,
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => {
// Dummy span for the `def_site` means it's an external macro.
expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site)
}
ExpnKind::Macro { .. } => true, // definitely a plugin
}
}
}

impl fmt::Debug for SyntaxContext {
21 changes: 3 additions & 18 deletions compiler/rustc_span/src/lib.rs
Original file line number Diff line number Diff line change
@@ -594,28 +594,13 @@ impl Span {
!self.is_dummy() && sm.is_span_accessible(self)
}

/// Returns whether `span` originates in a foreign crate's external macro.
/// Returns whether this span originates in a foreign crate's external macro.
///
/// This is used to test whether a lint should not even begin to figure out whether it should
/// be reported on the current node.
#[inline]
pub fn in_external_macro(self, sm: &SourceMap) -> bool {
let expn_data = self.ctxt().outer_expn_data();
match expn_data.kind {
ExpnKind::Root
| ExpnKind::Desugaring(
DesugaringKind::ForLoop
| DesugaringKind::WhileLoop
| DesugaringKind::OpaqueTy
| DesugaringKind::Async
| DesugaringKind::Await,
) => false,
ExpnKind::AstPass(_) | ExpnKind::Desugaring(_) => true, // well, it's "external"
ExpnKind::Macro(MacroKind::Bang, _) => {
// Dummy span for the `def_site` means it's an external macro.
expn_data.def_site.is_dummy() || sm.is_imported(expn_data.def_site)
}
ExpnKind::Macro { .. } => true, // definitely a plugin
}
self.ctxt().in_external_macro(sm)
}

/// Returns `true` if `span` originates in a derive-macro's expansion.
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
@@ -459,6 +459,7 @@ symbols! {
anonymous_lifetime_in_impl_trait,
any,
append_const_msg,
apx_target_feature,
arbitrary_enum_discriminant,
arbitrary_self_types,
arbitrary_self_types_pointers,
1 change: 1 addition & 0 deletions compiler/rustc_target/src/target_features.rs
Original file line number Diff line number Diff line change
@@ -393,6 +393,7 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
("amx-tf32", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("amx-tile", Unstable(sym::x86_amx_intrinsics), &[]),
("amx-transpose", Unstable(sym::x86_amx_intrinsics), &["amx-tile"]),
("apxf", Unstable(sym::apx_target_feature), &[]),
("avx", Stable, &["sse4.2"]),
(
"avx10.1",
1 change: 0 additions & 1 deletion compiler/rustc_trait_selection/Cargo.toml
Original file line number Diff line number Diff line change
@@ -20,7 +20,6 @@ rustc_parse_format = { path = "../rustc_parse_format" }
rustc_session = { path = "../rustc_session" }
rustc_span = { path = "../rustc_span" }
rustc_transmute = { path = "../rustc_transmute", features = ["rustc"] }
rustc_type_ir = { path = "../rustc_type_ir" }
smallvec = { version = "1.8.1", features = ["union", "may_dangle"] }
thin-vec = "0.2"
tracing = "0.1"
37 changes: 32 additions & 5 deletions compiler/rustc_trait_selection/src/solve/delegate.rs
Original file line number Diff line number Diff line change
@@ -104,8 +104,23 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
.map(|obligations| obligations.into_iter().map(|obligation| obligation.as_goal()).collect())
}

fn clone_opaque_types_for_query_response(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
self.0.clone_opaque_types_for_query_response()
fn clone_opaque_types_lookup_table(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
self.0
.inner
.borrow_mut()
.opaque_types()
.iter_lookup_table()
.map(|(k, h)| (k, h.ty))
.collect()
}
fn clone_duplicate_opaque_types(&self) -> Vec<(ty::OpaqueTypeKey<'tcx>, Ty<'tcx>)> {
self.0
.inner
.borrow_mut()
.opaque_types()
.iter_duplicate_entries()
.map(|(k, h)| (k, h.ty))
.collect()
}

fn make_deduplicated_outlives_constraints(
@@ -156,14 +171,26 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate<
fn register_hidden_type_in_storage(
&self,
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
hidden_ty: <Self::Interner as rustc_type_ir::Interner>::Ty,
span: <Self::Interner as rustc_type_ir::Interner>::Span,
) -> Option<<Self::Interner as rustc_type_ir::Interner>::Ty> {
hidden_ty: Ty<'tcx>,
span: Span,
) -> Option<Ty<'tcx>> {
self.0.register_hidden_type_in_storage(
opaque_type_key,
ty::OpaqueHiddenType { span, ty: hidden_ty },
)
}
fn add_duplicate_opaque_type(
&self,
opaque_type_key: ty::OpaqueTypeKey<'tcx>,
hidden_ty: Ty<'tcx>,
span: Span,
) {
self.0
.inner
.borrow_mut()
.opaque_types()
.add_duplicate(opaque_type_key, ty::OpaqueHiddenType { span, ty: hidden_ty })
}

fn add_item_bounds_for_hidden_type(
&self,
67 changes: 67 additions & 0 deletions library/alloc/src/collections/vec_deque/mod.rs
Original file line number Diff line number Diff line change
@@ -1188,6 +1188,73 @@ impl<T, A: Allocator> VecDeque<T, A> {
}
}

/// Shortens the deque, keeping the last `len` elements and dropping
/// the rest.
///
/// If `len` is greater or equal to the deque's current length, this has
/// no effect.
///
/// # Examples
///
/// ```
/// # #![feature(vec_deque_truncate_front)]
/// use std::collections::VecDeque;
///
/// let mut buf = VecDeque::new();
/// buf.push_front(5);
/// buf.push_front(10);
/// buf.push_front(15);
/// assert_eq!(buf, [15, 10, 5]);
/// assert_eq!(buf.as_slices(), (&[15, 10, 5][..], &[][..]));
/// buf.truncate_front(1);
/// assert_eq!(buf.as_slices(), (&[5][..], &[][..]));
/// ```
#[unstable(feature = "vec_deque_truncate_front", issue = "140667")]
pub fn truncate_front(&mut self, len: usize) {
/// Runs the destructor for all items in the slice when it gets dropped (normally or
/// during unwinding).
struct Dropper<'a, T>(&'a mut [T]);

impl<'a, T> Drop for Dropper<'a, T> {
fn drop(&mut self) {
unsafe {
ptr::drop_in_place(self.0);
}
}
}

unsafe {
if len >= self.len {
// No action is taken
return;
}

let (front, back) = self.as_mut_slices();
if len > back.len() {
// The 'back' slice remains unchanged.
// front.len() + back.len() == self.len, so 'end' is non-negative
// and end < front.len()
let end = front.len() - (len - back.len());
let drop_front = front.get_unchecked_mut(..end) as *mut _;
self.head += end;
self.len = len;
ptr::drop_in_place(drop_front);
} else {
let drop_front = front as *mut _;
// 'end' is non-negative by the condition above
let end = back.len() - len;
let drop_back = back.get_unchecked_mut(..end) as *mut _;
self.head = self.to_physical_idx(self.len - len);
self.len = len;

// Make sure the second half is dropped even when a destructor
// in the first one panics.
let _back_dropper = Dropper(&mut *drop_back);
ptr::drop_in_place(drop_front);
}
}
}

/// Returns a reference to the underlying allocator.
#[unstable(feature = "allocator_api", issue = "32838")]
#[inline]
10 changes: 5 additions & 5 deletions library/alloc/src/rc.rs
Original file line number Diff line number Diff line change
@@ -3536,11 +3536,11 @@ impl<T> Default for Weak<T> {
}
}

// NOTE: We checked_add here to deal with mem::forget safely. In particular
// if you mem::forget Rcs (or Weaks), the ref-count can overflow, and then
// you can free the allocation while outstanding Rcs (or Weaks) exist.
// We abort because this is such a degenerate scenario that we don't care about
// what happens -- no real program should ever experience this.
// NOTE: If you mem::forget Rcs (or Weaks), drop is skipped and the ref-count
// is not decremented, meaning the ref-count can overflow, and then you can
// free the allocation while outstanding Rcs (or Weaks) exist, which would be
// unsound. We abort because this is such a degenerate scenario that we don't
// care about what happens -- no real program should ever experience this.
//
// This should have negligible overhead since you don't actually need to
// clone these much in Rust thanks to ownership and move-semantics.
1 change: 1 addition & 0 deletions library/alloctests/tests/lib.rs
Original file line number Diff line number Diff line change
@@ -37,6 +37,7 @@
#![feature(str_as_str)]
#![feature(strict_provenance_lints)]
#![feature(vec_deque_pop_if)]
#![feature(vec_deque_truncate_front)]
#![feature(unique_rc_arc)]
#![feature(macro_metavar_expr_concat)]
#![allow(internal_features)]
69 changes: 69 additions & 0 deletions library/alloctests/tests/vec_deque.rs
Original file line number Diff line number Diff line change
@@ -1686,6 +1686,40 @@ fn truncate_leak() {
assert_eq!(unsafe { DROPS }, 7);
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn truncate_front_leak() {
static mut DROPS: i32 = 0;

struct D(bool);

impl Drop for D {
fn drop(&mut self) {
unsafe {
DROPS += 1;
}

if self.0 {
panic!("panic in `drop`");
}
}
}

let mut q = VecDeque::new();
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_back(D(false));
q.push_front(D(true));
q.push_front(D(false));
q.push_front(D(false));

catch_unwind(AssertUnwindSafe(|| q.truncate_front(1))).ok();

assert_eq!(unsafe { DROPS }, 7);
}

#[test]
#[cfg_attr(not(panic = "unwind"), ignore = "test requires unwinding support")]
fn test_drain_leak() {
@@ -1863,3 +1897,38 @@ fn test_collect_from_into_iter_keeps_allocation() {
assert_eq!(v.capacity(), 13);
}
}

#[test]
fn test_truncate_front() {
let mut v = VecDeque::with_capacity(13);
v.extend(0..7);
assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
v.truncate_front(10);
assert_eq!(v.len(), 7);
assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
v.truncate_front(7);
assert_eq!(v.len(), 7);
assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
v.truncate_front(3);
assert_eq!(v.as_slices(), ([4, 5, 6].as_slice(), [].as_slice()));
assert_eq!(v.len(), 3);
v.truncate_front(0);
assert_eq!(v.as_slices(), ([].as_slice(), [].as_slice()));
assert_eq!(v.len(), 0);

v.clear();
v.extend(0..7);
assert_eq!(v.as_slices(), ([0, 1, 2, 3, 4, 5, 6].as_slice(), [].as_slice()));
v.push_front(9);
v.push_front(8);
v.push_front(7);
assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice()));
v.truncate_front(12);
assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice()));
v.truncate_front(10);
assert_eq!(v.as_slices(), ([7, 8, 9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice()));
v.truncate_front(8);
assert_eq!(v.as_slices(), ([9].as_slice(), [0, 1, 2, 3, 4, 5, 6].as_slice()));
v.truncate_front(5);
assert_eq!(v.as_slices(), ([2, 3, 4, 5, 6].as_slice(), [].as_slice()));
}
1 change: 0 additions & 1 deletion library/core/src/macros/mod.rs
Original file line number Diff line number Diff line change
@@ -1661,7 +1661,6 @@ pub(crate) mod builtin {
#[unstable(
feature = "test",
issue = "50297",
soft,
reason = "`bench` is a part of custom test frameworks which are unstable"
)]
#[allow_internal_unstable(test, rustc_attrs, coverage_attribute)]
321 changes: 108 additions & 213 deletions library/std/src/sys/pal/unix/fuchsia.rs
Original file line number Diff line number Diff line change
@@ -1,48 +1,35 @@
#![allow(non_camel_case_types, unused)]
#![expect(non_camel_case_types)]

use libc::{c_int, c_void, size_t};
use libc::size_t;

use crate::ffi::{c_char, c_int, c_void};
use crate::io;
use crate::mem::MaybeUninit;
use crate::os::raw::c_char;

pub type zx_handle_t = u32;
pub type zx_vaddr_t = usize;
pub type zx_rights_t = u32;
pub type zx_status_t = i32;

pub const ZX_HANDLE_INVALID: zx_handle_t = 0;
//////////
// Time //
//////////

pub type zx_time_t = i64;
pub const ZX_TIME_INFINITE: zx_time_t = i64::MAX;

pub type zx_signals_t = u32;

pub const ZX_OBJECT_SIGNAL_3: zx_signals_t = 1 << 3;

pub const ZX_TASK_TERMINATED: zx_signals_t = ZX_OBJECT_SIGNAL_3;
pub const ZX_TIME_INFINITE: zx_time_t = i64::MAX;

pub const ZX_RIGHT_SAME_RIGHTS: zx_rights_t = 1 << 31;
unsafe extern "C" {
pub safe fn zx_clock_get_monotonic() -> zx_time_t;
}

// The upper four bits gives the minor version.
pub type zx_object_info_topic_t = u32;
/////////////
// Handles //
/////////////

pub const ZX_INFO_PROCESS: zx_object_info_topic_t = 3 | (1 << 28);
pub type zx_handle_t = u32;

pub type zx_info_process_flags_t = u32;
pub const ZX_HANDLE_INVALID: zx_handle_t = 0;

pub fn zx_cvt<T>(t: T) -> io::Result<T>
where
T: TryInto<zx_status_t> + Copy,
{
if let Ok(status) = TryInto::try_into(t) {
if status < 0 { Err(io::Error::from_raw_os_error(status)) } else { Ok(t) }
} else {
Err(io::Error::last_os_error())
}
unsafe extern "C" {
pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t;
}

// Safe wrapper around zx_handle_t
/// A safe wrapper around `zx_handle_t`.
pub struct Handle {
raw: zx_handle_t,
}
@@ -65,6 +52,66 @@ impl Drop for Handle {
}
}

///////////
// Futex //
///////////

pub type zx_futex_t = crate::sync::atomic::Atomic<u32>;

unsafe extern "C" {
pub fn zx_object_wait_one(
handle: zx_handle_t,
signals: zx_signals_t,
timeout: zx_time_t,
pending: *mut zx_signals_t,
) -> zx_status_t;

pub fn zx_futex_wait(
value_ptr: *const zx_futex_t,
current_value: zx_futex_t,
new_futex_owner: zx_handle_t,
deadline: zx_time_t,
) -> zx_status_t;
pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t;
pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t;
pub safe fn zx_thread_self() -> zx_handle_t;
}

////////////////
// Properties //
////////////////

pub const ZX_PROP_NAME: u32 = 3;

unsafe extern "C" {
pub fn zx_object_set_property(
handle: zx_handle_t,
property: u32,
value: *const libc::c_void,
value_size: libc::size_t,
) -> zx_status_t;
}

/////////////
// Signals //
/////////////

pub type zx_signals_t = u32;

pub const ZX_OBJECT_SIGNAL_3: zx_signals_t = 1 << 3;
pub const ZX_TASK_TERMINATED: zx_signals_t = ZX_OBJECT_SIGNAL_3;

/////////////////
// Object info //
/////////////////

// The upper four bits gives the minor version.
pub type zx_object_info_topic_t = u32;

pub const ZX_INFO_PROCESS: zx_object_info_topic_t = 3 | (1 << 28);

pub type zx_info_process_flags_t = u32;

// Returned for topic ZX_INFO_PROCESS
#[derive(Default)]
#[repr(C)]
@@ -76,25 +123,6 @@ pub struct zx_info_process_t {
}

unsafe extern "C" {
pub fn zx_job_default() -> zx_handle_t;

pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t;

pub fn zx_handle_close(handle: zx_handle_t) -> zx_status_t;

pub fn zx_handle_duplicate(
handle: zx_handle_t,
rights: zx_rights_t,
out: *const zx_handle_t,
) -> zx_handle_t;

pub fn zx_object_wait_one(
handle: zx_handle_t,
signals: zx_signals_t,
timeout: zx_time_t,
pending: *mut zx_signals_t,
) -> zx_status_t;

pub fn zx_object_get_info(
handle: zx_handle_t,
topic: u32,
@@ -105,6 +133,10 @@ unsafe extern "C" {
) -> zx_status_t;
}

///////////////
// Processes //
///////////////

#[derive(Default)]
#[repr(C)]
pub struct fdio_spawn_action_t {
@@ -130,180 +162,43 @@ unsafe extern "C" {

pub fn fdio_fd_clone(fd: c_int, out_handle: *mut zx_handle_t) -> zx_status_t;
pub fn fdio_fd_create(handle: zx_handle_t, fd: *mut c_int) -> zx_status_t;

pub fn zx_task_kill(handle: zx_handle_t) -> zx_status_t;
}

// fdio_spawn_etc flags

pub const FDIO_SPAWN_CLONE_JOB: u32 = 0x0001;
pub const FDIO_SPAWN_CLONE_LDSVC: u32 = 0x0002;
pub const FDIO_SPAWN_CLONE_NAMESPACE: u32 = 0x0004;
pub const FDIO_SPAWN_CLONE_STDIO: u32 = 0x0008;
pub const FDIO_SPAWN_CLONE_ENVIRON: u32 = 0x0010;
pub const FDIO_SPAWN_CLONE_UTC_CLOCK: u32 = 0x0020;
pub const FDIO_SPAWN_CLONE_ALL: u32 = 0xFFFF;

// fdio_spawn_etc actions

pub const FDIO_SPAWN_ACTION_CLONE_FD: u32 = 0x0001;
pub const FDIO_SPAWN_ACTION_TRANSFER_FD: u32 = 0x0002;

// Errors

#[allow(unused)]
pub const ERR_INTERNAL: zx_status_t = -1;

// ERR_NOT_SUPPORTED: The operation is not implemented, supported,
// or enabled.
#[allow(unused)]
pub const ERR_NOT_SUPPORTED: zx_status_t = -2;

// ERR_NO_RESOURCES: The system was not able to allocate some resource
// needed for the operation.
#[allow(unused)]
pub const ERR_NO_RESOURCES: zx_status_t = -3;

// ERR_NO_MEMORY: The system was not able to allocate memory needed
// for the operation.
#[allow(unused)]
pub const ERR_NO_MEMORY: zx_status_t = -4;

// ERR_CALL_FAILED: The second phase of zx_channel_call(; did not complete
// successfully.
#[allow(unused)]
pub const ERR_CALL_FAILED: zx_status_t = -5;

// ERR_INTERRUPTED_RETRY: The system call was interrupted, but should be
// retried. This should not be seen outside of the VDSO.
#[allow(unused)]
pub const ERR_INTERRUPTED_RETRY: zx_status_t = -6;

// ======= Parameter errors =======
// ERR_INVALID_ARGS: an argument is invalid, ex. null pointer
#[allow(unused)]
pub const ERR_INVALID_ARGS: zx_status_t = -10;

// ERR_BAD_HANDLE: A specified handle value does not refer to a handle.
#[allow(unused)]
pub const ERR_BAD_HANDLE: zx_status_t = -11;

// ERR_WRONG_TYPE: The subject of the operation is the wrong type to
// perform the operation.
// Example: Attempting a message_read on a thread handle.
#[allow(unused)]
pub const ERR_WRONG_TYPE: zx_status_t = -12;

// ERR_BAD_SYSCALL: The specified syscall number is invalid.
#[allow(unused)]
pub const ERR_BAD_SYSCALL: zx_status_t = -13;

// ERR_OUT_OF_RANGE: An argument is outside the valid range for this
// operation.
#[allow(unused)]
pub const ERR_OUT_OF_RANGE: zx_status_t = -14;

// ERR_BUFFER_TOO_SMALL: A caller provided buffer is too small for
// this operation.
#[allow(unused)]
pub const ERR_BUFFER_TOO_SMALL: zx_status_t = -15;

// ======= Precondition or state errors =======
// ERR_BAD_STATE: operation failed because the current state of the
// object does not allow it, or a precondition of the operation is
// not satisfied
#[allow(unused)]
pub const ERR_BAD_STATE: zx_status_t = -20;

// ERR_TIMED_OUT: The time limit for the operation elapsed before
// the operation completed.
#[allow(unused)]
pub const ERR_TIMED_OUT: zx_status_t = -21;

// ERR_SHOULD_WAIT: The operation cannot be performed currently but
// potentially could succeed if the caller waits for a prerequisite
// to be satisfied, for example waiting for a handle to be readable
// or writable.
// Example: Attempting to read from a message pipe that has no
// messages waiting but has an open remote will return ERR_SHOULD_WAIT.
// Attempting to read from a message pipe that has no messages waiting
// and has a closed remote end will return ERR_REMOTE_CLOSED.
#[allow(unused)]
pub const ERR_SHOULD_WAIT: zx_status_t = -22;

// ERR_CANCELED: The in-progress operation (e.g., a wait) has been
// // canceled.
#[allow(unused)]
pub const ERR_CANCELED: zx_status_t = -23;

// ERR_PEER_CLOSED: The operation failed because the remote end
// of the subject of the operation was closed.
#[allow(unused)]
pub const ERR_PEER_CLOSED: zx_status_t = -24;

// ERR_NOT_FOUND: The requested entity is not found.
#[allow(unused)]
pub const ERR_NOT_FOUND: zx_status_t = -25;

// ERR_ALREADY_EXISTS: An object with the specified identifier
// already exists.
// Example: Attempting to create a file when a file already exists
// with that name.
#[allow(unused)]
pub const ERR_ALREADY_EXISTS: zx_status_t = -26;

// ERR_ALREADY_BOUND: The operation failed because the named entity
// is already owned or controlled by another entity. The operation
// could succeed later if the current owner releases the entity.
#[allow(unused)]
pub const ERR_ALREADY_BOUND: zx_status_t = -27;

// ERR_UNAVAILABLE: The subject of the operation is currently unable
// to perform the operation.
// Note: This is used when there's no direct way for the caller to
// observe when the subject will be able to perform the operation
// and should thus retry.
#[allow(unused)]
pub const ERR_UNAVAILABLE: zx_status_t = -28;

// ======= Permission check errors =======
// ERR_ACCESS_DENIED: The caller did not have permission to perform
// the specified operation.
#[allow(unused)]
pub const ERR_ACCESS_DENIED: zx_status_t = -30;

// ======= Input-output errors =======
// ERR_IO: Otherwise unspecified error occurred during I/O.
#[allow(unused)]
pub const ERR_IO: zx_status_t = -40;

// ERR_REFUSED: The entity the I/O operation is being performed on
// rejected the operation.
// Example: an I2C device NAK'ing a transaction or a disk controller
// rejecting an invalid command.
#[allow(unused)]
pub const ERR_IO_REFUSED: zx_status_t = -41;

// ERR_IO_DATA_INTEGRITY: The data in the operation failed an integrity
// check and is possibly corrupted.
// Example: CRC or Parity error.
#[allow(unused)]
pub const ERR_IO_DATA_INTEGRITY: zx_status_t = -42;

// ERR_IO_DATA_LOSS: The data in the operation is currently unavailable
// and may be permanently lost.
// Example: A disk block is irrecoverably damaged.
#[allow(unused)]
pub const ERR_IO_DATA_LOSS: zx_status_t = -43;

// Filesystem specific errors
#[allow(unused)]
pub const ERR_BAD_PATH: zx_status_t = -50;
#[allow(unused)]
pub const ERR_NOT_DIR: zx_status_t = -51;
#[allow(unused)]
pub const ERR_NOT_FILE: zx_status_t = -52;
// ERR_FILE_BIG: A file exceeds a filesystem-specific size limit.
#[allow(unused)]
pub const ERR_FILE_BIG: zx_status_t = -53;
// ERR_NO_SPACE: Filesystem or device space is exhausted.
#[allow(unused)]
pub const ERR_NO_SPACE: zx_status_t = -54;
////////////
// Errors //
////////////

pub type zx_status_t = i32;

pub const ZX_OK: zx_status_t = 0;
pub const ZX_ERR_NOT_SUPPORTED: zx_status_t = -2;
pub const ZX_ERR_INVALID_ARGS: zx_status_t = -10;
pub const ZX_ERR_BAD_HANDLE: zx_status_t = -11;
pub const ZX_ERR_WRONG_TYPE: zx_status_t = -12;
pub const ZX_ERR_BAD_STATE: zx_status_t = -20;
pub const ZX_ERR_TIMED_OUT: zx_status_t = -21;

pub fn zx_cvt<T>(t: T) -> io::Result<T>
where
T: TryInto<zx_status_t> + Copy,
{
if let Ok(status) = TryInto::try_into(t) {
if status < 0 { Err(io::Error::from_raw_os_error(status)) } else { Ok(t) }
} else {
Err(io::Error::last_os_error())
}
}
54 changes: 8 additions & 46 deletions library/std/src/sys/pal/unix/futex.rs
Original file line number Diff line number Diff line change
@@ -254,67 +254,29 @@ pub fn futex_wake_all(futex: &Atomic<u32>) {
unsafe { emscripten_futex_wake(futex, i32::MAX) };
}

#[cfg(target_os = "fuchsia")]
pub mod zircon {
pub type zx_futex_t = crate::sync::atomic::Atomic<u32>;
pub type zx_handle_t = u32;
pub type zx_status_t = i32;
pub type zx_time_t = i64;

pub const ZX_HANDLE_INVALID: zx_handle_t = 0;

pub const ZX_TIME_INFINITE: zx_time_t = zx_time_t::MAX;

pub const ZX_OK: zx_status_t = 0;
pub const ZX_ERR_INVALID_ARGS: zx_status_t = -10;
pub const ZX_ERR_BAD_HANDLE: zx_status_t = -11;
pub const ZX_ERR_WRONG_TYPE: zx_status_t = -12;
pub const ZX_ERR_BAD_STATE: zx_status_t = -20;
pub const ZX_ERR_TIMED_OUT: zx_status_t = -21;

unsafe extern "C" {
pub fn zx_clock_get_monotonic() -> zx_time_t;
pub fn zx_futex_wait(
value_ptr: *const zx_futex_t,
current_value: zx_futex_t,
new_futex_owner: zx_handle_t,
deadline: zx_time_t,
) -> zx_status_t;
pub fn zx_futex_wake(value_ptr: *const zx_futex_t, wake_count: u32) -> zx_status_t;
pub fn zx_futex_wake_single_owner(value_ptr: *const zx_futex_t) -> zx_status_t;
pub fn zx_thread_self() -> zx_handle_t;
}
}

#[cfg(target_os = "fuchsia")]
pub fn futex_wait(futex: &Atomic<u32>, expected: u32, timeout: Option<Duration>) -> bool {
use super::fuchsia::*;

// Sleep forever if the timeout is longer than fits in a i64.
let deadline = timeout
.and_then(|d| {
i64::try_from(d.as_nanos())
.ok()?
.checked_add(unsafe { zircon::zx_clock_get_monotonic() })
})
.unwrap_or(zircon::ZX_TIME_INFINITE);
.and_then(|d| i64::try_from(d.as_nanos()).ok()?.checked_add(zx_clock_get_monotonic()))
.unwrap_or(ZX_TIME_INFINITE);

unsafe {
zircon::zx_futex_wait(
futex,
core::sync::atomic::AtomicU32::new(expected),
zircon::ZX_HANDLE_INVALID,
deadline,
) != zircon::ZX_ERR_TIMED_OUT
zx_futex_wait(futex, zx_futex_t::new(expected), ZX_HANDLE_INVALID, deadline)
!= ZX_ERR_TIMED_OUT
}
}

// Fuchsia doesn't tell us how many threads are woken up, so this always returns false.
#[cfg(target_os = "fuchsia")]
pub fn futex_wake(futex: &Atomic<u32>) -> bool {
unsafe { zircon::zx_futex_wake(futex, 1) };
unsafe { super::fuchsia::zx_futex_wake(futex, 1) };
false
}

#[cfg(target_os = "fuchsia")]
pub fn futex_wake_all(futex: &Atomic<u32>) {
unsafe { zircon::zx_futex_wake(futex, u32::MAX) };
unsafe { super::fuchsia::zx_futex_wake(futex, u32::MAX) };
}
19 changes: 1 addition & 18 deletions library/std/src/sys/pal/unix/thread.rs
Original file line number Diff line number Diff line change
@@ -22,23 +22,6 @@ pub const DEFAULT_MIN_STACK_SIZE: usize = 256 * 1024;
#[cfg(any(target_os = "espidf", target_os = "nuttx"))]
pub const DEFAULT_MIN_STACK_SIZE: usize = 0; // 0 indicates that the stack size configured in the ESP-IDF/NuttX menuconfig system should be used

#[cfg(target_os = "fuchsia")]
mod zircon {
type zx_handle_t = u32;
type zx_status_t = i32;
pub const ZX_PROP_NAME: u32 = 3;

unsafe extern "C" {
pub fn zx_object_set_property(
handle: zx_handle_t,
property: u32,
value: *const libc::c_void,
value_size: libc::size_t,
) -> zx_status_t;
pub fn zx_thread_self() -> zx_handle_t;
}
}

pub struct Thread {
id: libc::pthread_t,
}
@@ -216,7 +199,7 @@ impl Thread {

#[cfg(target_os = "fuchsia")]
pub fn set_name(name: &CStr) {
use self::zircon::*;
use super::fuchsia::*;
unsafe {
zx_object_set_property(
zx_thread_self(),
4 changes: 2 additions & 2 deletions library/std/src/sys/process/unix/fuchsia.rs
Original file line number Diff line number Diff line change
@@ -76,7 +76,7 @@ impl Command {

let mut handle = ZX_HANDLE_INVALID;
let status = fdio_fd_clone(target_fd, &mut handle);
if status == ERR_INVALID_ARGS || status == ERR_NOT_SUPPORTED {
if status == ZX_ERR_INVALID_ARGS || status == ZX_ERR_NOT_SUPPORTED {
// This descriptor is closed; skip it rather than generating an
// error.
return Ok(Default::default());
@@ -192,7 +192,7 @@ impl Process {
zx_object_wait_one(self.handle.raw(), ZX_TASK_TERMINATED, 0, ptr::null_mut());
match status {
0 => {} // Success
x if x == ERR_TIMED_OUT => {
x if x == ZX_ERR_TIMED_OUT => {
return Ok(None);
}
_ => {
6 changes: 3 additions & 3 deletions library/std/src/sys/sync/mutex/fuchsia.rs
Original file line number Diff line number Diff line change
@@ -39,7 +39,7 @@
use crate::sync::atomic::Ordering::{Acquire, Relaxed, Release};
use crate::sync::atomic::{Atomic, AtomicU32};
use crate::sys::futex::zircon::{
use crate::sys::fuchsia::{
ZX_ERR_BAD_HANDLE, ZX_ERR_BAD_STATE, ZX_ERR_INVALID_ARGS, ZX_ERR_TIMED_OUT, ZX_ERR_WRONG_TYPE,
ZX_OK, ZX_TIME_INFINITE, zx_futex_wait, zx_futex_wake_single_owner, zx_handle_t,
zx_thread_self,
@@ -83,13 +83,13 @@ impl Mutex {

#[inline]
pub fn try_lock(&self) -> bool {
let thread_self = unsafe { zx_thread_self() };
let thread_self = zx_thread_self();
self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed).is_ok()
}

#[inline]
pub fn lock(&self) {
let thread_self = unsafe { zx_thread_self() };
let thread_self = zx_thread_self();
if let Err(state) =
self.futex.compare_exchange(UNLOCKED, to_state(thread_self), Acquire, Relaxed)
{
1 change: 0 additions & 1 deletion src/librustdoc/Cargo.toml
Original file line number Diff line number Diff line change
@@ -14,7 +14,6 @@ base64 = "0.21.7"
itertools = "0.12"
indexmap = "2"
minifier = { version = "0.3.5", default-features = false }
pulldown-cmark-old = { version = "0.9.6", package = "pulldown-cmark", default-features = false }
pulldown-cmark-escape = { version = "0.11.0", features = ["simd"] }
regex = "1"
rustdoc-json-types = { path = "../rustdoc-json-types" }
10 changes: 1 addition & 9 deletions src/librustdoc/lint.rs
Original file line number Diff line number Diff line change
@@ -196,14 +196,6 @@ declare_rustdoc_lint! {
"detects redundant explicit links in doc comments"
}

declare_rustdoc_lint! {
/// This compatibility lint checks for Markdown syntax that works in the old engine but not
/// the new one.
UNPORTABLE_MARKDOWN,
Warn,
"detects markdown that is interpreted differently in different parser"
}

pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
vec![
BROKEN_INTRA_DOC_LINKS,
@@ -217,7 +209,6 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
MISSING_CRATE_LEVEL_DOCS,
UNESCAPED_BACKTICKS,
REDUNDANT_EXPLICIT_LINKS,
UNPORTABLE_MARKDOWN,
]
});

@@ -241,4 +232,5 @@ pub(crate) fn register_lints(_sess: &Session, lint_store: &mut LintStore) {
.register_renamed("intra_doc_link_resolution_failure", "rustdoc::broken_intra_doc_links");
lint_store.register_renamed("non_autolinks", "rustdoc::bare_urls");
lint_store.register_renamed("rustdoc::non_autolinks", "rustdoc::bare_urls");
lint_store.register_removed("rustdoc::unportable_markdown", "old parser removed");
}
4 changes: 0 additions & 4 deletions src/librustdoc/passes/lint.rs
Original file line number Diff line number Diff line change
@@ -6,7 +6,6 @@ mod check_code_block_syntax;
mod html_tags;
mod redundant_explicit_links;
mod unescaped_backticks;
mod unportable_markdown;

use super::Pass;
use crate::clean::*;
@@ -49,9 +48,6 @@ impl DocVisitor<'_> for Linter<'_, '_> {
}
if may_have_block_comment_or_html {
html_tags::visit_item(self.cx, item, hir_id, &dox);
unportable_markdown::visit_item(self.cx, item, hir_id, &dox);
} else if may_have_link {
unportable_markdown::visit_item(self.cx, item, hir_id, &dox);
}
}

145 changes: 0 additions & 145 deletions src/librustdoc/passes/lint/unportable_markdown.rs

This file was deleted.

1 change: 1 addition & 0 deletions src/tools/lint-docs/src/lib.rs
Original file line number Diff line number Diff line change
@@ -312,6 +312,7 @@ impl<'a> LintExtractor<'a> {
if matches!(
lint.name.as_str(),
"unused_features" // broken lint
| "soft_unstable" // cannot have a stable example
) {
return Ok(());
}
62 changes: 0 additions & 62 deletions tests/rustdoc-ui/unportable-markdown.rs

This file was deleted.

23 changes: 0 additions & 23 deletions tests/rustdoc-ui/unportable-markdown.stderr

This file was deleted.

22 changes: 22 additions & 0 deletions tests/ui/cast/cast-alias-of-array-to-element.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
//@ check-pass
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver

// Regression test for <https://github.com/rust-lang/trait-system-refactor-initiative/issues/203>.
// Test that we structually normalize in the hacky `&[T; N] -> *const T` in cast.

trait Mirror {
type Assoc: ?Sized;
}
impl<T: ?Sized> Mirror for T {
type Assoc = T;
}

struct W<'a>(&'a <[f32; 0] as Mirror>::Assoc);

fn foo(x: W<'_>) -> *const f32 {
x.0 as *const f32
}

fn main() {}
1 change: 1 addition & 0 deletions tests/ui/check-cfg/target_feature.stderr
Original file line number Diff line number Diff line change
@@ -27,6 +27,7 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE");
`amx-tf32`
`amx-tile`
`amx-transpose`
`apxf`
`atomics`
`avx`
`avx10.1`
2 changes: 0 additions & 2 deletions tests/ui/feature-gates/bench.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
//@ edition:2018

#[bench] //~ ERROR use of unstable library feature `test`
//~| WARN this was previously accepted
fn bench() {}

use bench as _; //~ ERROR use of unstable library feature `test`
//~| WARN this was previously accepted
fn main() {}
40 changes: 10 additions & 30 deletions tests/ui/feature-gates/bench.stderr
Original file line number Diff line number Diff line change
@@ -1,43 +1,23 @@
error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
error[E0658]: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:3:3
|
LL | #[bench]
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
= note: `#[deny(soft_unstable)]` on by default
= note: see issue #50297 <https://github.com/rust-lang/rust/issues/50297> for more information
= help: add `#![feature(test)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:7:5
error[E0658]: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:6:5
|
LL | use bench as _;
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
= note: see issue #50297 <https://github.com/rust-lang/rust/issues/50297> for more information
= help: add `#![feature(test)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: aborting due to 2 previous errors

Future incompatibility report: Future breakage diagnostic:
error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:3:3
|
LL | #[bench]
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
= note: `#[deny(soft_unstable)]` on by default

Future breakage diagnostic:
error: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
--> $DIR/bench.rs:7:5
|
LL | use bench as _;
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
= note: `#[deny(soft_unstable)]` on by default

For more information about this error, try `rustc --explain E0658`.
6 changes: 6 additions & 0 deletions tests/ui/feature-gates/feature-gate-apx-target-feature.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
//@ only-x86_64
#[target_feature(enable = "apxf")]
//~^ ERROR: currently unstable
unsafe fn foo() {}

fn main() {}
13 changes: 13 additions & 0 deletions tests/ui/feature-gates/feature-gate-apx-target-feature.stderr
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
error[E0658]: the target feature `apxf` is currently unstable
--> $DIR/feature-gate-apx-target-feature.rs:2:18
|
LL | #[target_feature(enable = "apxf")]
| ^^^^^^^^^^^^^^^
|
= note: see issue #139284 <https://github.com/rust-lang/rust/issues/139284> for more information
= help: add `#![feature(apx_target_feature)]` to the crate attributes to enable
= note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date

error: aborting due to 1 previous error

For more information about this error, try `rustc --explain E0658`.
7 changes: 0 additions & 7 deletions tests/ui/lint/expansion-time.rs
Original file line number Diff line number Diff line change
@@ -9,13 +9,6 @@ macro_rules! foo {
macro_rules! m { ($i) => {} } //~ WARN missing fragment specifier
//~| WARN this was previously accepted

#[warn(soft_unstable)]
mod benches {
#[bench] //~ WARN use of unstable library feature `test`
//~| WARN this was previously accepted
fn foo() {}
}

#[deprecated = "reason"]
macro_rules! deprecated {
() => {}
33 changes: 2 additions & 31 deletions tests/ui/lint/expansion-time.stderr
Original file line number Diff line number Diff line change
@@ -26,33 +26,19 @@ note: the lint level is defined here
LL | #[warn(missing_fragment_specifier)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
--> $DIR/expansion-time.rs:14:7
|
LL | #[bench]
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
note: the lint level is defined here
--> $DIR/expansion-time.rs:12:8
|
LL | #[warn(soft_unstable)]
| ^^^^^^^^^^^^^

warning: include macro expected single expression in source
--> $DIR/expansion-time-include.rs:4:1
|
LL | 2
| ^
|
note: the lint level is defined here
--> $DIR/expansion-time.rs:29:8
--> $DIR/expansion-time.rs:22:8
|
LL | #[warn(incomplete_include)]
| ^^^^^^^^^^^^^^^^^^

warning: 4 warnings emitted
warning: 3 warnings emitted

Future incompatibility report: Future breakage diagnostic:
warning: missing fragment specifier
@@ -69,18 +55,3 @@ note: the lint level is defined here
LL | #[warn(missing_fragment_specifier)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^

Future breakage diagnostic:
warning: use of unstable library feature `test`: `bench` is a part of custom test frameworks which are unstable
--> $DIR/expansion-time.rs:14:7
|
LL | #[bench]
| ^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= note: for more information, see issue #64266 <https://github.com/rust-lang/rust/issues/64266>
note: the lint level is defined here
--> $DIR/expansion-time.rs:12:8
|
LL | #[warn(soft_unstable)]
| ^^^^^^^^^^^^^

Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
//@ revisions: current next
//@ ignore-compare-mode-next-solver (explicit revisions)
//@[next] compile-flags: -Znext-solver
//@ check-pass
#![crate_type = "lib"]
trait Eq<T> {}
impl<T> Eq<T> for T {}
trait ConstrainAndEq<T> {}
impl<T, U> ConstrainAndEq<T> for U
where
T: FnOnce() -> u32,
U: FnOnce() -> u32,
T: Eq<U>,
{}

fn constrain_and_eq<T: ConstrainAndEq<U>, U>(_: T, _: U) {}
fn foo<'a>() -> impl Sized + use<'a> {
// This proves `foo<'a>: FnOnce() -> u32` and `foo<'1>: FnOnce() -> u32`,
// We constrain both `opaque<'a>` and `opaque<'1>` to `u32`, resulting in
// two distinct opaque type uses. Proving `foo<'a>: Eq<foo<'1>>` then
// equates the two regions at which point the two opaque type keys are now
// equal. This previously caused an ICE.
constrain_and_eq(foo::<'a>, foo::<'_>);
1u32
}