Auto merge of #145906 - samueltardieu:rollup-p8ibzhz, r=samueltardieu
Rollup of 9 pull requests Successful merges: - rust-lang/rust#144499 (ci: Begin running ui tests with `rust.debuginfo-level-tests=1`) - rust-lang/rust#145790 (Improve dist for gnullvm hosts) - rust-lang/rust#145792 (Use attribute name in message for "outer attr used as inner attr" errors) - rust-lang/rust#145840 (rustc_codegen_ssa: More comprehensive RISC-V ELF flags) - rust-lang/rust#145876 (Enable building/disting standard library in stage 0) - rust-lang/rust#145887 (bootstrap: Don't panic if codegen-backends is set to empty) - rust-lang/rust#145888 (platform-support: Fix LoongArch32 host column) - rust-lang/rust#145892 (add a flag to codegen fn attrs for foreign items) - rust-lang/rust#145901 (Fix typo in comment of library/alloc/src/raw_vec/mod.rs) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
176d8dbce6
55 changed files with 840 additions and 306 deletions
|
|
@ -86,6 +86,12 @@ attr_parsing_invalid_repr_hint_no_value =
|
|||
attr_parsing_invalid_since =
|
||||
'since' must be a Rust version number, such as "1.31.0"
|
||||
|
||||
attr_parsing_invalid_style = {$is_used_as_inner ->
|
||||
[false] crate-level attribute should be an inner attribute: add an exclamation mark: `#![{$name}]`
|
||||
*[other] the `#![{$name}]` attribute can only be used at the crate root
|
||||
}
|
||||
.note = This attribute does not have an `!`, which means it is applied to this {$target}
|
||||
|
||||
attr_parsing_link_ordinal_out_of_range = ordinal value in `link_ordinal` is too large: `{$ordinal}`
|
||||
.note = the value may not exceed `u16::MAX`
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
use rustc_feature::AttributeType;
|
||||
|
||||
use super::prelude::*;
|
||||
|
||||
pub(crate) struct CrateNameParser;
|
||||
|
|
@ -7,6 +9,7 @@ impl<S: Stage> SingleAttributeParser<S> for CrateNameParser {
|
|||
const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepOutermost;
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::WarnButFutureError;
|
||||
const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");
|
||||
const TYPE: AttributeType = AttributeType::CrateLevel;
|
||||
|
||||
// FIXME: crate name is allowed on all targets and ignored,
|
||||
// even though it should only be valid on crates of course
|
||||
|
|
|
|||
|
|
@ -12,11 +12,15 @@
|
|||
//! - [`CombineAttributeParser`](crate::attributes::CombineAttributeParser): makes it easy to implement an attribute which should combine the
|
||||
//! contents of attributes, if an attribute appear multiple times in a list
|
||||
//!
|
||||
//! By default, attributes are allowed anywhere. When adding an attribute that should only be used
|
||||
//! at the crate root, consider setting the `TYPE` in the parser trait to
|
||||
//! [`AttributeType::CrateLevel`](rustc_feature::AttributeType::CrateLevel).
|
||||
//!
|
||||
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
|
||||
|
||||
use std::marker::PhantomData;
|
||||
|
||||
use rustc_feature::{AttributeTemplate, template};
|
||||
use rustc_feature::{AttributeTemplate, AttributeType, template};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_span::{Span, Symbol};
|
||||
use thin_vec::ThinVec;
|
||||
|
|
@ -88,6 +92,8 @@ pub(crate) trait AttributeParser<S: Stage>: Default + 'static {
|
|||
|
||||
const ALLOWED_TARGETS: AllowedTargets;
|
||||
|
||||
const TYPE: AttributeType = AttributeType::Normal;
|
||||
|
||||
/// The parser has gotten a chance to accept the attributes on an item,
|
||||
/// here it can produce an attribute.
|
||||
///
|
||||
|
|
@ -129,6 +135,8 @@ pub(crate) trait SingleAttributeParser<S: Stage>: 'static {
|
|||
/// The template this attribute parser should implement. Used for diagnostics.
|
||||
const TEMPLATE: AttributeTemplate;
|
||||
|
||||
const TYPE: AttributeType = AttributeType::Normal;
|
||||
|
||||
/// Converts a single syntactical attribute to a single semantic attribute, or [`AttributeKind`]
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind>;
|
||||
}
|
||||
|
|
@ -175,6 +183,8 @@ impl<T: SingleAttributeParser<S>, S: Stage> AttributeParser<S> for Single<T, S>
|
|||
)];
|
||||
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
|
||||
|
||||
const TYPE: AttributeType = T::TYPE;
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
Some(self.1?.0)
|
||||
}
|
||||
|
|
@ -259,6 +269,7 @@ pub(crate) trait NoArgsAttributeParser<S: Stage>: 'static {
|
|||
const PATH: &[Symbol];
|
||||
const ON_DUPLICATE: OnDuplicate<S>;
|
||||
const ALLOWED_TARGETS: AllowedTargets;
|
||||
const TYPE: AttributeType = AttributeType::Normal;
|
||||
|
||||
/// Create the [`AttributeKind`] given attribute's [`Span`].
|
||||
const CREATE: fn(Span) -> AttributeKind;
|
||||
|
|
@ -278,6 +289,7 @@ impl<T: NoArgsAttributeParser<S>, S: Stage> SingleAttributeParser<S> for Without
|
|||
const ON_DUPLICATE: OnDuplicate<S> = T::ON_DUPLICATE;
|
||||
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
|
||||
const TEMPLATE: AttributeTemplate = template!(Word);
|
||||
const TYPE: AttributeType = T::TYPE;
|
||||
|
||||
fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
|
||||
if let Err(span) = args.no_args() {
|
||||
|
|
@ -311,6 +323,8 @@ pub(crate) trait CombineAttributeParser<S: Stage>: 'static {
|
|||
/// The template this attribute parser should implement. Used for diagnostics.
|
||||
const TEMPLATE: AttributeTemplate;
|
||||
|
||||
const TYPE: AttributeType = AttributeType::Normal;
|
||||
|
||||
/// Converts a single syntactical attribute to a number of elements of the semantic attribute, or [`AttributeKind`]
|
||||
fn extend<'c>(
|
||||
cx: &'c mut AcceptContext<'_, '_, S>,
|
||||
|
|
@ -346,6 +360,7 @@ impl<T: CombineAttributeParser<S>, S: Stage> AttributeParser<S> for Combine<T, S
|
|||
group.items.extend(T::extend(cx, args))
|
||||
})];
|
||||
const ALLOWED_TARGETS: AllowedTargets = T::ALLOWED_TARGETS;
|
||||
const TYPE: AttributeType = T::TYPE;
|
||||
|
||||
fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
|
||||
if let Some(first_span) = self.first_span {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
use std::mem;
|
||||
|
||||
use rustc_feature::AttributeType;
|
||||
|
||||
use super::prelude::*;
|
||||
use crate::attributes::{
|
||||
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
|
||||
|
|
@ -154,6 +156,7 @@ impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
|
|||
const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
|
||||
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
|
||||
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
|
||||
const TYPE: AttributeType = AttributeType::CrateLevel;
|
||||
const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -4,12 +4,12 @@ use std::ops::{Deref, DerefMut};
|
|||
use std::sync::LazyLock;
|
||||
|
||||
use private::Sealed;
|
||||
use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
|
||||
use rustc_ast::{AttrStyle, CRATE_NODE_ID, MetaItemLit, NodeId};
|
||||
use rustc_errors::{Diag, Diagnostic, Level};
|
||||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_feature::{AttributeTemplate, AttributeType};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_hir::{AttrPath, HirId};
|
||||
use rustc_hir::{AttrPath, CRATE_HIR_ID, HirId};
|
||||
use rustc_session::Session;
|
||||
use rustc_span::{ErrorGuaranteed, Span, Symbol};
|
||||
|
||||
|
|
@ -80,6 +80,7 @@ pub(super) struct GroupTypeInnerAccept<S: Stage> {
|
|||
pub(super) template: AttributeTemplate,
|
||||
pub(super) accept_fn: AcceptFn<S>,
|
||||
pub(super) allowed_targets: AllowedTargets,
|
||||
pub(super) attribute_type: AttributeType,
|
||||
}
|
||||
|
||||
type AcceptFn<S> =
|
||||
|
|
@ -129,6 +130,7 @@ macro_rules! attribute_parsers {
|
|||
})
|
||||
}),
|
||||
allowed_targets: <$names as crate::attributes::AttributeParser<$stage>>::ALLOWED_TARGETS,
|
||||
attribute_type: <$names as crate::attributes::AttributeParser<$stage>>::TYPE,
|
||||
});
|
||||
}
|
||||
|
||||
|
|
@ -250,6 +252,8 @@ pub trait Stage: Sized + 'static + Sealed {
|
|||
) -> ErrorGuaranteed;
|
||||
|
||||
fn should_emit(&self) -> ShouldEmit;
|
||||
|
||||
fn id_is_crate_root(id: Self::Id) -> bool;
|
||||
}
|
||||
|
||||
// allow because it's a sealed trait
|
||||
|
|
@ -271,6 +275,10 @@ impl Stage for Early {
|
|||
fn should_emit(&self) -> ShouldEmit {
|
||||
self.emit_errors
|
||||
}
|
||||
|
||||
fn id_is_crate_root(id: Self::Id) -> bool {
|
||||
id == CRATE_NODE_ID
|
||||
}
|
||||
}
|
||||
|
||||
// allow because it's a sealed trait
|
||||
|
|
@ -292,6 +300,10 @@ impl Stage for Late {
|
|||
fn should_emit(&self) -> ShouldEmit {
|
||||
ShouldEmit::ErrorsAndLints
|
||||
}
|
||||
|
||||
fn id_is_crate_root(id: Self::Id) -> bool {
|
||||
id == CRATE_HIR_ID
|
||||
}
|
||||
}
|
||||
|
||||
/// used when parsing attributes for miscellaneous things *before* ast lowering
|
||||
|
|
|
|||
|
|
@ -271,8 +271,8 @@ impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
|||
};
|
||||
|
||||
(accept.accept_fn)(&mut cx, args);
|
||||
|
||||
if !matches!(self.stage.should_emit(), ShouldEmit::Nothing) {
|
||||
if !matches!(cx.stage.should_emit(), ShouldEmit::Nothing) {
|
||||
Self::check_type(accept.attribute_type, target, &mut cx);
|
||||
self.check_target(
|
||||
path.get_attribute_path(),
|
||||
attr.span,
|
||||
|
|
|
|||
|
|
@ -66,5 +66,19 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<L::Id>, lint_emi
|
|||
attr_span: *span,
|
||||
},
|
||||
),
|
||||
|
||||
&AttributeLintKind::InvalidStyle { ref name, is_used_as_inner, target, target_span } => {
|
||||
lint_emitter.emit_node_span_lint(
|
||||
rustc_session::lint::builtin::UNUSED_ATTRIBUTES,
|
||||
*id,
|
||||
*span,
|
||||
session_diagnostics::InvalidAttrStyle {
|
||||
name: name.clone(),
|
||||
is_used_as_inner,
|
||||
target_span: (!is_used_as_inner).then_some(target_span),
|
||||
target,
|
||||
},
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ use rustc_errors::{
|
|||
Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
|
||||
};
|
||||
use rustc_feature::AttributeTemplate;
|
||||
use rustc_hir::AttrPath;
|
||||
use rustc_hir::{AttrPath, Target};
|
||||
use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
|
||||
use rustc_span::{Span, Symbol};
|
||||
|
||||
|
|
@ -826,3 +826,13 @@ pub(crate) struct SuffixedLiteralInAttribute {
|
|||
#[primary_span]
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(attr_parsing_invalid_style)]
|
||||
pub(crate) struct InvalidAttrStyle {
|
||||
pub name: AttrPath,
|
||||
pub is_used_as_inner: bool,
|
||||
#[note]
|
||||
pub target_span: Option<Span>,
|
||||
pub target: Target,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,13 +1,14 @@
|
|||
use std::borrow::Cow;
|
||||
|
||||
use rustc_ast::AttrStyle;
|
||||
use rustc_errors::DiagArgValue;
|
||||
use rustc_feature::Features;
|
||||
use rustc_feature::{AttributeType, Features};
|
||||
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
|
||||
use rustc_hir::{AttrPath, MethodKind, Target};
|
||||
use rustc_span::Span;
|
||||
|
||||
use crate::AttributeParser;
|
||||
use crate::context::Stage;
|
||||
use crate::context::{AcceptContext, Stage};
|
||||
use crate::session_diagnostics::InvalidTarget;
|
||||
|
||||
#[derive(Debug)]
|
||||
|
|
@ -68,7 +69,7 @@ pub(crate) enum Policy {
|
|||
Error(Target),
|
||||
}
|
||||
|
||||
impl<S: Stage> AttributeParser<'_, S> {
|
||||
impl<'sess, S: Stage> AttributeParser<'sess, S> {
|
||||
pub(crate) fn check_target(
|
||||
&self,
|
||||
attr_name: AttrPath,
|
||||
|
|
@ -111,6 +112,32 @@ impl<S: Stage> AttributeParser<'_, S> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn check_type(
|
||||
attribute_type: AttributeType,
|
||||
target: Target,
|
||||
cx: &mut AcceptContext<'_, 'sess, S>,
|
||||
) {
|
||||
let is_crate_root = S::id_is_crate_root(cx.target_id);
|
||||
|
||||
if is_crate_root {
|
||||
return;
|
||||
}
|
||||
|
||||
if attribute_type != AttributeType::CrateLevel {
|
||||
return;
|
||||
}
|
||||
|
||||
let lint = AttributeLintKind::InvalidStyle {
|
||||
name: cx.attr_path.clone(),
|
||||
is_used_as_inner: cx.attr_style == AttrStyle::Inner,
|
||||
target,
|
||||
target_span: cx.target_span,
|
||||
};
|
||||
let attr_span = cx.attr_span;
|
||||
|
||||
cx.emit_lint(lint, attr_span);
|
||||
}
|
||||
}
|
||||
|
||||
/// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
|
||||
|
|
|
|||
|
|
@ -329,12 +329,18 @@ pub(super) fn elf_e_flags(architecture: Architecture, sess: &Session) -> u32 {
|
|||
// Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
|
||||
let mut e_flags: u32 = 0x0;
|
||||
|
||||
// Check if compressed is enabled
|
||||
// `unstable_target_features` is used here because "c" is gated behind riscv_target_feature.
|
||||
if sess.unstable_target_features.contains(&sym::c) {
|
||||
// Check if compression is enabled
|
||||
// `unstable_target_features` is used here because "zca" is gated behind riscv_target_feature.
|
||||
if sess.unstable_target_features.contains(&sym::zca) {
|
||||
e_flags |= elf::EF_RISCV_RVC;
|
||||
}
|
||||
|
||||
// Check if RVTSO is enabled
|
||||
// `unstable_target_features` is used here because "ztso" is gated behind riscv_target_feature.
|
||||
if sess.unstable_target_features.contains(&sym::ztso) {
|
||||
e_flags |= elf::EF_RISCV_TSO;
|
||||
}
|
||||
|
||||
// Set the appropriate flag based on ABI
|
||||
// This needs to match LLVM `RISCVELFStreamer.cpp`
|
||||
match &*sess.target.llvm_abiname {
|
||||
|
|
|
|||
|
|
@ -570,7 +570,7 @@ fn symbol_export_level(tcx: TyCtxt<'_>, sym_def_id: DefId) -> SymbolExportLevel
|
|||
// core/std/allocators/etc. For example symbols used to hook up allocation
|
||||
// are not considered for export
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(sym_def_id);
|
||||
let is_extern = codegen_fn_attrs.contains_extern_indicator(tcx, sym_def_id);
|
||||
let is_extern = codegen_fn_attrs.contains_extern_indicator();
|
||||
let std_internal =
|
||||
codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL);
|
||||
|
||||
|
|
|
|||
|
|
@ -385,6 +385,8 @@ fn apply_overrides(tcx: TyCtxt<'_>, did: LocalDefId, codegen_fn_attrs: &mut Code
|
|||
|
||||
// Foreign items by default use no mangling for their symbol name.
|
||||
if tcx.is_foreign_item(did) {
|
||||
codegen_fn_attrs.flags |= CodegenFnAttrFlags::FOREIGN_ITEM;
|
||||
|
||||
// There's a few exceptions to this rule though:
|
||||
if codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL) {
|
||||
// * `#[rustc_std_internal_symbol]` mangles the symbol name in a special way
|
||||
|
|
|
|||
|
|
@ -35,4 +35,5 @@ pub enum AttributeLintKind {
|
|||
IllFormedAttributeInput { suggestions: Vec<String> },
|
||||
EmptyAttribute { first_span: Span },
|
||||
InvalidTarget { name: AttrPath, target: Target, applied: Vec<String>, only: &'static str },
|
||||
InvalidStyle { name: AttrPath, is_used_as_inner: bool, target: Target, target_span: Span },
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@ use std::borrow::Cow;
|
|||
|
||||
use rustc_abi::Align;
|
||||
use rustc_hir::attrs::{InlineAttr, InstructionSetAttr, Linkage, OptimizeAttr};
|
||||
use rustc_hir::def_id::DefId;
|
||||
use rustc_macros::{HashStable, TyDecodable, TyEncodable};
|
||||
use rustc_span::Symbol;
|
||||
use rustc_target::spec::SanitizerSet;
|
||||
|
|
@ -161,6 +160,8 @@ bitflags::bitflags! {
|
|||
const ALLOCATOR_ZEROED = 1 << 14;
|
||||
/// `#[no_builtins]`: indicates that disable implicit builtin knowledge of functions for the function.
|
||||
const NO_BUILTINS = 1 << 15;
|
||||
/// Marks foreign items, to make `contains_extern_indicator` cheaper.
|
||||
const FOREIGN_ITEM = 1 << 16;
|
||||
}
|
||||
}
|
||||
rustc_data_structures::external_bitflags_debug! { CodegenFnAttrFlags }
|
||||
|
|
@ -194,8 +195,8 @@ impl CodegenFnAttrs {
|
|||
/// * `#[linkage]` is present
|
||||
///
|
||||
/// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint.
|
||||
pub fn contains_extern_indicator(&self, tcx: TyCtxt<'_>, did: DefId) -> bool {
|
||||
if tcx.is_foreign_item(did) {
|
||||
pub fn contains_extern_indicator(&self) -> bool {
|
||||
if self.flags.contains(CodegenFnAttrFlags::FOREIGN_ITEM) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -149,7 +149,7 @@ impl<'tcx> MonoItem<'tcx> {
|
|||
// instantiation:
|
||||
// We emit an unused_attributes lint for this case, which should be kept in sync if possible.
|
||||
let codegen_fn_attrs = tcx.codegen_instance_attrs(instance.def);
|
||||
if codegen_fn_attrs.contains_extern_indicator(tcx, instance.def.def_id())
|
||||
if codegen_fn_attrs.contains_extern_indicator()
|
||||
|| codegen_fn_attrs.flags.contains(CodegenFnAttrFlags::NAKED)
|
||||
{
|
||||
return InstantiationMode::GloballyShared { may_conflict: false };
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
|||
let codegen_fn_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
// If this has an extern indicator, then this function is globally shared and thus will not
|
||||
// generate cgu-internal copies which would make it cross-crate inlinable.
|
||||
if codegen_fn_attrs.contains_extern_indicator(tcx, def_id.into()) {
|
||||
if codegen_fn_attrs.contains_extern_indicator() {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -462,8 +462,10 @@ passes_object_lifetime_err =
|
|||
{$repr}
|
||||
|
||||
passes_outer_crate_level_attr =
|
||||
crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
crate-level attribute should be an inner attribute
|
||||
|
||||
passes_outer_crate_level_attr_suggestion =
|
||||
add a `!`
|
||||
|
||||
passes_panic_unwind_without_std =
|
||||
unwinding panics are not supported without std
|
||||
|
|
|
|||
|
|
@ -369,24 +369,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
|
||||
if hir_id != CRATE_HIR_ID {
|
||||
match attr {
|
||||
// FIXME(jdonszelmann) move to attribute parsing when validation gets better there
|
||||
&Attribute::Parsed(AttributeKind::CrateName {
|
||||
attr_span: span, style, ..
|
||||
}) => match style {
|
||||
ast::AttrStyle::Outer => self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
span,
|
||||
errors::OuterCrateLevelAttr,
|
||||
),
|
||||
ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
span,
|
||||
errors::InnerCrateLevelAttr,
|
||||
),
|
||||
},
|
||||
Attribute::Parsed(_) => { /* not crate-level */ }
|
||||
Attribute::Parsed(_) => { /* Already validated. */ }
|
||||
Attribute::Unparsed(attr) => {
|
||||
// FIXME(jdonszelmann): remove once all crate-level attrs are parsed and caught by
|
||||
// the above
|
||||
|
|
@ -397,12 +380,26 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
.and_then(|ident| BUILTIN_ATTRIBUTE_MAP.get(&ident.name))
|
||||
{
|
||||
match attr.style {
|
||||
ast::AttrStyle::Outer => self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
errors::OuterCrateLevelAttr,
|
||||
),
|
||||
ast::AttrStyle::Outer => {
|
||||
let attr_span = attr.span;
|
||||
let bang_position = self
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_until_char(attr_span, '[')
|
||||
.shrink_to_hi();
|
||||
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span,
|
||||
errors::OuterCrateLevelAttr {
|
||||
suggestion: errors::OuterCrateLevelAttrSuggestion {
|
||||
bang_position,
|
||||
},
|
||||
},
|
||||
)
|
||||
}
|
||||
ast::AttrStyle::Inner => self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
|
|
@ -495,7 +492,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
{
|
||||
let attrs = self.tcx.codegen_fn_attrs(did);
|
||||
// Not checking naked as `#[inline]` is forbidden for naked functions anyways.
|
||||
if attrs.contains_extern_indicator(self.tcx, did.into()) {
|
||||
if attrs.contains_extern_indicator() {
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
|
|
@ -1851,12 +1848,24 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
|
|||
{
|
||||
if hir_id != CRATE_HIR_ID {
|
||||
match style {
|
||||
Some(ast::AttrStyle::Outer) => self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr.span(),
|
||||
errors::OuterCrateLevelAttr,
|
||||
),
|
||||
Some(ast::AttrStyle::Outer) => {
|
||||
let attr_span = attr.span();
|
||||
let bang_position = self
|
||||
.tcx
|
||||
.sess
|
||||
.source_map()
|
||||
.span_until_char(attr_span, '[')
|
||||
.shrink_to_hi();
|
||||
|
||||
self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
attr_span,
|
||||
errors::OuterCrateLevelAttr {
|
||||
suggestion: errors::OuterCrateLevelAttrSuggestion { bang_position },
|
||||
},
|
||||
)
|
||||
}
|
||||
Some(ast::AttrStyle::Inner) | None => self.tcx.emit_node_span_lint(
|
||||
UNUSED_ATTRIBUTES,
|
||||
hir_id,
|
||||
|
|
|
|||
|
|
@ -706,7 +706,7 @@ fn has_allow_dead_code_or_lang_attr(
|
|||
|
||||
// #[used], #[no_mangle], #[export_name], etc also keeps the item alive
|
||||
// forcefully, e.g., for placing it in a specific section.
|
||||
cg_attrs.contains_extern_indicator(tcx, def_id.into())
|
||||
cg_attrs.contains_extern_indicator()
|
||||
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
|
||||
|| cg_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -64,7 +64,17 @@ pub(crate) struct MixedExportNameAndNoMangle {
|
|||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_outer_crate_level_attr)]
|
||||
pub(crate) struct OuterCrateLevelAttr;
|
||||
pub(crate) struct OuterCrateLevelAttr {
|
||||
#[subdiagnostic]
|
||||
pub suggestion: OuterCrateLevelAttrSuggestion,
|
||||
}
|
||||
|
||||
#[derive(Subdiagnostic)]
|
||||
#[multipart_suggestion(passes_outer_crate_level_attr_suggestion, style = "verbose")]
|
||||
pub(crate) struct OuterCrateLevelAttrSuggestion {
|
||||
#[suggestion_part(code = "!")]
|
||||
pub bang_position: Span,
|
||||
}
|
||||
|
||||
#[derive(LintDiagnostic)]
|
||||
#[diag(passes_inner_crate_level_attr)]
|
||||
|
|
|
|||
|
|
@ -183,7 +183,7 @@ impl<'tcx> ReachableContext<'tcx> {
|
|||
} else {
|
||||
CodegenFnAttrs::EMPTY
|
||||
};
|
||||
let is_extern = codegen_attrs.contains_extern_indicator(self.tcx, search_item.into());
|
||||
let is_extern = codegen_attrs.contains_extern_indicator();
|
||||
if is_extern {
|
||||
self.reachable_symbols.insert(search_item);
|
||||
}
|
||||
|
|
@ -425,7 +425,7 @@ fn has_custom_linkage(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
|||
}
|
||||
|
||||
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
codegen_attrs.contains_extern_indicator(tcx, def_id.into())
|
||||
codegen_attrs.contains_extern_indicator()
|
||||
// FIXME(nbdd0121): `#[used]` are marked as reachable here so it's picked up by
|
||||
// `linked_symbols` in cg_ssa. They won't be exported in binary or cdylib due to their
|
||||
// `SymbolExportLevel::Rust` export level but may end up being exported in dylibs.
|
||||
|
|
|
|||
|
|
@ -2419,9 +2419,11 @@ symbols! {
|
|||
yield_expr,
|
||||
ymm_reg,
|
||||
yreg,
|
||||
zca,
|
||||
zfh,
|
||||
zfhmin,
|
||||
zmm_reg,
|
||||
ztso,
|
||||
// tidy-alphabetical-end
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ impl RawVecInner<Global> {
|
|||
}
|
||||
|
||||
// Tiny Vecs are dumb. Skip to:
|
||||
// - 8 if the element size is 1, because any heap allocators is likely
|
||||
// - 8 if the element size is 1, because any heap allocator is likely
|
||||
// to round up a request of less than 8 bytes to at least 8 bytes.
|
||||
// - 4 if elements are moderate-sized (<= 1 KiB).
|
||||
// - 1 otherwise, to avoid wasting too much space for very short Vecs.
|
||||
|
|
|
|||
|
|
@ -167,8 +167,13 @@ impl Step for Std {
|
|||
fn run(self, builder: &Builder<'_>) -> Self::Output {
|
||||
let target = self.target;
|
||||
|
||||
// We already have std ready to be used for stage 0.
|
||||
if self.build_compiler.stage == 0 {
|
||||
// In most cases, we already have the std ready to be used for stage 0.
|
||||
// However, if we are doing a local rebuild (so the build compiler can compile the standard
|
||||
// library even on stage 0), and we're cross-compiling (so the stage0 standard library for
|
||||
// *target* is not available), we still allow the stdlib to be built here.
|
||||
if self.build_compiler.stage == 0
|
||||
&& !(builder.local_rebuild && target != builder.host_target)
|
||||
{
|
||||
let compiler = self.build_compiler;
|
||||
builder.ensure(StdLink::from_std(self, compiler));
|
||||
|
||||
|
|
@ -1332,9 +1337,7 @@ pub fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetS
|
|||
cargo.env("CFG_OMIT_GIT_HASH", "1");
|
||||
}
|
||||
|
||||
if let Some(backend) = builder.config.default_codegen_backend(target) {
|
||||
cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", backend.name());
|
||||
}
|
||||
cargo.env("CFG_DEFAULT_CODEGEN_BACKEND", builder.config.default_codegen_backend(target).name());
|
||||
|
||||
let libdir_relative = builder.config.libdir_relative().unwrap_or_else(|| Path::new("lib"));
|
||||
let target_config = builder.config.target_config.get(&target);
|
||||
|
|
|
|||
|
|
@ -1850,7 +1850,7 @@ HELP: You can add it into `bootstrap.toml` in `rust.codegen-backends = [{name:?}
|
|||
// Tells compiletest which codegen backend to use.
|
||||
// It is used to e.g. ignore tests that don't support that codegen backend.
|
||||
cmd.arg("--default-codegen-backend")
|
||||
.arg(builder.config.default_codegen_backend(compiler.host).unwrap().name());
|
||||
.arg(builder.config.default_codegen_backend(compiler.host).name());
|
||||
}
|
||||
|
||||
if builder.build.config.llvm_enzyme {
|
||||
|
|
|
|||
|
|
@ -1323,12 +1323,7 @@ impl Builder<'_> {
|
|||
|
||||
if let Some(limit) = limit
|
||||
&& (build_compiler_stage == 0
|
||||
|| self
|
||||
.config
|
||||
.default_codegen_backend(target)
|
||||
.cloned()
|
||||
.unwrap_or_default()
|
||||
.is_llvm())
|
||||
|| self.config.default_codegen_backend(target).is_llvm())
|
||||
{
|
||||
rustflags.arg(&format!("-Cllvm-args=-import-instr-limit={limit}"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1435,22 +1435,30 @@ impl<'a> Builder<'a> {
|
|||
// FIXME: make the `Std` step return some type-level "proof" that std was indeed built,
|
||||
// and then require passing that to all Cargo invocations that we do.
|
||||
|
||||
// The "stage 0" std is always precompiled and comes with the stage0 compiler, so we have
|
||||
// special logic for it, to avoid creating needless and confusing Std steps that don't
|
||||
// The "stage 0" std is almost always precompiled and comes with the stage0 compiler, so we
|
||||
// have special logic for it, to avoid creating needless and confusing Std steps that don't
|
||||
// actually build anything.
|
||||
// We only allow building the stage0 stdlib if we do a local rebuild, so the stage0 compiler
|
||||
// actually comes from in-tree sources, and we're cross-compiling, so the stage0 for the
|
||||
// given `target` is not available.
|
||||
if compiler.stage == 0 {
|
||||
if target != compiler.host {
|
||||
panic!(
|
||||
r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
|
||||
if self.local_rebuild {
|
||||
self.ensure(Std::new(compiler, target))
|
||||
} else {
|
||||
panic!(
|
||||
r"It is not possible to build the standard library for `{target}` using the stage0 compiler.
|
||||
You have to build a stage1 compiler for `{}` first, and then use it to build a standard library for `{target}`.
|
||||
Alternatively, you can set `build.local-rebuild=true` and use a stage0 compiler built from in-tree sources.
|
||||
",
|
||||
compiler.host
|
||||
)
|
||||
compiler.host
|
||||
)
|
||||
}
|
||||
} else {
|
||||
// We still need to link the prebuilt standard library into the ephemeral stage0 sysroot
|
||||
self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
|
||||
None
|
||||
}
|
||||
|
||||
// We still need to link the prebuilt standard library into the ephemeral stage0 sysroot
|
||||
self.ensure(StdLink::from_std(Std::new(compiler, target), compiler));
|
||||
None
|
||||
} else {
|
||||
// This step both compiles the std and links it into the compiler's sysroot.
|
||||
// Yes, it's quite magical and side-effecty.. would be nice to refactor later.
|
||||
|
|
|
|||
|
|
@ -853,6 +853,18 @@ mod snapshot {
|
|||
ctx.config("build").path("library").stage(0).run();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_library_stage_0_local_rebuild() {
|
||||
let ctx = TestCtx::new();
|
||||
insta::assert_snapshot!(
|
||||
ctx.config("build")
|
||||
.path("library")
|
||||
.stage(0)
|
||||
.targets(&[TEST_TRIPLE_1])
|
||||
.args(&["--set", "build.local-rebuild=true"])
|
||||
.render_steps(), @"[build] rustc 0 <host> -> std 0 <target1>");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn build_library_stage_1() {
|
||||
let ctx = TestCtx::new();
|
||||
|
|
@ -1696,6 +1708,22 @@ mod snapshot {
|
|||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn dist_library_stage_0_local_rebuild() {
|
||||
let ctx = TestCtx::new();
|
||||
insta::assert_snapshot!(
|
||||
ctx.config("dist")
|
||||
.path("rust-std")
|
||||
.stage(0)
|
||||
.targets(&[TEST_TRIPLE_1])
|
||||
.args(&["--set", "build.local-rebuild=true"])
|
||||
.render_steps(), @r"
|
||||
[build] rustc 0 <host> -> std 0 <target1>
|
||||
[build] rustc 0 <host> -> RustInstaller 1 <host>
|
||||
[dist] rustc 0 <host> -> std 0 <target1>
|
||||
");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_compiler_no_explicit_stage() {
|
||||
let ctx = TestCtx::new();
|
||||
|
|
|
|||
|
|
@ -969,31 +969,38 @@ impl Config {
|
|||
| Subcommand::Vendor { .. } => flags_stage.unwrap_or(0),
|
||||
};
|
||||
|
||||
// Now check that the selected stage makes sense, and if not, print a warning and end
|
||||
let local_rebuild = build_local_rebuild.unwrap_or(false);
|
||||
|
||||
let check_stage0 = |kind: &str| {
|
||||
if local_rebuild {
|
||||
eprintln!("WARNING: running {kind} in stage 0. This might not work as expected.");
|
||||
} else {
|
||||
eprintln!(
|
||||
"ERROR: cannot {kind} anything on stage 0. Use at least stage 1 or set build.local-rebuild=true and use a stage0 compiler built from in-tree sources."
|
||||
);
|
||||
exit!(1);
|
||||
}
|
||||
};
|
||||
|
||||
// Now check that the selected stage makes sense, and if not, print an error and end
|
||||
match (stage, &flags_cmd) {
|
||||
(0, Subcommand::Build { .. }) => {
|
||||
eprintln!("ERROR: cannot build anything on stage 0. Use at least stage 1.");
|
||||
exit!(1);
|
||||
check_stage0("build");
|
||||
}
|
||||
(0, Subcommand::Check { .. }) => {
|
||||
eprintln!("ERROR: cannot check anything on stage 0. Use at least stage 1.");
|
||||
exit!(1);
|
||||
check_stage0("check");
|
||||
}
|
||||
(0, Subcommand::Doc { .. }) => {
|
||||
eprintln!("ERROR: cannot document anything on stage 0. Use at least stage 1.");
|
||||
exit!(1);
|
||||
check_stage0("doc");
|
||||
}
|
||||
(0, Subcommand::Clippy { .. }) => {
|
||||
eprintln!("ERROR: cannot run clippy on stage 0. Use at least stage 1.");
|
||||
exit!(1);
|
||||
check_stage0("clippy");
|
||||
}
|
||||
(0, Subcommand::Dist) => {
|
||||
eprintln!("ERROR: cannot dist anything on stage 0. Use at least stage 1.");
|
||||
exit!(1);
|
||||
check_stage0("dist");
|
||||
}
|
||||
(0, Subcommand::Install) => {
|
||||
eprintln!("ERROR: cannot install anything on stage 0. Use at least stage 1.");
|
||||
exit!(1);
|
||||
check_stage0("install");
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
|
@ -1234,7 +1241,7 @@ impl Config {
|
|||
llvm_use_libcxx: llvm_use_libcxx.unwrap_or(false),
|
||||
llvm_use_linker,
|
||||
llvm_version_suffix,
|
||||
local_rebuild: build_local_rebuild.unwrap_or(false),
|
||||
local_rebuild,
|
||||
locked_deps: build_locked_deps.unwrap_or(false),
|
||||
low_priority: build_low_priority.unwrap_or(false),
|
||||
mandir: install_mandir.map(PathBuf::from),
|
||||
|
|
@ -1663,8 +1670,9 @@ impl Config {
|
|||
|
||||
/// Returns the codegen backend that should be configured as the *default* codegen backend
|
||||
/// for a rustc compiled by bootstrap.
|
||||
pub fn default_codegen_backend(&self, target: TargetSelection) -> Option<&CodegenBackendKind> {
|
||||
self.enabled_codegen_backends(target).first()
|
||||
pub fn default_codegen_backend(&self, target: TargetSelection) -> &CodegenBackendKind {
|
||||
// We're guaranteed to have always at least one codegen backend listed.
|
||||
self.enabled_codegen_backends(target).first().unwrap()
|
||||
}
|
||||
|
||||
pub fn jemalloc(&self, target: TargetSelection) -> bool {
|
||||
|
|
|
|||
|
|
@ -415,6 +415,10 @@ pub(crate) fn parse_codegen_backends(
|
|||
};
|
||||
found_backends.push(backend);
|
||||
}
|
||||
if found_backends.is_empty() {
|
||||
eprintln!("ERROR: `{section}.codegen-backends` should not be set to `[]`");
|
||||
exit!(1);
|
||||
}
|
||||
found_backends
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -526,4 +526,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
|
|||
severity: ChangeSeverity::Info,
|
||||
summary: "The `optimized-compiler-builtins` option now accepts a path to an existing compiler-rt builtins library.",
|
||||
},
|
||||
ChangeInfo {
|
||||
change_id: 145876,
|
||||
severity: ChangeSeverity::Info,
|
||||
summary: "It is now possible to `check/build/dist` the standard stage 0 library if you use a stage0 rustc built from in-tree sources. This is useful for quickly cross-compiling the standard library. You have to enable build.local-rebuild for this to work.",
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -26,23 +26,10 @@ ENV CC_aarch64_pc_windows_gnullvm=aarch64-w64-mingw32-clang \
|
|||
|
||||
ENV HOST=aarch64-pc-windows-gnullvm
|
||||
|
||||
# We are bootstrapping this target and cannot use previously built artifacts.
|
||||
# Without this option Clang is given `"-I/checkout/obj/build/aarch64-pc-windows-gnullvm/ci-llvm/include"`
|
||||
# despite no such directory existing:
|
||||
# $ ls obj/dist-windows-gnullvm/build/aarch64-pc-windows-gnullvm/ -1
|
||||
# llvm
|
||||
# stage2
|
||||
ENV NO_DOWNLOAD_CI_LLVM 1
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--enable-extended \
|
||||
--enable-full-tools \
|
||||
--enable-profiler \
|
||||
--enable-sanitizers \
|
||||
--disable-docs \
|
||||
--set llvm.download-ci-llvm=false \
|
||||
--set rust.llvm-tools=false
|
||||
# LLVM cross tools are not installed into expected location so copying fails.
|
||||
# Probably will solve itself once this target can host itself on Windows.
|
||||
# --enable-full-tools \
|
||||
--disable-docs
|
||||
|
||||
ENV SCRIPT python3 ../x.py dist --host $HOST --target $HOST
|
||||
|
|
|
|||
|
|
@ -28,23 +28,10 @@ ENV CC_i686_pc_windows_gnullvm=i686-w64-mingw32-clang \
|
|||
ENV HOST=x86_64-pc-windows-gnullvm
|
||||
ENV TARGETS=i686-pc-windows-gnullvm,x86_64-pc-windows-gnullvm
|
||||
|
||||
# We are bootstrapping this target and cannot use previously built artifacts.
|
||||
# Without this option Clang is given `"-I/checkout/obj/build/aarch64-pc-windows-gnullvm/ci-llvm/include"`
|
||||
# despite no such directory existing:
|
||||
# $ ls obj/dist-windows-gnullvm/build/aarch64-pc-windows-gnullvm/ -1
|
||||
# llvm
|
||||
# stage2
|
||||
ENV NO_DOWNLOAD_CI_LLVM 1
|
||||
|
||||
ENV RUST_CONFIGURE_ARGS \
|
||||
--enable-extended \
|
||||
--enable-full-tools \
|
||||
--enable-profiler \
|
||||
--enable-sanitizers \
|
||||
--disable-docs \
|
||||
--set llvm.download-ci-llvm=false \
|
||||
--set rust.llvm-tools=false
|
||||
# LLVM cross tools are not installed into expected location so copying fails.
|
||||
# Probably will solve itself once these targets can host themselves on Windows.
|
||||
# --enable-full-tools \
|
||||
--disable-docs
|
||||
|
||||
ENV SCRIPT python3 ../x.py dist --host $HOST --target $TARGETS
|
||||
|
|
|
|||
|
|
@ -38,11 +38,15 @@ ENV RUST_CONFIGURE_ARGS \
|
|||
--build=x86_64-unknown-linux-gnu \
|
||||
--enable-debug \
|
||||
--enable-lld \
|
||||
--set rust.debuginfo-level-tests=1 \
|
||||
--set llvm.use-linker=lld \
|
||||
--set target.x86_64-unknown-linux-gnu.linker=clang \
|
||||
--set target.x86_64-unknown-linux-gnu.cc=clang \
|
||||
--set target.x86_64-unknown-linux-gnu.cxx=clang++
|
||||
|
||||
# This job checks:
|
||||
# - That ui tests can be built with `-Cdebuginfo=1`
|
||||
|
||||
# This job appears to be checking two separate things:
|
||||
# - That we can build the compiler with `--enable-debug`
|
||||
# (without necessarily testing the result).
|
||||
|
|
@ -51,4 +55,5 @@ ENV RUST_CONFIGURE_ARGS \
|
|||
|
||||
ENV SCRIPT \
|
||||
python3 ../x.py --stage 2 build && \
|
||||
python3 ../x.py --stage 2 test tests/ui && \
|
||||
python3 ../x.py --stage 2 test tests/run-make
|
||||
|
|
|
|||
|
|
@ -328,8 +328,8 @@ target | std | host | notes
|
|||
[`i686-win7-windows-msvc`](platform-support/win7-windows-msvc.md) | ✓ | | 32-bit Windows 7 support [^x86_32-floats-return-ABI] [^win32-msvc-alignment]
|
||||
[`i686-wrs-vxworks`](platform-support/vxworks.md) | ✓ | | [^x86_32-floats-return-ABI]
|
||||
[`loongarch64-unknown-linux-ohos`](platform-support/openharmony.md) | ✓ | | LoongArch64 OpenHarmony
|
||||
[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32D ABI)
|
||||
[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch32 Bare-metal (ILP32S ABI)
|
||||
[`loongarch32-unknown-none`](platform-support/loongarch-none.md) | * | | LoongArch32 Bare-metal (ILP32D ABI)
|
||||
[`loongarch32-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | | LoongArch32 Bare-metal (ILP32S ABI)
|
||||
[`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? | | Motorola 680x0 Linux
|
||||
[`m68k-unknown-none-elf`](platform-support/m68k-unknown-none-elf.md) | | | Motorola 680x0
|
||||
`mips-unknown-linux-gnu` | ✓ | ✓ | MIPS Linux (kernel 4.4, glibc 2.23)
|
||||
|
|
|
|||
|
|
@ -190,5 +190,5 @@ impl<'tcx> LateLintPass<'tcx> for MissingInline {
|
|||
/// and a rustc warning would be triggered, see #15301
|
||||
fn fn_is_externally_exported(cx: &LateContext<'_>, def_id: DefId) -> bool {
|
||||
let attrs = cx.tcx.codegen_fn_attrs(def_id);
|
||||
attrs.contains_extern_indicator(cx.tcx, def_id)
|
||||
attrs.contains_extern_indicator()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -279,7 +279,7 @@ impl rustc_driver::Callbacks for MiriBeRustCompilerCalls {
|
|||
return None;
|
||||
}
|
||||
let codegen_fn_attrs = tcx.codegen_fn_attrs(local_def_id);
|
||||
if codegen_fn_attrs.contains_extern_indicator(tcx, local_def_id.into())
|
||||
if codegen_fn_attrs.contains_extern_indicator()
|
||||
|| codegen_fn_attrs
|
||||
.flags
|
||||
.contains(CodegenFnAttrFlags::USED_COMPILER)
|
||||
|
|
|
|||
|
|
@ -134,8 +134,7 @@ pub fn iter_exported_symbols<'tcx>(
|
|||
for def_id in crate_items.definitions() {
|
||||
let exported = tcx.def_kind(def_id).has_codegen_attrs() && {
|
||||
let codegen_attrs = tcx.codegen_fn_attrs(def_id);
|
||||
codegen_attrs.contains_extern_indicator(tcx, def_id.into())
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::RUSTC_STD_INTERNAL_SYMBOL)
|
||||
codegen_attrs.contains_extern_indicator()
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)
|
||||
|| codegen_attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)
|
||||
};
|
||||
|
|
|
|||
10
tests/ui/attributes/crate-only-as-outer.rs
Normal file
10
tests/ui/attributes/crate-only-as-outer.rs
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#![deny(unused)]
|
||||
#[crate_name = "owo"]
|
||||
//~^ ERROR: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
|
||||
|
||||
fn main() {}
|
||||
|
||||
mod inner {
|
||||
#![crate_name = "iwi"]
|
||||
//~^ ERROR: the `#![crate_name]` attribute can only be used at the crate root
|
||||
}
|
||||
26
tests/ui/attributes/crate-only-as-outer.stderr
Normal file
26
tests/ui/attributes/crate-only-as-outer.stderr
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
|
||||
--> $DIR/crate-only-as-outer.rs:2:1
|
||||
|
|
||||
LL | #[crate_name = "owo"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: This attribute does not have an `!`, which means it is applied to this function
|
||||
--> $DIR/crate-only-as-outer.rs:5:1
|
||||
|
|
||||
LL | fn main() {}
|
||||
| ^^^^^^^^^^^^
|
||||
note: the lint level is defined here
|
||||
--> $DIR/crate-only-as-outer.rs:1:9
|
||||
|
|
||||
LL | #![deny(unused)]
|
||||
| ^^^^^^
|
||||
= note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
|
||||
|
||||
error: the `#![crate_name]` attribute can only be used at the crate root
|
||||
--> $DIR/crate-only-as-outer.rs:8:5
|
||||
|
|
||||
LL | #![crate_name = "iwi"]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
@ -1,4 +1,8 @@
|
|||
//@ check-pass
|
||||
//@ ignore-windows
|
||||
//@ compile-flags: -Cremark=foo --error-format=human --color=always
|
||||
|
||||
// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
|
||||
//@ compile-flags: -Cdebuginfo=0
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
|
|
@ -482,21 +482,26 @@ mod no_implicit_prelude {
|
|||
|
||||
#[reexport_test_harness_main = "2900"]
|
||||
//~^ WARN crate-level attribute should be
|
||||
//~| HELP add a `!`
|
||||
mod reexport_test_harness_main {
|
||||
mod inner { #![reexport_test_harness_main="2900"] }
|
||||
//~^ WARN crate-level attribute should be
|
||||
|
||||
#[reexport_test_harness_main = "2900"] fn f() { }
|
||||
//~^ WARN crate-level attribute should be
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[reexport_test_harness_main = "2900"] struct S;
|
||||
//~^ WARN crate-level attribute should be
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[reexport_test_harness_main = "2900"] type T = S;
|
||||
//~^ WARN crate-level attribute should be
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[reexport_test_harness_main = "2900"] impl S { }
|
||||
//~^ WARN crate-level attribute should be
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
// Cannot feed "2700" to `#[macro_escape]` without signaling an error.
|
||||
|
|
@ -534,21 +539,26 @@ mod macro_escape {
|
|||
|
||||
#[no_std]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
mod no_std {
|
||||
mod inner { #![no_std] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[no_std] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_std] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_std] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_std] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
// At time of authorship, #[proc_macro_derive = "2500"] signals error
|
||||
|
|
@ -760,21 +770,26 @@ mod must_use {
|
|||
|
||||
#[windows_subsystem = "windows"]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
mod windows_subsystem {
|
||||
mod inner { #![windows_subsystem="windows"] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[windows_subsystem = "windows"] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[windows_subsystem = "windows"] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[windows_subsystem = "windows"] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[windows_subsystem = "windows"] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
// BROKEN USES OF CRATE-LEVEL BUILT-IN ATTRIBUTES
|
||||
|
|
@ -782,135 +797,170 @@ mod windows_subsystem {
|
|||
#[crate_name = "0900"]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
mod crate_name {
|
||||
//~^ NOTE This attribute does not have an `!`, which means it is applied to this module
|
||||
mod inner { #![crate_name="0900"] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
//~^ WARN the `#![crate_name]` attribute can only be used at the crate root
|
||||
|
||||
#[crate_name = "0900"] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| NOTE This attribute does not have an `!`, which means it is applied to this function
|
||||
|
||||
#[crate_name = "0900"] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| NOTE This attribute does not have an `!`, which means it is applied to this struct
|
||||
|
||||
#[crate_name = "0900"] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| NOTE This attribute does not have an `!`, which means it is applied to this type alias
|
||||
|
||||
#[crate_name = "0900"] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| NOTE This attribute does not have an `!`, which means it is applied to this implementation block
|
||||
}
|
||||
|
||||
#[crate_type = "0800"]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
mod crate_type {
|
||||
mod inner { #![crate_type="0800"] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[crate_type = "0800"] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[crate_type = "0800"] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[crate_type = "0800"] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[crate_type = "0800"] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
#[feature(x0600)]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
mod feature {
|
||||
mod inner { #![feature(x0600)] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[feature(x0600)] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[feature(x0600)] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[feature(x0600)] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[feature(x0600)] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
|
||||
#[no_main]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
mod no_main_1 {
|
||||
mod inner { #![no_main] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[no_main] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_main] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_main] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_main] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
#[no_builtins]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
mod no_builtins {
|
||||
mod inner { #![no_builtins] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[no_builtins] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_builtins] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_builtins] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[no_builtins] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
#[recursion_limit="0200"]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
mod recursion_limit {
|
||||
mod inner { #![recursion_limit="0200"] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[recursion_limit="0200"] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[recursion_limit="0200"] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[recursion_limit="0200"] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[recursion_limit="0200"] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
#[type_length_limit="0100"]
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
mod type_length_limit {
|
||||
mod inner { #![type_length_limit="0100"] }
|
||||
//~^ WARN crate-level attribute should be in the root module
|
||||
|
||||
#[type_length_limit="0100"] fn f() { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[type_length_limit="0100"] struct S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[type_length_limit="0100"] type T = S;
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
|
||||
#[type_length_limit="0100"] impl S { }
|
||||
//~^ WARN crate-level attribute should be an inner attribute
|
||||
//~| HELP add a `!`
|
||||
}
|
||||
|
||||
fn main() {}
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -2,6 +2,9 @@
|
|||
//
|
||||
//@ run-pass
|
||||
|
||||
// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
|
||||
//@ compile-flags: -Cdebuginfo=0
|
||||
|
||||
#![allow(unused_variables)]
|
||||
|
||||
macro_rules! m(
|
||||
|
|
|
|||
|
|
@ -2,6 +2,9 @@
|
|||
//@ normalize-stderr: "std::option::Option<\[u32; \d+\]>" -> "TYPE"
|
||||
//@ normalize-stderr: "\[u32; \d+\]" -> "TYPE"
|
||||
|
||||
// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
|
||||
//@ compile-flags: -Cdebuginfo=0
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
type BIG = Option<[u32; (1<<29)-1]>;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
error: values of the type `Option<TYPE>` are too big for the target architecture
|
||||
--> $DIR/huge-enum.rs:12:9
|
||||
--> $DIR/huge-enum.rs:15:9
|
||||
|
|
||||
LL | let big: BIG = None;
|
||||
| ^^^
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
warning: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
warning: crate-level attribute should be an inner attribute
|
||||
--> $DIR/linker-warning.rs:7:1
|
||||
|
|
||||
LL | #[allow(linker_messages)]
|
||||
|
|
@ -9,6 +9,10 @@ note: the lint level is defined here
|
|||
|
|
||||
LL | #![warn(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
help: add a `!`
|
||||
|
|
||||
LL | #![allow(linker_messages)]
|
||||
| +
|
||||
|
||||
warning: unused attribute
|
||||
--> $DIR/linker-warning.rs:4:1
|
||||
|
|
|
|||
|
|
@ -10,11 +10,16 @@ note: the lint level is defined here
|
|||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
error: crate-level attribute should be an inner attribute
|
||||
--> $DIR/lint-misplaced-attr.rs:10:1
|
||||
|
|
||||
LL | #[crate_type = "bin"] fn main() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: add a `!`
|
||||
|
|
||||
LL | #![crate_type = "bin"] fn main() {}
|
||||
| +
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#![deny(unused)]
|
||||
|
||||
#[crate_name = concat !()]
|
||||
//~^ ERROR crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]
|
||||
//~^ ERROR crate-level attribute should be an inner attribute
|
||||
macro_rules! a {
|
||||
//~^ ERROR unused macro definition
|
||||
() => {};
|
||||
|
|
|
|||
|
|
@ -11,12 +11,20 @@ LL | #![deny(unused)]
|
|||
| ^^^^^^
|
||||
= note: `#[deny(unused_macros)]` implied by `#[deny(unused)]`
|
||||
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![crate_name]`
|
||||
--> $DIR/concat-in-crate-name-issue-137687.rs:3:1
|
||||
|
|
||||
LL | #[crate_name = concat !()]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
note: This attribute does not have an `!`, which means it is applied to this macro def
|
||||
--> $DIR/concat-in-crate-name-issue-137687.rs:5:1
|
||||
|
|
||||
LL | / macro_rules! a {
|
||||
LL | |
|
||||
LL | | () => {};
|
||||
LL | | }
|
||||
| |_^
|
||||
= note: `#[deny(unused_attributes)]` implied by `#[deny(unused)]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
error: crate-level attribute should be an inner attribute: add an exclamation mark: `#![foo]`
|
||||
error: crate-level attribute should be an inner attribute
|
||||
--> $DIR/unused-attr-macro-rules.rs:11:1
|
||||
|
|
||||
LL | #[recursion_limit="1"]
|
||||
|
|
@ -9,6 +9,10 @@ note: the lint level is defined here
|
|||
|
|
||||
LL | #![deny(unused_attributes)]
|
||||
| ^^^^^^^^^^^^^^^^^
|
||||
help: add a `!`
|
||||
|
|
||||
LL | #![recursion_limit="1"]
|
||||
| +
|
||||
|
||||
error: `#[macro_use]` attribute cannot be used on macro defs
|
||||
--> $DIR/unused-attr-macro-rules.rs:7:1
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
//@ check-run-results
|
||||
//@ exec-env:RUST_BACKTRACE=1
|
||||
|
||||
// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
|
||||
//@ compile-flags: -Cdebuginfo=0
|
||||
|
||||
// This is needed to avoid test output differences across std being built with v0 symbols vs legacy
|
||||
// symbols.
|
||||
//@ normalize-stderr: "begin_panic::<&str>" -> "begin_panic"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
thread 'main' ($TID) panicked at $DIR/issue-47429-short-backtraces.rs:24:5:
|
||||
thread 'main' ($TID) panicked at $DIR/issue-47429-short-backtraces.rs:27:5:
|
||||
explicit panic
|
||||
stack backtrace:
|
||||
0: std::panicking::begin_panic
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@
|
|||
//@ check-run-results
|
||||
//@ exec-env:RUST_BACKTRACE=0
|
||||
|
||||
// FIXME(#61117): Respect debuginfo-level-tests, do not force debuginfo-level=0
|
||||
//@ compile-flags: -Cdebuginfo=0
|
||||
|
||||
// This is needed to avoid test output differences across std being built with v0 symbols vs legacy
|
||||
// symbols.
|
||||
//@ normalize-stderr: "begin_panic::<&str>" -> "begin_panic"
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
|
||||
thread 'main' ($TID) panicked at $DIR/runtime-switch.rs:28:5:
|
||||
thread 'main' ($TID) panicked at $DIR/runtime-switch.rs:31:5:
|
||||
explicit panic
|
||||
stack backtrace:
|
||||
0: std::panicking::begin_panic
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue