Auto merge of #143810 - matthiaskrgr:rollup-iw7a23z, r=matthiaskrgr

Rollup of 9 pull requests

Successful merges:

 - rust-lang/rust#143403 (Port several trait/coherence-related attributes the new attribute system)
 - rust-lang/rust#143633 (fix: correct assertion to check for 'noinline' attribute presence before removal)
 - rust-lang/rust#143647 (Clarify and expand documentation for std::sys_common dependency structure)
 - rust-lang/rust#143716 (compiler: doc/comment some codegen-for-functions interfaces)
 - rust-lang/rust#143747 (Add target maintainer information for aarch64-unknown-linux-musl)
 - rust-lang/rust#143759 (Fix typos in function names in the `target_feature` test)
 - rust-lang/rust#143767 (Bump `src/tools/x` to Edition 2024 and some cleanups)
 - rust-lang/rust#143769 (Remove support for SwitchInt edge effects in backward dataflow)
 - rust-lang/rust#143770 (build-helper: clippy fixes)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-07-12 10:46:43 +00:00
commit 915e535244
32 changed files with 432 additions and 194 deletions

View file

@ -198,6 +198,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_allow_const_fn_unstable]`.
AllowConstFnUnstable(ThinVec<Symbol>, Span),
/// Represents `#[rustc_allow_incoherent_impl]`.
AllowIncoherentImpl(Span),
/// Represents `#[allow_internal_unstable]`.
AllowInternalUnstable(ThinVec<(Symbol, Span)>, Span),
@ -211,6 +214,12 @@ pub enum AttributeKind {
span: Span,
},
/// Represents `#[rustc_coherence_is_core]`.
CoherenceIsCore,
/// Represents `#[rustc_coinductive]`.
Coinductive(Span),
/// Represents `#[cold]`.
Cold(Span),
@ -234,9 +243,18 @@ pub enum AttributeKind {
/// Represents `#[rustc_const_stable_indirect]`.
ConstStabilityIndirect,
/// Represents `#[const_trait]`.
ConstTrait(Span),
///Represents `#[rustc_deny_explicit_impl]`.
DenyExplicitImpl(Span),
/// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
Deprecation { deprecation: Deprecation, span: Span },
/// Represents `#[rustc_do_not_implement_via_object]`.
DoNotImplementViaObject(Span),
/// Represents [`#[doc]`](https://doc.rust-lang.org/stable/rustdoc/write-documentation/the-doc-attribute.html).
DocComment { style: AttrStyle, kind: CommentKind, span: Span, comment: Symbol },
@ -260,6 +278,9 @@ pub enum AttributeKind {
/// Represents `#[ffi_pure]`.
FfiPure(Span),
/// Represents `#[fundamental]`.
Fundamental,
/// Represents `#[ignore]`
Ignore {
span: Span,
@ -282,6 +303,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_macro_transparency]`.
MacroTransparency(Transparency),
/// Represents `#[marker]`.
Marker(Span),
/// Represents [`#[may_dangle]`](https://std-dev-guide.rust-lang.org/tricky/may-dangle.html).
MayDangle(Span),
@ -307,6 +331,9 @@ pub enum AttributeKind {
/// Represents `#[optimize(size|speed)]`
Optimize(OptimizeAttr, Span),
/// Represents `#[rustc_paren_sugar]`.
ParenSugar(Span),
/// Represents `#[rustc_pass_by_value]` (used by the `rustc_pass_by_value` lint).
PassByValue(Span),
@ -331,6 +358,9 @@ pub enum AttributeKind {
/// Represents `#[rustc_skip_during_method_dispatch]`.
SkipDuringMethodDispatch { array: bool, boxed_slice: bool, span: Span },
/// Represents `#[rustc_specialization_trait]`.
SpecializationTrait(Span),
/// Represents `#[stable]`, `#[unstable]` and `#[rustc_allowed_through_unstable_modules]`.
Stability {
stability: Stability,
@ -347,6 +377,12 @@ pub enum AttributeKind {
/// Represents `#[track_caller]`
TrackCaller(Span),
/// Represents `#[type_const]`.
TypeConst(Span),
/// Represents `#[rustc_unsafe_specialization_marker]`.
UnsafeSpecializationMarker(Span),
/// Represents `#[used]`
Used { used_by: UsedBy, span: Span },
// tidy-alphabetical-end

View file

@ -15,27 +15,35 @@ impl AttributeKind {
// tidy-alphabetical-start
Align { .. } => No,
AllowConstFnUnstable(..) => No,
AllowIncoherentImpl(..) => No,
AllowInternalUnstable(..) => Yes,
AsPtr(..) => Yes,
BodyStability { .. } => No,
CoherenceIsCore => No,
Coinductive(..) => No,
Cold(..) => No,
Confusables { .. } => Yes,
ConstContinue(..) => No,
ConstStability { .. } => Yes,
ConstStabilityIndirect => No,
ConstTrait(..) => No,
DenyExplicitImpl(..) => No,
Deprecation { .. } => Yes,
DoNotImplementViaObject(..) => No,
DocComment { .. } => Yes,
Dummy => No,
ExportName { .. } => Yes,
ExportStable => No,
FfiConst(..) => No,
FfiPure(..) => No,
Fundamental { .. } => Yes,
Ignore { .. } => No,
Inline(..) => No,
LinkName { .. } => Yes,
LinkSection { .. } => No,
LoopMatch(..) => No,
MacroTransparency(..) => Yes,
Marker(..) => No,
MayDangle(..) => No,
MustUse { .. } => Yes,
Naked(..) => No,
@ -43,6 +51,7 @@ impl AttributeKind {
NoMangle(..) => No,
NonExhaustive(..) => Yes,
Optimize(..) => No,
ParenSugar(..) => No,
PassByValue(..) => Yes,
Path(..) => No,
PubTransparent(..) => Yes,
@ -51,10 +60,13 @@ impl AttributeKind {
RustcLayoutScalarValidRangeStart(..) => Yes,
RustcObjectLifetimeDefault => No,
SkipDuringMethodDispatch { .. } => No,
SpecializationTrait(..) => No,
Stability { .. } => Yes,
StdInternalSymbol(..) => No,
TargetFeature(..) => No,
TrackCaller(..) => Yes,
TypeConst(..) => Yes,
UnsafeSpecializationMarker(..) => No,
Used { .. } => No,
// tidy-alphabetical-end
}

View file

@ -2,14 +2,15 @@ use core::mem;
use rustc_attr_data_structures::AttributeKind;
use rustc_feature::{AttributeTemplate, template};
use rustc_span::{Symbol, sym};
use rustc_span::{Span, Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
pub(crate) struct SkipDuringMethodDispatchParser;
impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
@ -52,3 +53,95 @@ impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
}
}
pub(crate) struct ParenSugarParser;
impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
const PATH: &[Symbol] = &[sym::rustc_paren_sugar];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ParenSugar;
}
pub(crate) struct TypeConstParser;
impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
const PATH: &[Symbol] = &[sym::type_const];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
}
// Markers
pub(crate) struct MarkerParser;
impl<S: Stage> NoArgsAttributeParser<S> for MarkerParser {
const PATH: &[Symbol] = &[sym::marker];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Marker;
}
pub(crate) struct DenyExplicitImplParser;
impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl;
}
pub(crate) struct DoNotImplementViaObjectParser;
impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
const PATH: &[Symbol] = &[sym::rustc_do_not_implement_via_object];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
}
// Const traits
pub(crate) struct ConstTraitParser;
impl<S: Stage> NoArgsAttributeParser<S> for ConstTraitParser {
const PATH: &[Symbol] = &[sym::const_trait];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait;
}
// Specialization
pub(crate) struct SpecializationTraitParser;
impl<S: Stage> NoArgsAttributeParser<S> for SpecializationTraitParser {
const PATH: &[Symbol] = &[sym::rustc_specialization_trait];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::SpecializationTrait;
}
pub(crate) struct UnsafeSpecializationMarkerParser;
impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser {
const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::UnsafeSpecializationMarker;
}
// Coherence
pub(crate) struct CoinductiveParser;
impl<S: Stage> NoArgsAttributeParser<S> for CoinductiveParser {
const PATH: &[Symbol] = &[sym::rustc_coinductive];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::Coinductive;
}
pub(crate) struct AllowIncoherentImplParser;
impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl;
}
pub(crate) struct CoherenceIsCoreParser;
impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
}
pub(crate) struct FundamentalParser;
impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
const PATH: &[Symbol] = &[sym::fundamental];
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
}

View file

@ -43,7 +43,12 @@ use crate::attributes::stability::{
BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
};
use crate::attributes::test_attrs::IgnoreParser;
use crate::attributes::traits::SkipDuringMethodDispatchParser;
use crate::attributes::traits::{
AllowIncoherentImplParser, CoherenceIsCoreParser, CoinductiveParser, ConstTraitParser,
DenyExplicitImplParser, DoNotImplementViaObjectParser, FundamentalParser, MarkerParser,
ParenSugarParser, SkipDuringMethodDispatchParser, SpecializationTraitParser, TypeConstParser,
UnsafeSpecializationMarkerParser,
};
use crate::attributes::transparency::TransparencyParser;
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
use crate::parser::{ArgParser, MetaItemParser, PathParser};
@ -146,22 +151,34 @@ attribute_parsers!(
Single<RustcObjectLifetimeDefaultParser>,
Single<SkipDuringMethodDispatchParser>,
Single<TransparencyParser>,
Single<WithoutArgs<AllowIncoherentImplParser>>,
Single<WithoutArgs<AsPtrParser>>,
Single<WithoutArgs<CoherenceIsCoreParser>>,
Single<WithoutArgs<CoinductiveParser>>,
Single<WithoutArgs<ColdParser>>,
Single<WithoutArgs<ConstContinueParser>>,
Single<WithoutArgs<ConstStabilityIndirectParser>>,
Single<WithoutArgs<ConstTraitParser>>,
Single<WithoutArgs<DenyExplicitImplParser>>,
Single<WithoutArgs<DoNotImplementViaObjectParser>>,
Single<WithoutArgs<ExportStableParser>>,
Single<WithoutArgs<FfiConstParser>>,
Single<WithoutArgs<FfiPureParser>>,
Single<WithoutArgs<FundamentalParser>>,
Single<WithoutArgs<LoopMatchParser>>,
Single<WithoutArgs<MarkerParser>>,
Single<WithoutArgs<MayDangleParser>>,
Single<WithoutArgs<NoImplicitPreludeParser>>,
Single<WithoutArgs<NoMangleParser>>,
Single<WithoutArgs<NonExhaustiveParser>>,
Single<WithoutArgs<ParenSugarParser>>,
Single<WithoutArgs<PassByValueParser>>,
Single<WithoutArgs<PubTransparentParser>>,
Single<WithoutArgs<SpecializationTraitParser>>,
Single<WithoutArgs<StdInternalSymbolParser>>,
Single<WithoutArgs<TrackCallerParser>>,
Single<WithoutArgs<TypeConstParser>>,
Single<WithoutArgs<UnsafeSpecializationMarkerParser>>,
// tidy-alphabetical-end
];
);

View file

@ -680,7 +680,7 @@ pub(crate) fn run_pass_manager(
if attributes::has_string_attr(function, enzyme_marker) {
// Sanity check: Ensure 'noinline' is present before replacing it.
assert!(
!attributes::has_attr(function, Function, llvm::AttributeKind::NoInline),
attributes::has_attr(function, Function, llvm::AttributeKind::NoInline),
"Expected __enzyme function to have 'noinline' before adding 'alwaysinline'"
);

View file

@ -564,12 +564,33 @@ pub trait BuilderMethods<'a, 'tcx>:
/// Called for `StorageDead`
fn lifetime_end(&mut self, ptr: Self::Value, size: Size);
/// "Finally codegen the call"
///
/// ## Arguments
///
/// The `fn_attrs`, `fn_abi`, and `instance` arguments are Options because they are advisory.
/// They relate to optional codegen enhancements like LLVM CFI, and do not affect ABI per se.
/// Any ABI-related transformations should be handled by different, earlier stages of codegen.
/// For instance, in the caller of `BuilderMethods::call`.
///
/// This means that a codegen backend which disregards `fn_attrs`, `fn_abi`, and `instance`
/// should still do correct codegen, and code should not be miscompiled if they are omitted.
/// It is not a miscompilation in this sense if it fails to run under CFI, other sanitizers, or
/// in the context of other compiler-enhanced security features.
///
/// The typical case that they are None is during the codegen of intrinsics and lang-items,
/// as those are "fake functions" with only a trivial ABI if any, et cetera.
///
/// ## Return
///
/// Must return the value the function will return so it can be written to the destination,
/// assuming the function does not explicitly pass the destination as a pointer in `args`.
fn call(
&mut self,
llty: Self::Type,
fn_attrs: Option<&CodegenFnAttrs>,
fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>,
llfn: Self::Value,
fn_val: Self::Value,
args: &[Self::Value],
funclet: Option<&Self::Funclet>,
instance: Option<Instance<'tcx>>,

View file

@ -6,16 +6,22 @@ use crate::mir::operand::OperandRef;
use crate::mir::place::PlaceRef;
pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes {
/// Higher-level interface to emitting calls to intrinsics
///
/// Remember to add all intrinsics here, in `compiler/rustc_hir_analysis/src/check/mod.rs`,
/// and in `library/core/src/intrinsics.rs`; if you need access to any LLVM intrinsics,
/// add them to `compiler/rustc_codegen_llvm/src/context.rs`.
/// Returns `Err` if another instance should be called instead. This is used to invoke
/// intrinsic default bodies in case an intrinsic is not implemented by the backend.
///
/// NOTE: allowed to call [`BuilderMethods::call`]
///
/// [`BuilderMethods::call`]: super::builder::BuilderMethods::call
fn codegen_intrinsic_call(
&mut self,
instance: ty::Instance<'tcx>,
args: &[OperandRef<'tcx, Self::Value>],
result: PlaceRef<'tcx, Self::Value>,
result_dest: PlaceRef<'tcx, Self::Value>,
span: Span,
) -> Result<(), ty::Instance<'tcx>>;

View file

@ -7,6 +7,7 @@
//! `tcx.inherent_impls(def_id)`). That value, however,
//! is computed by selecting an idea from this table.
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_hir as hir;
use rustc_hir::def::DefKind;
use rustc_hir::def_id::{DefId, LocalDefId};
@ -85,7 +86,10 @@ impl<'tcx> InherentCollect<'tcx> {
}
for &impl_item in items {
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
if !find_attr!(
self.tcx.get_all_attrs(impl_item),
AttributeKind::AllowIncoherentImpl(_)
) {
let impl_span = self.tcx.def_span(impl_def_id);
return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsideRelevant {
span: impl_span,
@ -116,7 +120,10 @@ impl<'tcx> InherentCollect<'tcx> {
if !self.tcx.hir_rustc_coherence_is_core() {
if self.tcx.features().rustc_attrs() {
for &impl_item in items {
if !self.tcx.has_attr(impl_item, sym::rustc_allow_incoherent_impl) {
if !find_attr!(
self.tcx.get_all_attrs(impl_item),
AttributeKind::AllowIncoherentImpl(_)
) {
let span = self.tcx.def_span(impl_def_id);
return Err(self.tcx.dcx().emit_err(errors::InherentTyOutsidePrimitive {
span,

View file

@ -852,39 +852,41 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
_ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
};
let attrs = tcx.get_all_attrs(def_id);
// Only regular traits can be const.
let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) {
let constness = if !is_alias && find_attr!(attrs, AttributeKind::ConstTrait(_)) {
hir::Constness::Const
} else {
hir::Constness::NotConst
};
let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
let paren_sugar = find_attr!(attrs, AttributeKind::ParenSugar(_));
if paren_sugar && !tcx.features().unboxed_closures() {
tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
}
// Only regular traits can be marker.
let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker);
let is_marker = !is_alias && find_attr!(attrs, AttributeKind::Marker(_));
let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
let rustc_coinductive = find_attr!(attrs, AttributeKind::Coinductive(_));
let is_fundamental = find_attr!(attrs, AttributeKind::Fundamental);
let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
tcx.get_all_attrs(def_id),
AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span:_ } => [*array, *boxed_slice]
attrs,
AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
)
.unwrap_or([false; 2]);
let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
let specialization_kind = if find_attr!(attrs, AttributeKind::UnsafeSpecializationMarker(_)) {
ty::trait_def::TraitSpecializationKind::Marker
} else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
} else if find_attr!(attrs, AttributeKind::SpecializationTrait(_)) {
ty::trait_def::TraitSpecializationKind::AlwaysApplicable
} else {
ty::trait_def::TraitSpecializationKind::None
};
let must_implement_one_of = tcx
.get_attr(def_id, sym::rustc_must_implement_one_of)
let must_implement_one_of = attrs
.iter()
.find(|attr| attr.has_name(sym::rustc_must_implement_one_of))
// Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]`
// and that they are all identifiers
.and_then(|attr| match attr.meta_item_list() {
@ -958,8 +960,8 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
no_dups.then_some(list)
});
let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
let implement_via_object = !tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
let deny_explicit_impl = find_attr!(attrs, AttributeKind::DenyExplicitImpl(_));
let implement_via_object = !find_attr!(attrs, AttributeKind::DoNotImplementViaObject(_));
ty::TraitDef {
def_id: def_id.to_def_id(),

View file

@ -4,6 +4,7 @@
use rustc_abi::ExternAbi;
use rustc_ast::visit::{VisitorResult, walk_list};
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
use rustc_data_structures::svh::Svh;
@ -15,7 +16,7 @@ use rustc_hir::intravisit::Visitor;
use rustc_hir::*;
use rustc_hir_pretty as pprust_hir;
use rustc_span::def_id::StableCrateId;
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, sym, with_metavar_spans};
use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, kw, with_metavar_spans};
use crate::hir::{ModuleItems, nested_filter};
use crate::middle::debugger_visualizer::DebuggerVisualizerFile;
@ -369,7 +370,7 @@ impl<'tcx> TyCtxt<'tcx> {
}
pub fn hir_rustc_coherence_is_core(self) -> bool {
self.hir_krate_attrs().iter().any(|attr| attr.has_name(sym::rustc_coherence_is_core))
find_attr!(self.hir_krate_attrs(), AttributeKind::CoherenceIsCore)
}
pub fn hir_get_module(self, module: LocalModDefId) -> (&'tcx Mod<'tcx>, Span, HirId) {

View file

@ -1,6 +1,5 @@
use std::sync::OnceLock;
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::graph;
use rustc_data_structures::graph::dominators::{Dominators, dominators};
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
@ -10,7 +9,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
use smallvec::SmallVec;
use crate::mir::traversal::Postorder;
use crate::mir::{BasicBlock, BasicBlockData, START_BLOCK, Terminator, TerminatorKind};
use crate::mir::{BasicBlock, BasicBlockData, START_BLOCK};
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
pub struct BasicBlocks<'tcx> {
@ -21,15 +20,6 @@ pub struct BasicBlocks<'tcx> {
// Typically 95%+ of basic blocks have 4 or fewer predecessors.
type Predecessors = IndexVec<BasicBlock, SmallVec<[BasicBlock; 4]>>;
/// Each `(target, switch)` entry in the map contains a list of switch values
/// that lead to a `target` block from a `switch` block.
///
/// Note: this type is currently never instantiated, because it's only used for
/// `BasicBlocks::switch_sources`, which is only called by backwards analyses
/// that do `SwitchInt` handling, and we don't have any of those, not even in
/// tests. See #95120 and #94576.
type SwitchSources = FxHashMap<(BasicBlock, BasicBlock), SmallVec<[SwitchTargetValue; 1]>>;
#[derive(Debug, Clone, Copy)]
pub enum SwitchTargetValue {
// A normal switch value.
@ -41,7 +31,6 @@ pub enum SwitchTargetValue {
#[derive(Clone, Default, Debug)]
struct Cache {
predecessors: OnceLock<Predecessors>,
switch_sources: OnceLock<SwitchSources>,
reverse_postorder: OnceLock<Vec<BasicBlock>>,
dominators: OnceLock<Dominators<BasicBlock>>,
}
@ -86,33 +75,6 @@ impl<'tcx> BasicBlocks<'tcx> {
})
}
/// Returns info about switch values that lead from one block to another
/// block. See `SwitchSources`.
#[inline]
pub fn switch_sources(&self) -> &SwitchSources {
self.cache.switch_sources.get_or_init(|| {
let mut switch_sources: SwitchSources = FxHashMap::default();
for (bb, data) in self.basic_blocks.iter_enumerated() {
if let Some(Terminator {
kind: TerminatorKind::SwitchInt { targets, .. }, ..
}) = &data.terminator
{
for (value, target) in targets.iter() {
switch_sources
.entry((target, bb))
.or_default()
.push(SwitchTargetValue::Normal(value));
}
switch_sources
.entry((targets.otherwise(), bb))
.or_default()
.push(SwitchTargetValue::Otherwise);
}
}
switch_sources
})
}
/// Returns mutable reference to basic blocks. Invalidates CFG cache.
#[inline]
pub fn as_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {

View file

@ -17,7 +17,6 @@ use rustc_index::{IndexSlice, IndexVec};
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
use rustc_query_system::ich::StableHashingContext;
use rustc_session::DataTypeKind;
use rustc_span::sym;
use rustc_type_ir::solve::AdtDestructorKind;
use tracing::{debug, info, trace};
@ -296,7 +295,7 @@ impl AdtDefData {
flags |= AdtFlags::HAS_CTOR;
}
if tcx.has_attr(did, sym::fundamental) {
if find_attr!(tcx.get_all_attrs(did), AttributeKind::Fundamental) {
flags |= AdtFlags::IS_FUNDAMENTAL;
}
if tcx.is_lang_item(did, LangItem::PhantomData) {

View file

@ -1,9 +1,10 @@
use rustc_attr_data_structures::{AttributeKind, find_attr};
use rustc_data_structures::sorted_map::SortedIndexMultiMap;
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Namespace};
use rustc_hir::def_id::DefId;
use rustc_macros::{Decodable, Encodable, HashStable};
use rustc_span::{Ident, Symbol, sym};
use rustc_span::{Ident, Symbol};
use super::{TyCtxt, Visibility};
use crate::ty;
@ -160,7 +161,7 @@ impl AssocItem {
// Inherent impl but this attr is only applied to trait assoc items.
(AssocItemContainer::Impl, None) => return true,
};
tcx.has_attr(def_id, sym::type_const)
find_attr!(tcx.get_all_attrs(def_id), AttributeKind::TypeConst(_))
}
}

View file

@ -991,18 +991,16 @@ fn needs_fn_once_adapter_shim(
Ok(false)
}
(ty::ClosureKind::Fn, ty::ClosureKind::FnMut) => {
// The closure fn `llfn` is a `fn(&self, ...)`. We want a
// `fn(&mut self, ...)`. In fact, at codegen time, these are
// basically the same thing, so we can just return llfn.
// The closure fn is a `fn(&self, ...)`, but we want a `fn(&mut self, ...)`.
// At codegen time, these are basically the same, so we can just return the closure.
Ok(false)
}
(ty::ClosureKind::Fn | ty::ClosureKind::FnMut, ty::ClosureKind::FnOnce) => {
// The closure fn `llfn` is a `fn(&self, ...)` or `fn(&mut
// self, ...)`. We want a `fn(self, ...)`. We can produce
// this by doing something like:
// The closure fn is a `fn(&self, ...)` or `fn(&mut self, ...)`, but
// we want a `fn(self, ...)`. We can produce this by doing something like:
//
// fn call_once(self, ...) { call_mut(&self, ...) }
// fn call_once(mut self, ...) { call_mut(&mut self, ...) }
// fn call_once(self, ...) { Fn::call(&self, ...) }
// fn call_once(mut self, ...) { FnMut::call_mut(&mut self, ...) }
//
// These are both the same at codegen time.
Ok(true)

View file

@ -1782,21 +1782,18 @@ impl<'tcx> TyCtxt<'tcx> {
did: impl Into<DefId>,
attr: Symbol,
) -> impl Iterator<Item = &'tcx hir::Attribute> {
self.get_all_attrs(did).filter(move |a: &&hir::Attribute| a.has_name(attr))
self.get_all_attrs(did).iter().filter(move |a: &&hir::Attribute| a.has_name(attr))
}
/// Gets all attributes.
///
/// To see if an item has a specific attribute, you should use [`rustc_attr_data_structures::find_attr!`] so you can use matching.
pub fn get_all_attrs(
self,
did: impl Into<DefId>,
) -> impl Iterator<Item = &'tcx hir::Attribute> {
pub fn get_all_attrs(self, did: impl Into<DefId>) -> &'tcx [hir::Attribute] {
let did: DefId = did.into();
if let Some(did) = did.as_local() {
self.hir_attrs(self.local_def_id_to_hir_id(did)).iter()
self.hir_attrs(self.local_def_id_to_hir_id(did))
} else {
self.attrs_for_def(did).iter()
self.attrs_for_def(did)
}
}

View file

@ -1,5 +1,6 @@
use std::ops::RangeInclusive;
use rustc_middle::bug;
use rustc_middle::mir::{
self, BasicBlock, CallReturnPlaces, Location, SwitchTargetValue, TerminatorEdges,
};
@ -112,15 +113,11 @@ impl Direction for Backward {
propagate(pred, &tmp);
}
mir::TerminatorKind::SwitchInt { ref targets, ref discr } => {
if let Some(mut data) = analysis.get_switch_int_data(block, discr) {
let mut tmp = analysis.bottom_value(body);
for &value in &body.basic_blocks.switch_sources()[&(block, pred)] {
tmp.clone_from(exit_state);
analysis
.apply_switch_int_edge_effect(&mut data, &mut tmp, value, targets);
propagate(pred, &tmp);
}
mir::TerminatorKind::SwitchInt { ref discr, .. } => {
if let Some(_data) = analysis.get_switch_int_data(pred, discr) {
bug!(
"SwitchInt edge effects are unsupported in backward dataflow analyses"
);
} else {
propagate(pred, exit_state)
}

View file

@ -283,6 +283,18 @@ pub fn check_builtin_meta_item(
| sym::rustc_confusables
| sym::rustc_skip_during_method_dispatch
| sym::rustc_pass_by_value
| sym::rustc_deny_explicit_impl
| sym::rustc_do_not_implement_via_object
| sym::rustc_coinductive
| sym::const_trait
| sym::rustc_specialization_trait
| sym::rustc_unsafe_specialization_marker
| sym::rustc_allow_incoherent_impl
| sym::rustc_coherence_is_core
| sym::marker
| sym::fundamental
| sym::rustc_paren_sugar
| sym::type_const
| sym::repr
| sym::align
| sym::deprecated

View file

@ -120,12 +120,35 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
for attr in attrs {
let mut style = None;
match attr {
Attribute::Parsed(AttributeKind::SkipDuringMethodDispatch {
span: attr_span,
..
}) => {
Attribute::Parsed(
AttributeKind::SkipDuringMethodDispatch { span: attr_span, .. }
| AttributeKind::Coinductive(attr_span)
| AttributeKind::ConstTrait(attr_span)
| AttributeKind::DenyExplicitImpl(attr_span)
| AttributeKind::DoNotImplementViaObject(attr_span),
) => {
self.check_must_be_applied_to_trait(*attr_span, span, target);
}
&Attribute::Parsed(
AttributeKind::SpecializationTrait(attr_span)
| AttributeKind::UnsafeSpecializationMarker(attr_span)
| AttributeKind::ParenSugar(attr_span),
) => {
// FIXME: more validation is needed
self.check_must_be_applied_to_trait(attr_span, span, target);
}
&Attribute::Parsed(AttributeKind::TypeConst(attr_span)) => {
self.check_type_const(hir_id, attr_span, target)
}
&Attribute::Parsed(AttributeKind::Marker(attr_span)) => {
self.check_marker(hir_id, attr_span, span, target)
}
Attribute::Parsed(AttributeKind::Fundamental | AttributeKind::CoherenceIsCore) => {
// FIXME: add validation
}
&Attribute::Parsed(AttributeKind::AllowIncoherentImpl(attr_span)) => {
self.check_allow_incoherent_impl(attr_span, span, target)
}
Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => {
self.check_confusables(*first_span, target);
}
@ -259,7 +282,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::no_sanitize, ..] => {
self.check_no_sanitize(attr, span, target)
}
[sym::marker, ..] => self.check_marker(hir_id, attr, span, target),
[sym::thread_local, ..] => self.check_thread_local(attr, span, target),
[sym::doc, ..] => self.check_doc_attrs(
attr,
@ -297,16 +319,9 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| [sym::rustc_dirty, ..]
| [sym::rustc_if_this_changed, ..]
| [sym::rustc_then_this_would_need, ..] => self.check_rustc_dirty_clean(attr),
[sym::rustc_coinductive, ..]
| [sym::rustc_must_implement_one_of, ..]
| [sym::rustc_deny_explicit_impl, ..]
| [sym::rustc_do_not_implement_via_object, ..]
| [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target),
[sym::rustc_must_implement_one_of, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target),
[sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
[sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
[sym::rustc_allow_incoherent_impl, ..] => {
self.check_allow_incoherent_impl(attr, span, target)
}
[sym::rustc_has_incoherent_inherent_impls, ..] => {
self.check_has_incoherent_inherent_impls(attr, span, target)
}
@ -339,9 +354,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
[sym::coroutine, ..] => {
self.check_coroutine(attr, target);
}
[sym::type_const, ..] => {
self.check_type_const(hir_id,attr, target);
}
[sym::linkage, ..] => self.check_linkage(attr, span, target),
[
// ok
@ -366,7 +378,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
| sym::prelude_import
| sym::panic_handler
| sym::allow_internal_unsafe
| sym::fundamental
| sym::lang
| sym::needs_allocator
| sym::default_lib_allocator
@ -830,7 +841,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
/// Checks if the `#[marker]` attribute on an `item` is valid.
fn check_marker(&self, hir_id: HirId, attr: &Attribute, span: Span, target: Target) {
fn check_marker(&self, hir_id: HirId, attr_span: Span, span: Span, target: Target) {
match target {
Target::Trait => {}
// FIXME(#80564): We permit struct fields, match arms and macro defs to have an
@ -838,13 +849,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
// erroneously allowed it and some crates used it accidentally, to be compatible
// with crates depending on them, we can't throw an error here.
Target::Field | Target::Arm | Target::MacroDef => {
self.inline_attr_str_error_with_macro_def(hir_id, attr.span(), "marker");
self.inline_attr_str_error_with_macro_def(hir_id, attr_span, "marker");
}
_ => {
self.dcx().emit_err(errors::AttrShouldBeAppliedToTrait {
attr_span: attr.span(),
defn_span: span,
});
self.dcx()
.emit_err(errors::AttrShouldBeAppliedToTrait { attr_span, defn_span: span });
}
}
}
@ -1489,11 +1498,11 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_allow_incoherent_impl(&self, attr: &Attribute, span: Span, target: Target) {
fn check_allow_incoherent_impl(&self, attr_span: Span, span: Span, target: Target) {
match target {
Target::Method(MethodKind::Inherent) => {}
_ => {
self.dcx().emit_err(errors::AllowIncoherentImpl { attr_span: attr.span(), span });
self.dcx().emit_err(errors::AllowIncoherentImpl { attr_span, span });
}
}
}
@ -2514,7 +2523,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
}
}
fn check_type_const(&self, hir_id: HirId, attr: &Attribute, target: Target) {
fn check_type_const(&self, hir_id: HirId, attr_span: Span, target: Target) {
let tcx = self.tcx;
if target == Target::AssocConst
&& let parent = tcx.parent(hir_id.expect_owner().to_def_id())
@ -2524,7 +2533,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
} else {
self.dcx()
.struct_span_err(
attr.span(),
attr_span,
"`#[type_const]` must only be applied to trait associated constants",
)
.emit();

View file

@ -11,7 +11,7 @@
//! This is because `sys_common` not only contains platform-independent code,
//! but also code that is shared between the different platforms in `sys`.
//! Ideally all that shared code should be moved to `sys::common`,
//! and the dependencies between `std`, `sys_common` and `sys` all would form a dag.
//! and the dependencies between `std`, `sys_common` and `sys` all would form a DAG.
//! Progress on this is tracked in #84187.
#![allow(missing_docs)]

View file

@ -9,7 +9,7 @@ pub enum CiEnv {
impl CiEnv {
/// Obtains the current CI environment.
pub fn current() -> CiEnv {
if std::env::var("GITHUB_ACTIONS").map_or(false, |e| e == "true") {
if std::env::var("GITHUB_ACTIONS").is_ok_and(|e| e == "true") {
CiEnv::GitHubActions
} else {
CiEnv::None

View file

@ -13,7 +13,7 @@ pub struct GitConfig<'a> {
pub fn output_result(cmd: &mut Command) -> Result<String, String> {
let output = match cmd.stderr(Stdio::inherit()).output() {
Ok(status) => status,
Err(e) => return Err(format!("failed to run command: {:?}: {}", cmd, e)),
Err(e) => return Err(format!("failed to run command: {cmd:?}: {e}")),
};
if !output.status.success() {
return Err(format!(
@ -62,22 +62,22 @@ pub enum PathFreshness {
/// The function behaves differently in CI and outside CI.
///
/// - Outside CI, we want to find out if `target_paths` were modified in some local commit on
/// top of the latest upstream commit that is available in local git history.
/// If not, we try to find the most recent upstream commit (which we assume are commits
/// made by bors) that modified `target_paths`.
/// We don't want to simply take the latest master commit to avoid changing the output of
/// this function frequently after rebasing on the latest master branch even if `target_paths`
/// were not modified upstream in the meantime. In that case we would be redownloading CI
/// artifacts unnecessarily.
/// top of the latest upstream commit that is available in local git history.
/// If not, we try to find the most recent upstream commit (which we assume are commits
/// made by bors) that modified `target_paths`.
/// We don't want to simply take the latest master commit to avoid changing the output of
/// this function frequently after rebasing on the latest master branch even if `target_paths`
/// were not modified upstream in the meantime. In that case we would be redownloading CI
/// artifacts unnecessarily.
///
/// - In CI, we use a shallow clone of depth 2, i.e., we fetch only a single parent commit
/// (which will be the most recent bors merge commit) and do not have access
/// to the full git history. Luckily, we only need to distinguish between two situations:
/// 1) The current PR made modifications to `target_paths`.
/// In that case, a build is typically necessary.
/// 2) The current PR did not make modifications to `target_paths`.
/// In that case we simply take the latest upstream commit, because on CI there is no need to avoid
/// redownloading.
/// (which will be the most recent bors merge commit) and do not have access
/// to the full git history. Luckily, we only need to distinguish between two situations:
/// 1) The current PR made modifications to `target_paths`.
/// In that case, a build is typically necessary.
/// 2) The current PR did not make modifications to `target_paths`.
/// In that case we simply take the latest upstream commit, because on CI there is no need to avoid
/// redownloading.
pub fn check_path_modifications(
git_dir: &Path,
config: &GitConfig<'_>,
@ -232,7 +232,7 @@ pub fn get_closest_upstream_commit(
"--author-date-order",
&format!("--author={}", config.git_merge_commit_email),
"-n1",
&base,
base,
]);
let output = output_result(&mut git)?.trim().to_owned();

View file

@ -141,7 +141,7 @@ impl BuildStep {
} => {
let full_name = format!("{parent_name}-{kind}");
let children: Vec<_> =
children.into_iter().filter_map(|s| parse(s, &full_name)).collect();
children.iter().filter_map(|s| parse(s, &full_name)).collect();
let children_duration = children.iter().map(|c| c.duration).sum::<Duration>();
Some(BuildStep {
r#type: kind.to_string(),

View file

@ -18,29 +18,28 @@ macro_rules! exit {
pub fn detail_exit(code: i32, is_test: bool) -> ! {
// if in test and code is an error code, panic with status code provided
if is_test {
panic!("status code: {}", code);
panic!("status code: {code}");
} else {
// otherwise,exit with provided status code
// otherwise, exit with provided status code
std::process::exit(code);
}
}
pub fn fail(s: &str) -> ! {
eprintln!("\n\n{}\n\n", s);
eprintln!("\n\n{s}\n\n");
detail_exit(1, cfg!(test));
}
pub fn try_run(cmd: &mut Command, print_cmd_on_fail: bool) -> Result<(), ()> {
let status = match cmd.status() {
Ok(status) => status,
Err(e) => fail(&format!("failed to execute command: {:?}\nerror: {}", cmd, e)),
Err(e) => fail(&format!("failed to execute command: {cmd:?}\nerror: {e}")),
};
if !status.success() {
if print_cmd_on_fail {
println!(
"\n\ncommand did not execute successfully: {:?}\n\
expected success, got: {}\n\n",
cmd, status
"\n\ncommand did not execute successfully: {cmd:?}\n\
expected success, got: {status}\n\n"
);
}
Err(())
@ -60,7 +59,7 @@ pub fn parse_gitmodules(target_dir: &Path) -> Vec<String> {
for line in BufReader::new(file).lines().map_while(Result::ok) {
let line = line.trim();
if line.starts_with("path") {
let actual_path = line.split(' ').last().expect("Couldn't get value of path");
let actual_path = line.split(' ').next_back().expect("Couldn't get value of path");
submodules_paths.push(actual_path.to_owned());
}
}

View file

@ -46,6 +46,7 @@
- [\*-apple-watchos](platform-support/apple-watchos.md)
- [\*-apple-visionos](platform-support/apple-visionos.md)
- [aarch64-nintendo-switch-freestanding](platform-support/aarch64-nintendo-switch-freestanding.md)
- [aarch64-unknown-linux-musl](platform-support/aarch64-unknown-linux-musl.md)
- [amdgcn-amd-amdhsa](platform-support/amdgcn-amd-amdhsa.md)
- [armeb-unknown-linux-gnueabi](platform-support/armeb-unknown-linux-gnueabi.md)
- [arm-none-eabi](platform-support/arm-none-eabi.md)

View file

@ -90,7 +90,7 @@ target | notes
-------|-------
[`aarch64-pc-windows-gnullvm`](platform-support/windows-gnullvm.md) | ARM64 MinGW (Windows 10+), LLVM ABI
[`aarch64-pc-windows-msvc`](platform-support/windows-msvc.md) | ARM64 Windows MSVC
`aarch64-unknown-linux-musl` | ARM64 Linux with musl 1.2.3
[`aarch64-unknown-linux-musl`](platform-support/aarch64-unknown-linux-musl.md) | ARM64 Linux with musl 1.2.3
[`aarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ARM64 OpenHarmony
`arm-unknown-linux-gnueabi` | Armv6 Linux (kernel 3.2+, glibc 2.17)
`arm-unknown-linux-gnueabihf` | Armv6 Linux, hardfloat (kernel 3.2+, glibc 2.17)

View file

@ -0,0 +1,49 @@
# aarch64-unknown-linux-musl
**Tier: 2**
Target for 64-bit little endian ARMv8-A Linux programs using musl libc.
## Target maintainers
[@Gelbpunkt](https://github.com/Gelbpunkt)
[@famfo](https://github.com/famfo)
## Requirements
Building the target itself requires a 64-bit little endian ARMv8-A compiler
that is supported by `cc-rs`.
## Building the target
The target can be built by enabling it for a `rustc` build.
```toml
[build]
target = ["aarch64-unknown-linux-musl"]
```
Make sure your C compiler is included in `$PATH`, then add it to the
`bootstrap.toml`:
```toml
[target.aarch64-unknown-linux-musl]
cc = "aarch64-linux-musl-gcc"
cxx = "aarch64-linux-musl-g++"
ar = "aarch64-linux-musl-ar"
linker = "aarch64-linux-musl-gcc"
```
## Building Rust programs
This target is distributed through `rustup`, and otherwise requires no
special configuration.
## Cross-compilation
This target can be cross-compiled from any host.
## Testing
This target can be tested as normal with `x.py` on a 64-bit little endian
ARMv8-A host or via QEMU emulation.

View file

@ -2,5 +2,5 @@
name = "x"
version = "0.1.1"
description = "Run x.py slightly more conveniently"
edition = "2021"
edition = "2024"
publish = false

View file

@ -19,15 +19,14 @@ const PYTHON2: &str = "python2";
const PYTHON3: &str = "python3";
fn python() -> &'static str {
let val = match env::var_os("PATH") {
Some(val) => val,
None => return PYTHON,
let Some(path) = env::var_os("PATH") else {
return PYTHON;
};
let mut python2 = false;
let mut python3 = false;
for dir in env::split_paths(&val) {
for dir in env::split_paths(&path) {
// `python` should always take precedence over python2 / python3 if it exists
if dir.join(PYTHON).with_extension(EXE_EXTENSION).exists() {
return PYTHON;
@ -89,7 +88,7 @@ fn exec_or_status(command: &mut Command) -> io::Result<ExitStatus> {
fn handle_result(result: io::Result<ExitStatus>, cmd: Command) {
match result {
Err(error) => {
eprintln!("Failed to invoke `{:?}`: {}", cmd, error);
eprintln!("Failed to invoke `{cmd:?}`: {error}");
}
Ok(status) => {
process::exit(status.code().unwrap_or(1));
@ -98,14 +97,12 @@ fn handle_result(result: io::Result<ExitStatus>, cmd: Command) {
}
fn main() {
match env::args().skip(1).next().as_deref() {
Some("--wrapper-version") => {
let version = env!("CARGO_PKG_VERSION");
println!("{}", version);
return;
}
_ => {}
if env::args().nth(1).is_some_and(|s| s == "--wrapper-version") {
let version = env!("CARGO_PKG_VERSION");
println!("{version}");
return;
}
let current = match env::current_dir() {
Ok(dir) => dir,
Err(err) => {
@ -113,7 +110,6 @@ fn main() {
process::exit(1);
}
};
for dir in current.ancestors() {
let candidate = dir.join("x.py");
if candidate.exists() {

View file

@ -6,17 +6,17 @@
pub fn test1() {}
//@ is "$.index[?(@.name=='test2')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\")]"]'
//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
//@ is "$.index[?(@.name=='test2')].inner.function.header.is_unsafe" false
#[target_feature(enable = "avx,avx2")]
pub fn test2() {}
//@ is "$.index[?(@.name=='test3')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\")]"]'
//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
//@ is "$.index[?(@.name=='test3')].inner.function.header.is_unsafe" false
#[target_feature(enable = "avx", enable = "avx2")]
pub fn test3() {}
//@ is "$.index[?(@.name=='test4')].attrs" '["#[target_feature(enable=\"avx\", enable=\"avx2\", enable=\"avx512f\")]"]'
//@ is "$.index[?(@.name=='test1')].inner.function.header.is_unsafe" false
//@ is "$.index[?(@.name=='test4')].inner.function.header.is_unsafe" false
#[target_feature(enable = "avx", enable = "avx2,avx512f")]
pub fn test4() {}

View file

@ -116,24 +116,6 @@ error: malformed `cfi_encoding` attribute input
LL | #[cfi_encoding]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[cfi_encoding = "encoding"]`
error: malformed `type_const` attribute input
--> $DIR/malformed-attrs.rs:143:5
|
LL | #[type_const = 1]
| ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[type_const]`
error: malformed `marker` attribute input
--> $DIR/malformed-attrs.rs:155:1
|
LL | #[marker = 3]
| ^^^^^^^^^^^^^ help: must be of the form: `#[marker]`
error: malformed `fundamental` attribute input
--> $DIR/malformed-attrs.rs:157:1
|
LL | #[fundamental()]
| ^^^^^^^^^^^^^^^^ help: must be of the form: `#[fundamental]`
error: malformed `link_ordinal` attribute input
--> $DIR/malformed-attrs.rs:167:5
|
@ -528,6 +510,24 @@ LL | #[rustc_layout_scalar_valid_range_end]
| expected this to be a list
| help: must be of the form: `#[rustc_layout_scalar_valid_range_end(end)]`
error[E0565]: malformed `marker` attribute input
--> $DIR/malformed-attrs.rs:155:1
|
LL | #[marker = 3]
| ^^^^^^^^^---^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[marker]`
error[E0565]: malformed `fundamental` attribute input
--> $DIR/malformed-attrs.rs:157:1
|
LL | #[fundamental()]
| ^^^^^^^^^^^^^--^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[fundamental]`
error[E0565]: malformed `ffi_pure` attribute input
--> $DIR/malformed-attrs.rs:165:5
|
@ -555,6 +555,15 @@ LL | #[non_exhaustive = 1]
| | didn't expect any arguments here
| help: must be of the form: `#[non_exhaustive]`
error[E0565]: malformed `type_const` attribute input
--> $DIR/malformed-attrs.rs:143:5
|
LL | #[type_const = 1]
| ^^^^^^^^^^^^^---^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[type_const]`
error: attribute should be applied to `const fn`
--> $DIR/malformed-attrs.rs:34:1
|

View file

@ -1,9 +1,3 @@
error: malformed `type_const` attribute input
--> $DIR/bad-type_const-syntax.rs:2:5
|
LL | #[type_const()]
| ^^^^^^^^^^^^^^^ help: must be of the form: `#[type_const]`
error[E0658]: the `#[type_const]` attribute is an experimental feature
--> $DIR/bad-type_const-syntax.rs:2:5
|
@ -24,6 +18,15 @@ LL | #[type_const]
= help: add `#![feature(min_generic_const_args)]` 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[E0565]: malformed `type_const` attribute input
--> $DIR/bad-type_const-syntax.rs:2:5
|
LL | #[type_const()]
| ^^^^^^^^^^^^--^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[type_const]`
error: `#[type_const]` must only be applied to trait associated constants
--> $DIR/bad-type_const-syntax.rs:11:5
|
@ -32,4 +35,5 @@ LL | #[type_const]
error: aborting due to 4 previous errors
For more information about this error, try `rustc --explain E0658`.
Some errors have detailed explanations: E0565, E0658.
For more information about an error, try `rustc --explain E0565`.

View file

@ -1,20 +1,30 @@
error: malformed `marker` attribute input
error[E0565]: malformed `marker` attribute input
--> $DIR/marker-attribute-with-values.rs:3:1
|
LL | #[marker(always)]
| ^^^^^^^^^^^^^^^^^ help: must be of the form: `#[marker]`
| ^^^^^^^^--------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[marker]`
error: malformed `marker` attribute input
error[E0565]: malformed `marker` attribute input
--> $DIR/marker-attribute-with-values.rs:6:1
|
LL | #[marker("never")]
| ^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[marker]`
| ^^^^^^^^---------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[marker]`
error: malformed `marker` attribute input
error[E0565]: malformed `marker` attribute input
--> $DIR/marker-attribute-with-values.rs:9:1
|
LL | #[marker(key = "value")]
| ^^^^^^^^^^^^^^^^^^^^^^^^ help: must be of the form: `#[marker]`
| ^^^^^^^^---------------^
| | |
| | didn't expect any arguments here
| help: must be of the form: `#[marker]`
error: aborting due to 3 previous errors
For more information about this error, try `rustc --explain E0565`.