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:
commit
1279939b38
33 changed files with 332 additions and 188 deletions
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
|
||||
|
|
|
|||
|
|
@ -95,6 +95,7 @@ impl AttributeKind {
|
|||
Repr { .. } => No,
|
||||
RustcBuiltinMacro { .. } => Yes,
|
||||
RustcCoherenceIsCore(..) => No,
|
||||
RustcHasIncoherentInherentImpls => Yes,
|
||||
RustcLayoutScalarValidRangeEnd(..) => Yes,
|
||||
RustcLayoutScalarValidRangeStart(..) => Yes,
|
||||
RustcLegacyConstGenerics { .. } => Yes,
|
||||
|
|
|
|||
|
|
@ -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 }));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 &[];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]`
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 hasn’t 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
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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_ {}
|
||||
|
|
|
|||
|
|
@ -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"]
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue