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:
commit
915e535244
32 changed files with 432 additions and 194 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
];
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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'"
|
||||
);
|
||||
|
||||
|
|
|
|||
|
|
@ -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>>,
|
||||
|
|
|
|||
|
|
@ -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>>;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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>> {
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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(_))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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)]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
@ -2,5 +2,5 @@
|
|||
name = "x"
|
||||
version = "0.1.1"
|
||||
description = "Run x.py slightly more conveniently"
|
||||
edition = "2021"
|
||||
edition = "2024"
|
||||
publish = false
|
||||
|
|
|
|||
|
|
@ -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() {
|
||||
|
|
|
|||
|
|
@ -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() {}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
|
|
@ -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`.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue