Auto merge of #150957 - matthiaskrgr:rollup-Cf6MsNU, r=matthiaskrgr

Rollup of 14 pull requests

Successful merges:

 - rust-lang/rust#148941 (stabilize `Peekable::next_if_map` (`#![feature(peekable_next_if_map)]`))
 - rust-lang/rust#150368 (adding Ordering enum to minicore.rs, importing minicore in "tests/assembly-llvm/rust-abi-arg-attr.rs" test file)
 - rust-lang/rust#150668 (Unix implementation for stdio set/take/replace)
 - rust-lang/rust#150743 (Reword the collect() docs)
 - rust-lang/rust#150776 (Fix the connect_error test on FreeBSD 15+)
 - rust-lang/rust#150781 (Use `rand` crate more idiomatically)
 - rust-lang/rust#150812 (Bump `diesel` to the most recent commit in `cargotest`)
 - rust-lang/rust#150862 (std: sys: fs: uefi: Implement File::flush)
 - rust-lang/rust#150873 (Reenable GCC CI download)
 - rust-lang/rust#150908 (llvm: Update `reliable_f16` configuration for LLVM22)
 - rust-lang/rust#150918 (std: sys: fs: uefi: Implement File::seek)
 - rust-lang/rust#150922 (Subscribe myself to attr parsing)
 - rust-lang/rust#150930 (Remove special case for `AllowedTargets::CrateLevel`)
 - rust-lang/rust#150942 (Port `#[rustc_has_incoherent_inherent_impls]` to attribute parser)

Failed merges:

 - rust-lang/rust#150943 (Port `#[must_not_suspend]` to attribute parser)

r? @ghost
This commit is contained in:
rust-bors[bot] 2026-01-11 12:16:33 +00:00 committed by GitHub
commit 1279939b38
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
33 changed files with 332 additions and 188 deletions

View file

@ -9,7 +9,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(n) = args else {
@ -33,7 +33,7 @@ impl<S: Stage> SingleAttributeParser<S> for RecursionLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N", "https://doc.rust-lang.org/reference/attributes/limits.html#the-recursion_limit-attribute");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
@ -56,7 +56,7 @@ impl<S: Stage> SingleAttributeParser<S> for MoveSizeLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
@ -79,7 +79,7 @@ impl<S: Stage> SingleAttributeParser<S> for TypeLengthLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
@ -102,7 +102,7 @@ impl<S: Stage> SingleAttributeParser<S> for PatternComplexityLimitParser {
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
let ArgParser::NameValue(nv) = args else {
@ -123,7 +123,7 @@ pub(crate) struct NoCoreParser;
impl<S: Stage> NoArgsAttributeParser<S> for NoCoreParser {
const PATH: &[Symbol] = &[sym::no_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoCore;
}
@ -132,7 +132,7 @@ pub(crate) struct NoStdParser;
impl<S: Stage> NoArgsAttributeParser<S> for NoStdParser {
const PATH: &[Symbol] = &[sym::no_std];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::NoStd;
}
@ -141,7 +141,7 @@ pub(crate) struct RustcCoherenceIsCoreParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcCoherenceIsCoreParser {
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoherenceIsCore;
}
@ -151,7 +151,7 @@ impl<S: Stage> SingleAttributeParser<S> for WindowsSubsystemParser {
const PATH: &[Symbol] = &[sym::windows_subsystem];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::CrateLevel;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
const TEMPLATE: AttributeTemplate = template!(NameValueStr: ["windows", "console"], "https://doc.rust-lang.org/reference/runtime.html#the-windows_subsystem-attribute");
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {

View file

@ -305,3 +305,18 @@ impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser {
Some(AttributeKind::RustcScalableVector { element_count: Some(n), span: cx.attr_span })
}
}
pub(crate) struct RustcHasIncoherentInherentImplsParser;
impl<S: Stage> NoArgsAttributeParser<S> for RustcHasIncoherentInherentImplsParser {
const PATH: &[Symbol] = &[sym::rustc_has_incoherent_inherent_impls];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
Allow(Target::Trait),
Allow(Target::Struct),
Allow(Target::Enum),
Allow(Target::Union),
Allow(Target::ForeignTy),
]);
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;
}

View file

@ -4,12 +4,12 @@ use std::ops::{Deref, DerefMut};
use std::sync::LazyLock;
use private::Sealed;
use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
use rustc_errors::{Diag, Diagnostic, Level};
use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
use rustc_hir::{AttrPath, HirId};
use rustc_session::Session;
use rustc_session::lint::{Lint, LintId};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
@ -62,12 +62,12 @@ use crate::attributes::proc_macro_attrs::{
use crate::attributes::prototype::CustomMirParser;
use crate::attributes::repr::{AlignParser, AlignStaticParser, ReprParser};
use crate::attributes::rustc_internal::{
RustcLayoutScalarValidRangeEndParser, RustcLayoutScalarValidRangeStartParser,
RustcLegacyConstGenericsParser, RustcLintDiagnosticsParser, RustcLintOptDenyFieldAccessParser,
RustcLintOptTyParser, RustcLintQueryInstabilityParser,
RustcLintUntrackedQueryInformationParser, RustcMainParser, RustcMustImplementOneOfParser,
RustcNeverReturnsNullPointerParser, RustcNoImplicitAutorefsParser,
RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
RustcHasIncoherentInherentImplsParser, RustcLayoutScalarValidRangeEndParser,
RustcLayoutScalarValidRangeStartParser, RustcLegacyConstGenericsParser,
RustcLintDiagnosticsParser, RustcLintOptDenyFieldAccessParser, RustcLintOptTyParser,
RustcLintQueryInstabilityParser, RustcLintUntrackedQueryInformationParser, RustcMainParser,
RustcMustImplementOneOfParser, RustcNeverReturnsNullPointerParser,
RustcNoImplicitAutorefsParser, RustcObjectLifetimeDefaultParser, RustcScalableVectorParser,
RustcSimdMonomorphizeLaneLimitParser,
};
use crate::attributes::semantics::MayDangleParser;
@ -264,6 +264,7 @@ attribute_parsers!(
Single<WithoutArgs<ProcMacroParser>>,
Single<WithoutArgs<PubTransparentParser>>,
Single<WithoutArgs<RustcCoherenceIsCoreParser>>,
Single<WithoutArgs<RustcHasIncoherentInherentImplsParser>>,
Single<WithoutArgs<RustcLintDiagnosticsParser>>,
Single<WithoutArgs<RustcLintOptTyParser>>,
Single<WithoutArgs<RustcLintQueryInstabilityParser>>,
@ -303,8 +304,6 @@ pub trait Stage: Sized + 'static + Sealed {
) -> ErrorGuaranteed;
fn should_emit(&self) -> ShouldEmit;
fn id_is_crate_root(id: Self::Id) -> bool;
}
// allow because it's a sealed trait
@ -326,10 +325,6 @@ impl Stage for Early {
fn should_emit(&self) -> ShouldEmit {
self.emit_errors
}
fn id_is_crate_root(id: Self::Id) -> bool {
id == CRATE_NODE_ID
}
}
// allow because it's a sealed trait
@ -351,10 +346,6 @@ impl Stage for Late {
fn should_emit(&self) -> ShouldEmit {
ShouldEmit::ErrorsAndLints
}
fn id_is_crate_root(id: Self::Id) -> bool {
id == CRATE_HIR_ID
}
}
/// used when parsing attributes for miscellaneous things *before* ast lowering

View file

@ -15,11 +15,6 @@ use crate::session_diagnostics::InvalidTarget;
pub(crate) enum AllowedTargets {
AllowList(&'static [Policy]),
AllowListWarnRest(&'static [Policy]),
/// Special, and not the same as `AllowList(&[Allow(Target::Crate)])`.
/// For crate-level attributes we emit a specific set of lints to warn
/// people about accidentally not using them on the crate.
/// Only use this for attributes that are *exclusively* valid at the crate level.
CrateLevel,
}
pub(crate) enum AllowedResult {
@ -53,7 +48,6 @@ impl AllowedTargets {
AllowedResult::Warn
}
}
AllowedTargets::CrateLevel => AllowedResult::Allowed,
}
}
@ -61,7 +55,6 @@ impl AllowedTargets {
match self {
AllowedTargets::AllowList(list) => list,
AllowedTargets::AllowListWarnRest(list) => list,
AllowedTargets::CrateLevel => ALL_TARGETS,
}
.iter()
.filter_map(|target| match target {
@ -95,7 +88,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
target: Target,
cx: &mut AcceptContext<'_, 'sess, S>,
) {
Self::check_type(matches!(allowed_targets, AllowedTargets::CrateLevel), target, cx);
if allowed_targets.allowed_targets() == &[Target::Crate] {
Self::check_crate_level(target, cx);
return;
}
match allowed_targets.is_allowed(target) {
AllowedResult::Allowed => {}
@ -149,18 +145,10 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
}
}
pub(crate) fn check_type(
crate_level: bool,
target: Target,
cx: &mut AcceptContext<'_, 'sess, S>,
) {
let is_crate_root = S::id_is_crate_root(cx.target_id);
if is_crate_root {
return;
}
if !crate_level {
pub(crate) fn check_crate_level(target: Target, cx: &mut AcceptContext<'_, 'sess, S>) {
// For crate-level attributes we emit a specific set of lints to warn
// people about accidentally not using them on the crate.
if target == Target::Crate {
return;
}

View file

@ -379,19 +379,19 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
{
false
}
// Unsupported <https://github.com/llvm/llvm-project/issues/94434>
(Arch::Arm64EC, _) => false,
// Unsupported <https://github.com/llvm/llvm-project/issues/94434> (fixed in llvm22)
(Arch::Arm64EC, _) if major < 22 => false,
// Selection failure <https://github.com/llvm/llvm-project/issues/50374> (fixed in llvm21)
(Arch::S390x, _) if major < 21 => false,
// MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
(Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != Abi::Llvm => false,
// Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
(Arch::CSky, _) => false,
(Arch::CSky, _) if major < 22 => false, // (fixed in llvm22)
(Arch::Hexagon, _) if major < 21 => false, // (fixed in llvm21)
(Arch::LoongArch32 | Arch::LoongArch64, _) if major < 21 => false, // (fixed in llvm21)
(Arch::PowerPC | Arch::PowerPC64, _) => false,
(Arch::Sparc | Arch::Sparc64, _) => false,
(Arch::Wasm32 | Arch::Wasm64, _) => false,
(Arch::PowerPC | Arch::PowerPC64, _) if major < 22 => false, // (fixed in llvm22)
(Arch::Sparc | Arch::Sparc64, _) if major < 22 => false, // (fixed in llvm22)
(Arch::Wasm32 | Arch::Wasm64, _) if major < 22 => false, // (fixed in llvm22)
// `f16` support only requires that symbols converting to and from `f32` are available. We
// provide these in `compiler-builtins`, so `f16` should be available on all platforms that
// do not have other ABI issues or LLVM crashes.

View file

@ -880,6 +880,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_coherence_is_core]`
RustcCoherenceIsCore(Span),
/// Represents `#[rustc_has_incoherent_inherent_impls]`
RustcHasIncoherentInherentImpls,
/// Represents `#[rustc_layout_scalar_valid_range_end]`.
RustcLayoutScalarValidRangeEnd(Box<u128>, Span),

View file

@ -95,6 +95,7 @@ impl AttributeKind {
Repr { .. } => No,
RustcBuiltinMacro { .. } => Yes,
RustcCoherenceIsCore(..) => No,
RustcHasIncoherentInherentImpls => Yes,
RustcLayoutScalarValidRangeEnd(..) => Yes,
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcLegacyConstGenerics { .. } => Yes,

View file

@ -15,7 +15,7 @@ use rustc_hir::find_attr;
use rustc_middle::bug;
use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams, simplify_type};
use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt};
use rustc_span::{ErrorGuaranteed, sym};
use rustc_span::ErrorGuaranteed;
use crate::errors;
@ -79,7 +79,10 @@ impl<'tcx> InherentCollect<'tcx> {
}
if self.tcx.features().rustc_attrs() {
if !self.tcx.has_attr(ty_def_id, sym::rustc_has_incoherent_inherent_impls) {
if !find_attr!(
self.tcx.get_all_attrs(ty_def_id),
AttributeKind::RustcHasIncoherentInherentImpls
) {
let impl_span = self.tcx.def_span(impl_def_id);
return Err(self.tcx.dcx().emit_err(errors::InherentTyOutside { span: impl_span }));
}

View file

@ -2,11 +2,11 @@ use std::iter;
use rustc_data_structures::fx::FxIndexMap;
use rustc_errors::ErrorGuaranteed;
use rustc_hir as hir;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::{self as hir, find_attr};
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_span::symbol::sym;
use tracing::debug;
use crate::query::LocalCrate;
@ -241,7 +241,7 @@ pub(super) fn trait_impls_of_provider(tcx: TyCtxt<'_>, trait_id: DefId) -> Trait
/// Query provider for `incoherent_impls`.
pub(super) fn incoherent_impls_provider(tcx: TyCtxt<'_>, simp: SimplifiedType) -> &[DefId] {
if let Some(def_id) = simp.def()
&& !tcx.has_attr(def_id, sym::rustc_has_incoherent_inherent_impls)
&& !find_attr!(tcx.get_all_attrs(def_id), AttributeKind::RustcHasIncoherentInherentImpls)
{
return &[];
}

View file

@ -244,10 +244,6 @@ passes_function_not_have_default_implementation = function doesn't have a defaul
passes_functions_names_duplicated = functions names are duplicated
.note = all `#[rustc_must_implement_one_of]` arguments must be unique
passes_has_incoherent_inherent_impl =
`rustc_has_incoherent_inherent_impls` attribute should be applied to types or traits
.label = only adts, extern types and traits are supported
passes_ignored_derived_impls =
`{$name}` has {$trait_list_len ->
[one] a derived impl

View file

@ -306,6 +306,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| AttributeKind::CfgAttrTrace
| AttributeKind::ThreadLocal
| AttributeKind::CfiEncoding { .. }
| AttributeKind::RustcHasIncoherentInherentImpls
) => { /* do nothing */ }
Attribute::Unparsed(attr_item) => {
style = Some(attr_item.style);
@ -325,9 +326,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr),
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
[sym::rustc_has_incoherent_inherent_impls, ..] => {
self.check_has_incoherent_inherent_impls(attr, span, target)
}
[sym::autodiff_forward, ..] | [sym::autodiff_reverse, ..] => {
self.check_autodiff(hir_id, attr, span, target)
}
@ -1164,17 +1162,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_has_incoherent_inherent_impls(&self, attr: &Attribute, span: Span, target: Target) {
match target {
Target::Trait | Target::Struct | Target::Enum | Target::Union | Target::ForeignTy => {}
_ => {
self.tcx
.dcx()
.emit_err(errors::HasIncoherentInherentImpl { attr_span: attr.span(), span });
}
}
}
fn check_ffi_pure(&self, attr_span: Span, attrs: &[Attribute]) {
if find_attr!(attrs, AttributeKind::FfiConst(_)) {
// `#[ffi_const]` functions cannot be `#[ffi_pure]`

View file

@ -187,15 +187,6 @@ pub(crate) struct DocAttrNotCrateLevel<'a> {
pub attr_name: &'a str,
}
#[derive(Diagnostic)]
#[diag(passes_has_incoherent_inherent_impl)]
pub(crate) struct HasIncoherentInherentImpl {
#[primary_span]
pub attr_span: Span,
#[label]
pub span: Span,
}
#[derive(Diagnostic)]
#[diag(passes_both_ffi_const_and_pure, code = E0757)]
pub(crate) struct BothFfiConstAndPure {

View file

@ -2,6 +2,7 @@ use std::collections::BTreeMap;
use std::ops::RangeBounds;
use rand::Rng;
use rand::distr::{Distribution, Uniform};
use rand::seq::SliceRandom;
use test::{Bencher, black_box};
@ -106,7 +107,8 @@ macro_rules! map_find_rand_bench {
// setup
let mut rng = crate::bench_rng();
let mut keys: Vec<_> = (0..n).map(|_| rng.random::<u32>() % n).collect();
let mut keys: Vec<_> =
Uniform::new(0, n).unwrap().sample_iter(&mut rng).take(n as usize).collect();
for &k in &keys {
map.insert(k, k);

View file

@ -27,21 +27,20 @@ where
{
// :.:.:.::
let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed());
let rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed());
// Abstracting over ranges in Rust :(
let dist = Uniform::try_from(range).unwrap();
(0..len).map(|_| dist.sample(&mut rng)).collect()
rng.sample_iter(dist).take(len).collect()
}
pub fn random_zipf(len: usize, exponent: f64) -> Vec<i32> {
// https://en.wikipedia.org/wiki/Zipf's_law
let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed());
let rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed());
// Abstracting over ranges in Rust :(
let dist = ZipfDistribution::new(len, exponent).unwrap();
(0..len).map(|_| dist.sample(&mut rng) as i32).collect()
rng.sample_iter(dist).map(|val| val as i32).take(len).collect()
}
pub fn random_sorted(len: usize, sorted_percent: f64) -> Vec<i32> {
@ -68,7 +67,7 @@ pub fn all_equal(len: usize) -> Vec<i32> {
// ......
// ::::::
(0..len).map(|_| 66).collect::<Vec<_>>()
vec![66; len]
}
pub fn ascending(len: usize) -> Vec<i32> {
@ -206,6 +205,6 @@ fn rand_root_seed() -> u64 {
}
fn random_vec(len: usize) -> Vec<i32> {
let mut rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed());
(0..len).map(|_| rng.random::<i32>()).collect()
let rng: XorShiftRng = rand::SeedableRng::seed_from_u64(get_or_init_rand_seed());
rng.random_iter().take(len).collect()
}

View file

@ -337,7 +337,6 @@ impl<I: Iterator> Peekable<I> {
///
/// Parse the leading decimal number from an iterator of characters.
/// ```
/// #![feature(peekable_next_if_map)]
/// let mut iter = "125 GOTO 10".chars().peekable();
/// let mut line_num = 0_u32;
/// while let Some(digit) = iter.next_if_map(|c| c.to_digit(10).ok_or(c)) {
@ -349,7 +348,6 @@ impl<I: Iterator> Peekable<I> {
///
/// Matching custom types.
/// ```
/// #![feature(peekable_next_if_map)]
///
/// #[derive(Debug, PartialEq, Eq)]
/// enum Node {
@ -408,7 +406,7 @@ impl<I: Iterator> Peekable<I> {
///# ],
///# )
/// ```
#[unstable(feature = "peekable_next_if_map", issue = "143702")]
#[stable(feature = "peekable_next_if_map", since = "CURRENT_RUSTC_VERSION")]
pub fn next_if_map<R>(&mut self, f: impl FnOnce(I::Item) -> Result<R, I::Item>) -> Option<R> {
let unpeek = if let Some(item) = self.next() {
match f(item) {
@ -437,7 +435,6 @@ impl<I: Iterator> Peekable<I> {
///
/// Parse the leading decimal number from an iterator of characters.
/// ```
/// #![feature(peekable_next_if_map)]
/// let mut iter = "125 GOTO 10".chars().peekable();
/// let mut line_num = 0_u32;
/// while let Some(digit) = iter.next_if_map_mut(|c| c.to_digit(10)) {
@ -446,7 +443,7 @@ impl<I: Iterator> Peekable<I> {
/// assert_eq!(line_num, 125);
/// assert_eq!(iter.collect::<String>(), " GOTO 10");
/// ```
#[unstable(feature = "peekable_next_if_map", issue = "143702")]
#[stable(feature = "peekable_next_if_map", since = "CURRENT_RUSTC_VERSION")]
pub fn next_if_map_mut<R>(&mut self, f: impl FnOnce(&mut I::Item) -> Option<R>) -> Option<R> {
let unpeek = if let Some(mut item) = self.next() {
match f(&mut item) {

View file

@ -1906,9 +1906,12 @@ pub trait Iterator {
/// Transforms an iterator into a collection.
///
/// `collect()` can take anything iterable, and turn it into a relevant
/// collection. This is one of the more powerful methods in the standard
/// library, used in a variety of contexts.
/// `collect()` takes ownership of an iterator and produces whichever
/// collection type you request. The iterator itself carries no knowledge of
/// the eventual container; the target collection is chosen entirely by the
/// type you ask `collect()` to return. This makes `collect()` one of the
/// more powerful methods in the standard library, and it shows up in a wide
/// variety of contexts.
///
/// The most basic pattern in which `collect()` is used is to turn one
/// collection into another. You take a collection, call [`iter`] on it,

View file

@ -4,11 +4,12 @@ macro_rules! bench_template {
($op:path, $name:ident, $mask:expr) => {
#[bench]
fn $name(bench: &mut ::test::Bencher) {
use ::rand::Rng;
use ::rand::distr::{Distribution, Uniform};
let mut rng = crate::bench_rng();
let mut dst = vec![0; ITERATIONS];
let src1: Vec<U> = (0..ITERATIONS).map(|_| rng.random_range(0..=U::MAX)).collect();
let mut src2: Vec<U> = (0..ITERATIONS).map(|_| rng.random_range(0..=U::MAX)).collect();
let distr = &Uniform::try_from(0..=U::MAX).unwrap();
let src1: Vec<U> = distr.sample_iter(&mut rng).take(ITERATIONS).collect();
let mut src2: Vec<U> = distr.sample_iter(&mut rng).take(ITERATIONS).collect();
// Fix the loop invariant mask
src2[0] = U::MAX / 3;
let dst = dst.first_chunk_mut().unwrap();

View file

@ -1,3 +1,5 @@
use std::iter;
use rand::Rng;
use test::{Bencher, black_box};
@ -20,7 +22,9 @@ macro_rules! int_sqrt_bench {
let mut rng = crate::bench_rng();
/* Exponentially distributed random numbers from the whole range of the type. */
let numbers: Vec<$t> =
(0..256).map(|_| rng.random::<$t>() >> rng.random_range(0..<$t>::BITS)).collect();
iter::repeat_with(|| rng.random::<$t>() >> rng.random_range(0..<$t>::BITS))
.take(256)
.collect();
bench.iter(|| {
for x in &numbers {
black_box(black_box(x).isqrt());
@ -32,9 +36,10 @@ macro_rules! int_sqrt_bench {
fn $random_small(bench: &mut Bencher) {
let mut rng = crate::bench_rng();
/* Exponentially distributed random numbers from the range 0..256. */
let numbers: Vec<$t> = (0..256)
.map(|_| (rng.random::<u8>() >> rng.random_range(0..u8::BITS)) as $t)
.collect();
let numbers: Vec<$t> =
iter::repeat_with(|| (rng.random::<u8>() >> rng.random_range(0..u8::BITS)) as $t)
.take(256)
.collect();
bench.iter(|| {
for x in &numbers {
black_box(black_box(x).isqrt());
@ -44,9 +49,9 @@ macro_rules! int_sqrt_bench {
#[bench]
fn $random_uniform(bench: &mut Bencher) {
let mut rng = crate::bench_rng();
let rng = crate::bench_rng();
/* Exponentially distributed random numbers from the whole range of the type. */
let numbers: Vec<$t> = (0..256).map(|_| rng.random::<$t>()).collect();
let numbers: Vec<$t> = rng.random_iter().take(256).collect();
bench.iter(|| {
for x in &numbers {
black_box(black_box(x).isqrt());

View file

@ -90,7 +90,6 @@
#![feature(one_sided_range)]
#![feature(option_reduce)]
#![feature(pattern)]
#![feature(peekable_next_if_map)]
#![feature(pointer_is_aligned_to)]
#![feature(portable_simd)]
#![feature(ptr_metadata)]

View file

@ -37,7 +37,8 @@ fn connect_error() {
e.kind() == ErrorKind::ConnectionRefused
|| e.kind() == ErrorKind::InvalidInput
|| e.kind() == ErrorKind::AddrInUse
|| e.kind() == ErrorKind::AddrNotAvailable,
|| e.kind() == ErrorKind::AddrNotAvailable
|| e.kind() == ErrorKind::NetworkUnreachable,
"bad error: {} {:?}",
e,
e.kind()

View file

@ -92,9 +92,138 @@
#![stable(feature = "rust1", since = "1.0.0")]
use crate::io::{self, Stderr, StderrLock, Stdin, StdinLock, Stdout, StdoutLock, Write};
#[stable(feature = "rust1", since = "1.0.0")]
pub use crate::os::fd::*;
#[allow(unused_imports)] // not used on all targets
use crate::sys::cvt;
// Tests for this module
#[cfg(test)]
mod tests;
#[unstable(feature = "stdio_swap", issue = "150667", reason = "recently added")]
pub trait StdioExt: crate::sealed::Sealed {
/// Redirects the stdio file descriptor to point to the file description underpinning `fd`.
///
/// Rust std::io write buffers (if any) are flushed, but other runtimes
/// (e.g. C stdio) or libraries that acquire a clone of the file descriptor
/// will not be aware of this change.
///
/// # Platform-specific behavior
///
/// This is [currently] implemented using
///
/// - `fd_renumber` on wasip1
/// - `dup2` on most unixes
///
/// [currently]: crate::io#platform-specific-behavior
///
/// ```
/// #![feature(stdio_swap)]
/// use std::io::{self, Read, Write};
/// use std::os::unix::io::StdioExt;
///
/// fn main() -> io::Result<()> {
/// let (reader, mut writer) = io::pipe()?;
/// let mut stdin = io::stdin();
/// stdin.set_fd(reader)?;
/// writer.write_all(b"Hello, world!")?;
/// let mut buffer = vec![0; 13];
/// assert_eq!(stdin.read(&mut buffer)?, 13);
/// assert_eq!(&buffer, b"Hello, world!");
/// Ok(())
/// }
/// ```
fn set_fd<T: Into<OwnedFd>>(&mut self, fd: T) -> io::Result<()>;
/// Redirects the stdio file descriptor and returns a new `OwnedFd`
/// backed by the previous file description.
///
/// See [`set_fd()`] for details.
///
/// [`set_fd()`]: StdioExt::set_fd
fn replace_fd<T: Into<OwnedFd>>(&mut self, replace_with: T) -> io::Result<OwnedFd>;
/// Redirects the stdio file descriptor to the null device (`/dev/null`)
/// and returns a new `OwnedFd` backed by the previous file description.
///
/// Programs that communicate structured data via stdio can use this early in `main()` to
/// extract the fds, treat them as other IO types (`File`, `UnixStream`, etc),
/// apply custom buffering or avoid interference from stdio use later in the program.
///
/// See [`set_fd()`] for additional details.
///
/// [`set_fd()`]: StdioExt::set_fd
fn take_fd(&mut self) -> io::Result<OwnedFd>;
}
macro io_ext_impl($stdio_ty:ty, $stdio_lock_ty:ty, $writer:literal) {
#[unstable(feature = "stdio_swap", issue = "150667", reason = "recently added")]
impl StdioExt for $stdio_ty {
fn set_fd<T: Into<OwnedFd>>(&mut self, fd: T) -> io::Result<()> {
self.lock().set_fd(fd)
}
fn take_fd(&mut self) -> io::Result<OwnedFd> {
self.lock().take_fd()
}
fn replace_fd<T: Into<OwnedFd>>(&mut self, replace_with: T) -> io::Result<OwnedFd> {
self.lock().replace_fd(replace_with)
}
}
#[unstable(feature = "stdio_swap", issue = "150667", reason = "recently added")]
impl StdioExt for $stdio_lock_ty {
fn set_fd<T: Into<OwnedFd>>(&mut self, fd: T) -> io::Result<()> {
#[cfg($writer)]
self.flush()?;
replace_stdio_fd(self.as_fd(), fd.into())
}
fn take_fd(&mut self) -> io::Result<OwnedFd> {
let null = null_fd()?;
let cloned = self.as_fd().try_clone_to_owned()?;
self.set_fd(null)?;
Ok(cloned)
}
fn replace_fd<T: Into<OwnedFd>>(&mut self, replace_with: T) -> io::Result<OwnedFd> {
let cloned = self.as_fd().try_clone_to_owned()?;
self.set_fd(replace_with)?;
Ok(cloned)
}
}
}
io_ext_impl!(Stdout, StdoutLock<'_>, true);
io_ext_impl!(Stdin, StdinLock<'_>, false);
io_ext_impl!(Stderr, StderrLock<'_>, true);
fn null_fd() -> io::Result<OwnedFd> {
let null_dev = crate::fs::OpenOptions::new().read(true).write(true).open("/dev/null")?;
Ok(null_dev.into())
}
/// Replaces the underlying file descriptor with the one from `other`.
/// Does not set CLOEXEC.
fn replace_stdio_fd(this: BorrowedFd<'_>, other: OwnedFd) -> io::Result<()> {
cfg_select! {
all(target_os = "wasi", target_env = "p1") => {
cvt(unsafe { libc::__wasilibc_fd_renumber(other.as_raw_fd(), this.as_raw_fd()) }).map(|_| ())
}
not(any(
target_arch = "wasm32",
target_os = "hermit",
target_os = "trusty",
target_os = "motor"
)) => {
cvt(unsafe {libc::dup2(other.as_raw_fd(), this.as_raw_fd())}).map(|_| ())
}
_ => {
let _ = (this, other);
Err(io::Error::UNSUPPORTED_PLATFORM)
}
}
}

View file

@ -285,11 +285,11 @@ impl File {
}
pub fn fsync(&self) -> io::Result<()> {
unsupported()
self.datasync()
}
pub fn datasync(&self) -> io::Result<()> {
unsupported()
self.0.flush()
}
pub fn lock(&self) -> io::Result<()> {
@ -348,12 +348,29 @@ impl File {
false
}
// Write::flush is only meant for buffered writers. So should be noop for unbuffered files.
pub fn flush(&self) -> io::Result<()> {
unsupported()
Ok(())
}
pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
unsupported()
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
const NEG_OFF_ERR: io::Error =
io::const_error!(io::ErrorKind::InvalidInput, "cannot seek to negative offset.");
let off = match pos {
SeekFrom::Start(p) => p,
SeekFrom::End(p) => {
// Seeking to position 0xFFFFFFFFFFFFFFFF causes the current position to be set to the end of the file.
if p == 0 {
0xFFFFFFFFFFFFFFFF
} else {
self.file_attr()?.size().checked_add_signed(p).ok_or(NEG_OFF_ERR)?
}
}
SeekFrom::Current(p) => self.tell()?.checked_add_signed(p).ok_or(NEG_OFF_ERR)?,
};
self.0.set_position(off).map(|_| off)
}
pub fn size(&self) -> Option<io::Result<u64>> {
@ -774,6 +791,12 @@ mod uefi_fs {
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(pos) }
}
pub(crate) fn set_position(&self, pos: u64) -> io::Result<()> {
let file_ptr = self.protocol.as_ptr();
let r = unsafe { ((*file_ptr).set_position)(file_ptr, pos) };
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}
pub(crate) fn delete(self) -> io::Result<()> {
let file_ptr = self.protocol.as_ptr();
let r = unsafe { ((*file_ptr).delete)(file_ptr) };
@ -784,6 +807,12 @@ mod uefi_fs {
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}
pub(crate) fn flush(&self) -> io::Result<()> {
let file_ptr = self.protocol.as_ptr();
let r = unsafe { ((*file_ptr).flush)(file_ptr) };
if r.is_error() { Err(io::Error::from_raw_os_error(r.as_usize())) } else { Ok(()) }
}
pub(crate) fn path(&self) -> &Path {
&self.path
}

View file

@ -1,4 +1,4 @@
Change this file to make users of the `download-ci-gcc` configuration download
a new version of GCC from CI, even if the GCC submodule hasnt changed.
Last change is for: https://github.com/rust-lang/rust/pull/138051
Last change is for: https://github.com/rust-lang/rust/pull/150873

View file

@ -396,7 +396,7 @@ impl Config {
";
self.download_file(&format!("{base}/{gcc_sha}/{filename}"), &tarball, help_on_error);
}
self.unpack(&tarball, root_dir, "gcc");
self.unpack(&tarball, root_dir, "gcc-dev");
}
}

View file

@ -187,9 +187,8 @@ else
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.static-libstdcpp"
fi
# Download GCC from CI on test builders (temporarily disabled because the CI gcc component
# was renamed).
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set gcc.download-ci-gcc=false"
# Download GCC from CI on test builders
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set gcc.download-ci-gcc=true"
# download-rustc seems to be broken on CI after the stage0 redesign
# Disable it until these issues are debugged and resolved

View file

@ -84,7 +84,7 @@ const TEST_REPOS: &[Test] = &[
Test {
name: "diesel",
repo: "https://github.com/diesel-rs/diesel",
sha: "91493fe47175076f330ce5fc518f0196c0476f56",
sha: "3db7c17c5b069656ed22750e84d6498c8ab5b81d",
lock: None,
packages: &[],
// Test the embedded sqlite variant of diesel

View file

@ -249,6 +249,15 @@ impl FileDescription for io::Stdin {
finish.call(ecx, result)
}
fn destroy<'tcx>(
self,
_self_id: FdId,
_communicate_allowed: bool,
_ecx: &mut MiriInterpCx<'tcx>,
) -> InterpResult<'tcx, io::Result<()>> {
interp_ok(Ok(()))
}
fn is_tty(&self, communicate_allowed: bool) -> bool {
communicate_allowed && self.is_terminal()
}
@ -279,6 +288,15 @@ impl FileDescription for io::Stdout {
finish.call(ecx, result)
}
fn destroy<'tcx>(
self,
_self_id: FdId,
_communicate_allowed: bool,
_ecx: &mut MiriInterpCx<'tcx>,
) -> InterpResult<'tcx, io::Result<()>> {
interp_ok(Ok(()))
}
fn is_tty(&self, communicate_allowed: bool) -> bool {
communicate_allowed && self.is_terminal()
}
@ -289,6 +307,15 @@ impl FileDescription for io::Stderr {
"stderr"
}
fn destroy<'tcx>(
self,
_self_id: FdId,
_communicate_allowed: bool,
_ecx: &mut MiriInterpCx<'tcx>,
) -> InterpResult<'tcx, io::Result<()>> {
interp_ok(Ok(()))
}
fn write<'tcx>(
self: FileDescriptionRef<Self>,
_communicate_allowed: bool,
@ -436,6 +463,15 @@ impl FileDescription for NullOutput {
// We just don't write anything, but report to the user that we did.
finish.call(ecx, Ok(len))
}
fn destroy<'tcx>(
self,
_self_id: FdId,
_communicate_allowed: bool,
_ecx: &mut MiriInterpCx<'tcx>,
) -> InterpResult<'tcx, io::Result<()>> {
interp_ok(Ok(()))
}
}
/// Internal type of a file-descriptor - this is what [`FdTable`] expects

View file

@ -1,10 +0,0 @@
//@ignore-target: windows # No libc IO on Windows
//@compile-flags: -Zmiri-disable-isolation
// FIXME: standard handles cannot be closed (https://github.com/rust-lang/rust/issues/40032)
fn main() {
unsafe {
libc::close(1); //~ ERROR: cannot close stdout
}
}

View file

@ -1,12 +0,0 @@
error: unsupported operation: cannot close stdout
--> tests/fail-dep/libc/fs/close_stdout.rs:LL:CC
|
LL | libc::close(1);
| ^^^^^^^^^^^^^^ unsupported operation occurred here
|
= help: this is likely not a bug in the program; it indicates that the program performed an operation that Miri does not support
note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
error: aborting due to 1 previous error

View file

@ -48,6 +48,7 @@ fn main() {
test_nofollow_not_symlink();
#[cfg(target_os = "macos")]
test_ioctl();
test_close_stdout();
}
fn test_file_open_unix_allow_two_args() {
@ -579,3 +580,11 @@ fn test_ioctl() {
assert_eq!(libc::ioctl(fd, libc::FIOCLEX), 0);
}
}
fn test_close_stdout() {
// This is std library UB, but that's not relevant since we're
// only interacting with libc here.
unsafe {
libc::close(1);
}
}

View file

@ -1,3 +1,4 @@
//@ add-minicore
//@ assembly-output: emit-asm
//@ revisions: riscv64 riscv64-zbb loongarch64
//@ compile-flags: -C opt-level=3
@ -14,45 +15,8 @@
#![no_std]
#![no_core]
// FIXME: Migrate these code after PR #130693 is landed.
#[lang = "pointee_sized"]
pub trait PointeeSized {}
#[lang = "meta_sized"]
pub trait MetaSized: PointeeSized {}
#[lang = "sized"]
pub trait Sized: MetaSized {}
#[lang = "copy"]
trait Copy {}
impl Copy for i8 {}
impl Copy for u32 {}
impl Copy for i32 {}
#[lang = "neg"]
trait Neg {
type Output;
fn neg(self) -> Self::Output;
}
impl Neg for i8 {
type Output = i8;
fn neg(self) -> Self::Output {
-self
}
}
#[lang = "Ordering"]
#[repr(i8)]
enum Ordering {
Less = -1,
Equal = 0,
Greater = 1,
}
extern crate minicore;
use minicore::*;
#[rustc_intrinsic]
fn three_way_compare<T: Copy>(lhs: T, rhs: T) -> Ordering;

View file

@ -210,6 +210,14 @@ impl Neg for isize {
}
}
impl Neg for i8 {
type Output = i8;
fn neg(self) -> i8 {
loop {}
}
}
#[lang = "sync"]
pub trait Sync {}
impl_marker_trait!(
@ -280,6 +288,16 @@ pub enum c_void {
__variant2,
}
#[lang = "Ordering"]
#[repr(i8)]
pub enum Ordering {
Less = -1,
Equal = 0,
Greater = 1,
}
impl Copy for Ordering {}
#[lang = "const_param_ty"]
#[diagnostic::on_unimplemented(message = "`{Self}` can't be used as a const parameter type")]
pub trait ConstParamTy_ {}

View file

@ -1365,11 +1365,11 @@ message = "The rustc-dev-guide subtree was changed. If this PR *only* touches th
cc = ["@BoxyUwU", "@jieyouxu", "@kobzol", "@tshepang"]
[mentions."compiler/rustc_passes/src/check_attr.rs"]
cc = ["@jdonszelmann"]
cc = ["@jdonszelmann", "@JonathanBrouwer"]
[mentions."compiler/rustc_attr_parsing"]
cc = ["@jdonszelmann"]
cc = ["@jdonszelmann", "@JonathanBrouwer"]
[mentions."compiler/rustc_hir/src/attrs"]
cc = ["@jdonszelmann"]
cc = ["@jdonszelmann", "@JonathanBrouwer"]
[mentions."src/tools/enzyme"]
cc = ["@ZuseZ4"]