Auto merge of #145728 - jhpratt:rollup-nwbw8de, r=jhpratt

Rollup of 16 pull requests

Successful merges:

 - rust-lang/rust#137494 (libstd: init(): dup() subsequent /dev/nulls instead of opening them again)
 - rust-lang/rust#144541 (c-variadic: multiple ABIs in the same program for arm)
 - rust-lang/rust#144613 (aarch64-nintendo-switch-freestanding - Enable CPU features that are always available in a live system (crypto instructions, plus explicit NEON).)
 - rust-lang/rust#144780 (Add a method to dump MIR in the middle of MIR building)
 - rust-lang/rust#145137 (Consolidate panicking functions in `slice/index.rs`)
 - rust-lang/rust#145507 (Refactor attribute parsing to improve ergonomics and some diagnostics)
 - rust-lang/rust#145604 (Gate static closures behind a parser feature)
 - rust-lang/rust#145648 (Add two tidy dependency checks)
 - rust-lang/rust#145661 (update some s390x codegen tests)
 - rust-lang/rust#145672 (Instantiate higher-ranked binder with erased when checking `IntoIterator` predicate for query instability)
 - rust-lang/rust#145689 (Migrate `panic_unwind` to use `cfg_select!`)
 - rust-lang/rust#145700 (Handle `ReEarlyParam` in `type_name`.)
 - rust-lang/rust#145703 (Remove MIPS targets from CI LLVM platforms)
 - rust-lang/rust#145704 (ci: don't cleanup windows disk)
 - rust-lang/rust#145705 (remove an `as` cast in prefetch codegen)
 - rust-lang/rust#145712 (Update outdated link in bound region comments)

r? `@ghost`
`@rustbot` modify labels: rollup
This commit is contained in:
bors 2025-08-21 22:57:46 +00:00
commit 8e3710ef31
109 changed files with 1505 additions and 1437 deletions

View File

@ -117,12 +117,12 @@ jobs:
with:
fetch-depth: 2
# Free up disk space on Linux and Windows by removing preinstalled components that
# Free up disk space on Linux by removing preinstalled components that
# we do not need. We do this to enable some of the less resource
# intensive jobs to run on free runners, which however also have
# less disk space.
- name: free up disk space
run: src/ci/scripts/free-disk-space.sh
run: src/ci/scripts/free-disk-space-linux.sh
if: matrix.free_disk
# If we don't need to free up disk space then just report how much space we have
@ -223,11 +223,6 @@ jobs:
cd src/ci/citool
CARGO_INCREMENTAL=0 CARGO_TARGET_DIR=../../../build/citool cargo build
- name: wait for Windows disk cleanup to finish
if: ${{ matrix.free_disk && startsWith(matrix.os, 'windows-') }}
run: |
python3 src/ci/scripts/free-disk-space-windows-wait.py
- name: run the build
run: |
set +e

View File

@ -3481,7 +3481,6 @@ dependencies = [
name = "rustc_attr_parsing"
version = "0.0.0"
dependencies = [
"itertools",
"rustc_abi",
"rustc_ast",
"rustc_ast_pretty",

View File

@ -524,6 +524,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
gate_all!(where_clause_attrs, "attributes in `where` clause are unstable");
gate_all!(super_let, "`super let` is experimental");
gate_all!(frontmatter, "frontmatters are experimental");
gate_all!(coroutines, "coroutine syntax is experimental");
if !visitor.features.never_patterns() {
if let Some(spans) = spans.get(&sym::never_patterns) {

View File

@ -5,7 +5,6 @@ edition = "2024"
[dependencies]
# tidy-alphabetical-start
itertools = "0.12"
rustc_abi = { path = "../rustc_abi" }
rustc_ast = { path = "../rustc_ast" }
rustc_ast_pretty = { path = "../rustc_ast_pretty" }

View File

@ -1,14 +1,6 @@
use std::iter;
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use super::{CombineAttributeParser, ConvertFn};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
use super::prelude::*;
use crate::session_diagnostics;
pub(crate) struct AllowInternalUnstableParser;

View File

@ -1,12 +1,6 @@
//! Attributes that can be found in function body.
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};
use super::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::Allow;
use crate::context::{AllowedTargets, Stage};
use super::prelude::*;
pub(crate) struct CoroutineParser;

View File

@ -1,16 +1,7 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::{AttributeKind, CoverageAttrKind, OptimizeAttr, UsedBy};
use rustc_hir::{MethodKind, Target};
use rustc_hir::attrs::{CoverageAttrKind, OptimizeAttr, UsedBy};
use rustc_session::parse::feature_err;
use rustc_span::{Span, Symbol, sym};
use super::{
AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
use crate::parser::ArgParser;
use super::prelude::*;
use crate::session_diagnostics::{NakedFunctionIncompatibleAttribute, NullOnExport};
pub(crate) struct OptimizeParser;

View File

@ -1,13 +1,6 @@
use rustc_feature::template;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use thin_vec::ThinVec;
use super::prelude::*;
use crate::session_diagnostics::EmptyConfusables;
use super::{AcceptMapping, AttributeParser};
use crate::context::MaybeWarn::Allow;
use crate::context::{AllowedTargets, FinalizeContext, Stage};
use crate::session_diagnostics;
#[derive(Default)]
pub(crate) struct ConfusablesParser {
confusables: ThinVec<Symbol>,
@ -25,7 +18,7 @@ impl<S: Stage> AttributeParser<S> for ConfusablesParser {
};
if list.is_empty() {
cx.emit_err(session_diagnostics::EmptyConfusables { span: cx.attr_span });
cx.emit_err(EmptyConfusables { span: cx.attr_span });
}
for param in list.mixed() {

View File

@ -1,14 +1,11 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation};
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use rustc_hir::attrs::{DeprecatedSince, Deprecation};
use super::prelude::*;
use super::util::parse_version;
use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::MaybeWarn::{Allow, Error};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;
use crate::session_diagnostics::{
DeprecatedItemSuggestion, InvalidSince, MissingNote, MissingSince,
};
pub(crate) struct DeprecationParser;
fn get<S: Stage>(
@ -102,7 +99,7 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
}
Some(name @ sym::suggestion) => {
if !features.deprecated_suggestion() {
cx.emit_err(session_diagnostics::DeprecatedItemSuggestion {
cx.emit_err(DeprecatedItemSuggestion {
span: param.span(),
is_nightly: cx.sess().is_nightly_build(),
details: (),
@ -144,18 +141,18 @@ impl<S: Stage> SingleAttributeParser<S> for DeprecationParser {
} else if let Some(version) = parse_version(since) {
DeprecatedSince::RustcVersion(version)
} else {
cx.emit_err(session_diagnostics::InvalidSince { span: cx.attr_span });
cx.emit_err(InvalidSince { span: cx.attr_span });
DeprecatedSince::Err
}
} else if is_rustc {
cx.emit_err(session_diagnostics::MissingSince { span: cx.attr_span });
cx.emit_err(MissingSince { span: cx.attr_span });
DeprecatedSince::Err
} else {
DeprecatedSince::Unspecified
};
if is_rustc && note.is_none() {
cx.emit_err(session_diagnostics::MissingNote { span: cx.attr_span });
cx.emit_err(MissingNote { span: cx.attr_span });
return None;
}

View File

@ -3,8 +3,10 @@ use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
pub(crate) struct DummyParser;
impl<S: Stage> SingleAttributeParser<S> for DummyParser {
const PATH: &[Symbol] = &[sym::rustc_dummy];

View File

@ -2,17 +2,10 @@
// note: need to model better how duplicate attr errors work when not using
// SingleAttributeParser which is what we have two of here.
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::{AttributeKind, InlineAttr};
use rustc_hir::lints::AttributeLintKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Symbol, sym};
use super::{AcceptContext, AttributeOrder, OnDuplicate};
use crate::attributes::SingleAttributeParser;
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AllowedTargets, Stage};
use crate::parser::ArgParser;
use super::prelude::*;
pub(crate) struct InlineParser;
impl<S: Stage> SingleAttributeParser<S> for InlineParser {

View File

@ -1,16 +1,10 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind::{LinkName, LinkOrdinal, LinkSection};
use rustc_hir::attrs::{AttributeKind, Linkage};
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use rustc_hir::attrs::Linkage;
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::MaybeWarn::Allow;
use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage, parse_single_integer};
use crate::parser::ArgParser;
use super::prelude::*;
use super::util::parse_single_integer;
use crate::session_diagnostics::{LinkOrdinalOutOfRange, NullOnLinkSection};
pub(crate) struct LinkNameParser;
impl<S: Stage> SingleAttributeParser<S> for LinkNameParser {

View File

@ -1,10 +1,5 @@
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use super::prelude::*;
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::{Allow, Error};
use crate::context::{AllowedTargets, Stage};
pub(crate) struct AsPtrParser;
impl<S: Stage> NoArgsAttributeParser<S> for AsPtrParser {
const PATH: &[Symbol] = &[sym::rustc_as_ptr];

View File

@ -1,10 +1,5 @@
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol, sym};
use super::prelude::*;
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::Allow;
use crate::context::{AllowedTargets, Stage};
pub(crate) struct LoopMatchParser;
impl<S: Stage> NoArgsAttributeParser<S> for LoopMatchParser {
const PATH: &[Symbol] = &[sym::loop_match];

View File

@ -1,15 +1,9 @@
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::{AttributeKind, MacroUseArgs};
use rustc_span::{Span, Symbol, sym};
use thin_vec::ThinVec;
use rustc_hir::attrs::MacroUseArgs;
use super::prelude::*;
use crate::session_diagnostics::IllFormedAttributeInputLint;
use crate::attributes::{AcceptMapping, AttributeParser, NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::{Allow, Error, Warn};
use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;
pub(crate) struct MacroEscapeParser;
impl<S: Stage> NoArgsAttributeParser<S> for MacroEscapeParser {
const PATH: &[Symbol] = &[sym::macro_escape];
@ -108,7 +102,7 @@ impl<S: Stage> AttributeParser<S> for MacroUseParser {
}
ArgParser::NameValue(_) => {
let suggestions = MACRO_USE_TEMPLATE.suggestions(cx.attr_style, sym::macro_use);
cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
cx.emit_err(IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),

View File

@ -7,9 +7,9 @@
//! Specifically, you might not care about managing the state of your [`AttributeParser`]
//! state machine yourself. In this case you can choose to implement:
//!
//! - [`SingleAttributeParser`]: makes it easy to implement an attribute which should error if it
//! - [`SingleAttributeParser`](crate::attributes::SingleAttributeParser): makes it easy to implement an attribute which should error if it
//! appears more than once in a list of attributes
//! - [`CombineAttributeParser`]: makes it easy to implement an attribute which should combine the
//! - [`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
//!
//! Attributes should be added to `crate::context::ATTRIBUTE_PARSERS` to be parsed.
@ -21,9 +21,13 @@ use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol};
use thin_vec::ThinVec;
use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
use crate::context::{AcceptContext, FinalizeContext, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics::UnusedMultiple;
use crate::target_checking::AllowedTargets;
/// All the parsers require roughly the same imports, so this prelude has most of the often-needed ones.
mod prelude;
pub(crate) mod allow_unstable;
pub(crate) mod body;

View File

@ -1,14 +1,8 @@
use rustc_errors::DiagArgValue;
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Symbol, sym};
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::MaybeWarn::{Allow, Error};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
use crate::session_diagnostics;
use super::prelude::*;
use crate::session_diagnostics::IllFormedAttributeInputLint;
pub(crate) struct MustUseParser;
impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
@ -53,7 +47,7 @@ impl<S: Stage> SingleAttributeParser<S> for MustUseParser {
ArgParser::List(_) => {
let suggestions = <Self as SingleAttributeParser<S>>::TEMPLATE
.suggestions(cx.attr_style, "must_use");
cx.emit_err(session_diagnostics::IllFormedAttributeInputLint {
cx.emit_err(IllFormedAttributeInputLint {
num_suggestions: suggestions.len(),
suggestions: DiagArgValue::StrListSepByAnd(
suggestions.into_iter().map(|s| format!("`{s}`").into()).collect(),

View File

@ -1,10 +1,5 @@
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, sym};
use super::prelude::*;
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::Allow;
use crate::context::{AllowedTargets, Stage};
pub(crate) struct NoImplicitPreludeParser;
impl<S: Stage> NoArgsAttributeParser<S> for NoImplicitPreludeParser {

View File

@ -3,8 +3,10 @@ use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol, sym};
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AllowedTargets, Stage};
use crate::context::Stage;
use crate::target_checking::AllowedTargets;
use crate::target_checking::Policy::{Allow, Warn};
pub(crate) struct NonExhaustiveParser;
impl<S: Stage> NoArgsAttributeParser<S> for NonExhaustiveParser {

View File

@ -1,12 +1,5 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};
use super::prelude::*;
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::MaybeWarn::{Allow, Error};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
pub(crate) struct PathParser;
impl<S: Stage> SingleAttributeParser<S> for PathParser {

View File

@ -0,0 +1,20 @@
// parsing
// templates
pub(super) use rustc_feature::{AttributeTemplate, template};
// data structures
pub(super) use rustc_hir::attrs::AttributeKind;
pub(super) use rustc_hir::lints::AttributeLintKind;
pub(super) use rustc_hir::{MethodKind, Target};
pub(super) use rustc_span::{DUMMY_SP, Ident, Span, Symbol, sym};
pub(super) use thin_vec::ThinVec;
pub(super) use crate::attributes::{
AcceptMapping, AttributeOrder, AttributeParser, CombineAttributeParser, ConvertFn,
NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
// contexts
pub(super) use crate::context::{AcceptContext, FinalizeContext, Stage};
pub(super) use crate::parser::*;
// target checking
pub(super) use crate::target_checking::Policy::{Allow, Error, Warn};
pub(super) use crate::target_checking::{ALL_TARGETS, AllowedTargets};

View File

@ -1,15 +1,5 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol, sym};
use thin_vec::ThinVec;
use super::prelude::*;
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
pub(crate) struct ProcMacroParser;
impl<S: Stage> NoArgsAttributeParser<S> for ProcMacroParser {
const PATH: &[Symbol] = &[sym::proc_macro];

View File

@ -7,8 +7,10 @@ use rustc_span::{Span, Symbol, sym};
use super::{AttributeOrder, OnDuplicate};
use crate::attributes::SingleAttributeParser;
use crate::context::{AcceptContext, AllowedTargets, MaybeWarn, Stage};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::AllowedTargets;
use crate::target_checking::Policy::Allow;
pub(crate) struct CustomMirParser;
@ -19,8 +21,7 @@ impl<S: Stage> SingleAttributeParser<S> for CustomMirParser {
const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
const ALLOWED_TARGETS: AllowedTargets =
AllowedTargets::AllowList(&[MaybeWarn::Allow(Target::Fn)]);
const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
const TEMPLATE: AttributeTemplate = template!(List: &[r#"dialect = "...", phase = "...""#]);

View File

@ -1,16 +1,10 @@
use rustc_abi::Align;
use rustc_ast::{IntTy, LitIntType, LitKind, UintTy};
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::{AttributeKind, IntType, ReprAttr};
use rustc_hir::{MethodKind, Target};
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use rustc_hir::attrs::{IntType, ReprAttr};
use super::prelude::*;
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
use super::{AcceptMapping, AttributeParser, CombineAttributeParser, ConvertFn, FinalizeContext};
use crate::context::MaybeWarn::Allow;
use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
use crate::parser::{ArgParser, MetaItemListParser, MetaItemParser};
use crate::session_diagnostics;
use crate::session_diagnostics::IncorrectReprFormatGenericCause;
/// Parse #[repr(...)] forms.
///
/// Valid repr contents: any of the primitive integral type names (see

View File

@ -1,12 +1,6 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Symbol, sym};
use super::prelude::*;
use super::util::parse_single_integer;
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::MaybeWarn::Allow;
use crate::context::{AcceptContext, AllowedTargets, Stage, parse_single_integer};
use crate::parser::ArgParser;
pub(crate) struct RustcLayoutScalarValidRangeStart;
impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStart {

View File

@ -1,8 +1,5 @@
use rustc_hir::attrs::AttributeKind;
use rustc_span::{Span, Symbol, sym};
use super::prelude::*;
use crate::attributes::{NoArgsAttributeParser, OnDuplicate};
use crate::context::{ALL_TARGETS, AllowedTargets, Stage};
pub(crate) struct MayDangleParser;
impl<S: Stage> NoArgsAttributeParser<S> for MayDangleParser {
const PATH: &[Symbol] = &[sym::may_dangle];

View File

@ -1,20 +1,13 @@
use std::num::NonZero;
use rustc_errors::ErrorGuaranteed;
use rustc_feature::template;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{
DefaultBodyStability, MethodKind, PartialConstStability, Stability, StabilityLevel,
StableSince, Target, UnstableReason, VERSION_PLACEHOLDER,
};
use rustc_span::{Ident, Span, Symbol, sym};
use super::prelude::*;
use super::util::parse_version;
use super::{AcceptMapping, AttributeParser, OnDuplicate};
use crate::attributes::NoArgsAttributeParser;
use crate::context::MaybeWarn::Allow;
use crate::context::{AcceptContext, AllowedTargets, FinalizeContext, Stage};
use crate::parser::{ArgParser, MetaItemParser};
use crate::session_diagnostics::{self, UnsupportedLiteralReason};
macro_rules! reject_outside_std {

View File

@ -1,13 +1,5 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::AttributeLintKind;
use rustc_span::{Symbol, sym};
use super::prelude::*;
use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::MaybeWarn::{Allow, Error};
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
pub(crate) struct IgnoreParser;
impl<S: Stage> SingleAttributeParser<S> for IgnoreParser {

View File

@ -1,16 +1,14 @@
use core::mem;
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::{MethodKind, Target};
use rustc_span::{Span, Symbol, sym};
use std::mem;
use super::prelude::*;
use crate::attributes::{
AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
};
use crate::context::MaybeWarn::{Allow, Warn};
use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
use crate::target_checking::Policy::{Allow, Warn};
use crate::target_checking::{ALL_TARGETS, AllowedTargets};
pub(crate) struct SkipDuringMethodDispatchParser;
impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];

View File

@ -1,13 +1,7 @@
use rustc_feature::{AttributeTemplate, template};
use rustc_hir::Target;
use rustc_hir::attrs::AttributeKind;
use rustc_span::hygiene::Transparency;
use rustc_span::{Symbol, sym};
use super::{AttributeOrder, OnDuplicate, SingleAttributeParser};
use crate::context::MaybeWarn::Allow;
use crate::context::{AcceptContext, AllowedTargets, Stage};
use crate::parser::ArgParser;
use super::prelude::*;
pub(crate) struct TransparencyParser;
// FIXME(jdonszelmann): make these proper diagnostics

View File

@ -1,8 +1,12 @@
use rustc_ast::LitKind;
use rustc_ast::attr::{AttributeExt, first_attr_value_str_by_name};
use rustc_feature::is_builtin_attr_name;
use rustc_hir::RustcVersion;
use rustc_span::{Symbol, sym};
use crate::context::{AcceptContext, Stage};
use crate::parser::ArgParser;
/// Parse a rustc version number written inside string literal in an attribute,
/// like appears in `since = "1.0.0"`. Suffixes like "-dev" and "-nightly" are
/// not accepted in this position, unlike when parsing CFG_RELEASE.
@ -56,3 +60,32 @@ pub fn is_doc_alias_attrs_contain_symbol<'tcx, T: AttributeExt + 'tcx>(
}
false
}
/// Parse a single integer.
///
/// Used by attributes that take a single integer as argument, such as
/// `#[link_ordinal]` and `#[rustc_layout_scalar_valid_range_start]`.
/// `cx` is the context given to the attribute.
/// `args` is the parser for the attribute arguments.
pub(crate) fn parse_single_integer<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser<'_>,
) -> Option<u128> {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
return None;
};
let Some(single) = list.single() else {
cx.expected_single_argument(list.span);
return None;
};
let Some(lit) = single.lit() else {
cx.expected_integer_literal(single.span());
return None;
};
let LitKind::Int(num, _ty) = lit.kind else {
cx.expected_integer_literal(single.span());
return None;
};
Some(num.0)
}

View File

@ -3,19 +3,17 @@ use std::collections::BTreeMap;
use std::ops::{Deref, DerefMut};
use std::sync::LazyLock;
use itertools::Itertools;
use private::Sealed;
use rustc_ast::{self as ast, AttrStyle, LitKind, MetaItemLit, NodeId};
use rustc_errors::{DiagCtxtHandle, Diagnostic};
use rustc_feature::{AttributeTemplate, Features};
use rustc_ast::{AttrStyle, MetaItemLit, NodeId};
use rustc_errors::Diagnostic;
use rustc_feature::AttributeTemplate;
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::{
AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, HirId, MethodKind, Target,
};
use rustc_hir::{AttrPath, HirId};
use rustc_session::Session;
use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
use rustc_span::{ErrorGuaranteed, Span, Symbol};
use crate::AttributeParser;
use crate::attributes::allow_unstable::{
AllowConstFnUnstableParser, AllowInternalUnstableParser, UnstableFeatureBoundParser,
};
@ -65,23 +63,21 @@ use crate::attributes::traits::{
};
use crate::attributes::transparency::TransparencyParser;
use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
use crate::context::MaybeWarn::{Allow, Error, Warn};
use crate::parser::{ArgParser, MetaItemParser, PathParser};
use crate::session_diagnostics::{
AttributeParseError, AttributeParseErrorReason, InvalidTarget, UnknownMetaItem,
};
use crate::parser::{ArgParser, PathParser};
use crate::session_diagnostics::{AttributeParseError, AttributeParseErrorReason, UnknownMetaItem};
use crate::target_checking::AllowedTargets;
type GroupType<S> = LazyLock<GroupTypeInner<S>>;
struct GroupTypeInner<S: Stage> {
accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
finalizers: Vec<FinalizeFn<S>>,
pub(super) struct GroupTypeInner<S: Stage> {
pub(super) accepters: BTreeMap<&'static [Symbol], Vec<GroupTypeInnerAccept<S>>>,
pub(super) finalizers: Vec<FinalizeFn<S>>,
}
struct GroupTypeInnerAccept<S: Stage> {
template: AttributeTemplate,
accept_fn: AcceptFn<S>,
allowed_targets: AllowedTargets,
pub(super) struct GroupTypeInnerAccept<S: Stage> {
pub(super) template: AttributeTemplate,
pub(super) accept_fn: AcceptFn<S>,
pub(super) allowed_targets: AllowedTargets,
}
type AcceptFn<S> =
@ -595,7 +591,7 @@ pub struct SharedContext<'p, 'sess, S: Stage> {
/// The id ([`NodeId`] if `S` is `Early`, [`HirId`] if `S` is `Late`) of the syntactical component this attribute was applied to
pub(crate) target_id: S::Id,
emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
pub(crate) emit_lint: &'p mut dyn FnMut(AttributeLint<S::Id>),
}
/// Context given to every attribute parser during finalization.
@ -666,557 +662,3 @@ impl ShouldEmit {
}
}
}
#[derive(Debug)]
pub(crate) enum AllowedTargets {
AllowList(&'static [MaybeWarn]),
AllowListWarnRest(&'static [MaybeWarn]),
}
pub(crate) enum AllowedResult {
Allowed,
Warn,
Error,
}
impl AllowedTargets {
pub(crate) fn is_allowed(&self, target: Target) -> AllowedResult {
match self {
AllowedTargets::AllowList(list) => {
if list.contains(&Allow(target)) {
AllowedResult::Allowed
} else if list.contains(&Warn(target)) {
AllowedResult::Warn
} else {
AllowedResult::Error
}
}
AllowedTargets::AllowListWarnRest(list) => {
if list.contains(&Allow(target)) {
AllowedResult::Allowed
} else if list.contains(&Error(target)) {
AllowedResult::Error
} else {
AllowedResult::Warn
}
}
}
}
pub(crate) fn allowed_targets(&self) -> Vec<Target> {
match self {
AllowedTargets::AllowList(list) => list,
AllowedTargets::AllowListWarnRest(list) => list,
}
.iter()
.filter_map(|target| match target {
Allow(target) => Some(*target),
Warn(_) => None,
Error(_) => None,
})
.collect()
}
}
#[derive(Debug, Eq, PartialEq)]
pub(crate) enum MaybeWarn {
Allow(Target),
Warn(Target),
Error(Target),
}
/// Context created once, for example as part of the ast lowering
/// context, through which all attributes can be lowered.
pub struct AttributeParser<'sess, S: Stage = Late> {
pub(crate) tools: Vec<Symbol>,
features: Option<&'sess Features>,
sess: &'sess Session,
stage: S,
/// *Only* parse attributes with this symbol.
///
/// Used in cases where we want the lowering infrastructure for parse just a single attribute.
parse_only: Option<Symbol>,
}
impl<'sess> AttributeParser<'sess, Early> {
/// This method allows you to parse attributes *before* you have access to features or tools.
/// One example where this is necessary, is to parse `feature` attributes themselves for
/// example.
///
/// Try to use this as little as possible. Attributes *should* be lowered during
/// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
/// crash if you tried to do so through [`parse_limited`](Self::parse_limited).
///
/// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with
/// that symbol are picked out of the list of instructions and parsed. Those are returned.
///
/// No diagnostics will be emitted when parsing limited. Lints are not emitted at all, while
/// errors will be emitted as a delayed bugs. in other words, we *expect* attributes parsed
/// with `parse_limited` to be reparsed later during ast lowering where we *do* emit the errors
pub fn parse_limited(
sess: &'sess Session,
attrs: &[ast::Attribute],
sym: Symbol,
target_span: Span,
target_node_id: NodeId,
features: Option<&'sess Features>,
) -> Option<Attribute> {
let mut p = Self {
features,
tools: Vec::new(),
parse_only: Some(sym),
sess,
stage: Early { emit_errors: ShouldEmit::Nothing },
};
let mut parsed = p.parse_attribute_list(
attrs,
target_span,
target_node_id,
Target::Crate, // Does not matter, we're not going to emit errors anyways
OmitDoc::Skip,
std::convert::identity,
|_lint| {
panic!("can't emit lints here for now (nothing uses this atm)");
},
);
assert!(parsed.len() <= 1);
parsed.pop()
}
pub fn parse_single<T>(
sess: &'sess Session,
attr: &ast::Attribute,
target_span: Span,
target_node_id: NodeId,
features: Option<&'sess Features>,
emit_errors: ShouldEmit,
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
template: &AttributeTemplate,
) -> T {
let mut parser = Self {
features,
tools: Vec::new(),
parse_only: None,
sess,
stage: Early { emit_errors },
};
let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
panic!("parse_single called on a doc attr")
};
let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx());
let path = meta_parser.path();
let args = meta_parser.args();
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
shared: SharedContext {
cx: &mut parser,
target_span,
target_id: target_node_id,
emit_lint: &mut |_lint| {
panic!("can't emit lints here for now (nothing uses this atm)");
},
},
attr_span: attr.span,
attr_style: attr.style,
template,
attr_path: path.get_attribute_path(),
};
parse_fn(&mut cx, args)
}
}
impl<'sess, S: Stage> AttributeParser<'sess, S> {
pub fn new(
sess: &'sess Session,
features: &'sess Features,
tools: Vec<Symbol>,
stage: S,
) -> Self {
Self { features: Some(features), tools, parse_only: None, sess, stage }
}
pub(crate) fn sess(&self) -> &'sess Session {
&self.sess
}
pub(crate) fn features(&self) -> &'sess Features {
self.features.expect("features not available at this point in the compiler")
}
pub(crate) fn features_option(&self) -> Option<&'sess Features> {
self.features
}
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
self.sess().dcx()
}
/// Parse a list of attributes.
///
/// `target_span` is the span of the thing this list of attributes is applied to,
/// and when `omit_doc` is set, doc attributes are filtered out.
pub fn parse_attribute_list(
&mut self,
attrs: &[ast::Attribute],
target_span: Span,
target_id: S::Id,
target: Target,
omit_doc: OmitDoc,
lower_span: impl Copy + Fn(Span) -> Span,
mut emit_lint: impl FnMut(AttributeLint<S::Id>),
) -> Vec<Attribute> {
let mut attributes = Vec::new();
let mut attr_paths = Vec::new();
for attr in attrs {
// If we're only looking for a single attribute, skip all the ones we don't care about.
if let Some(expected) = self.parse_only {
if !attr.has_name(expected) {
continue;
}
}
// Sometimes, for example for `#![doc = include_str!("readme.md")]`,
// doc still contains a non-literal. You might say, when we're lowering attributes
// that's expanded right? But no, sometimes, when parsing attributes on macros,
// we already use the lowering logic and these are still there. So, when `omit_doc`
// is set we *also* want to ignore these.
if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
continue;
}
match &attr.kind {
ast::AttrKind::DocComment(comment_kind, symbol) => {
if omit_doc == OmitDoc::Skip {
continue;
}
attributes.push(Attribute::Parsed(AttributeKind::DocComment {
style: attr.style,
kind: *comment_kind,
span: lower_span(attr.span),
comment: *symbol,
}))
}
// // FIXME: make doc attributes go through a proper attribute parser
// ast::AttrKind::Normal(n) if n.has_name(sym::doc) => {
// let p = GenericMetaItemParser::from_attr(&n, self.dcx());
//
// attributes.push(Attribute::Parsed(AttributeKind::DocComment {
// style: attr.style,
// kind: CommentKind::Line,
// span: attr.span,
// comment: p.args().name_value(),
// }))
// }
ast::AttrKind::Normal(n) => {
attr_paths.push(PathParser::Ast(&n.item.path));
let parser = MetaItemParser::from_attr(n, self.dcx());
let path = parser.path();
let args = parser.args();
let parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
if let Some(accepts) = S::parsers().accepters.get(parts.as_slice()) {
for accept in accepts {
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
shared: SharedContext {
cx: self,
target_span,
target_id,
emit_lint: &mut emit_lint,
},
attr_span: lower_span(attr.span),
attr_style: attr.style,
template: &accept.template,
attr_path: path.get_attribute_path(),
};
(accept.accept_fn)(&mut cx, args);
if self.stage.should_emit().should_emit() {
match accept.allowed_targets.is_allowed(target) {
AllowedResult::Allowed => {}
AllowedResult::Warn => {
let allowed_targets =
accept.allowed_targets.allowed_targets();
let (applied, only) = allowed_targets_applied(
allowed_targets,
target,
self.features,
);
emit_lint(AttributeLint {
id: target_id,
span: attr.span,
kind: AttributeLintKind::InvalidTarget {
name: parts[0],
target,
only: if only { "only " } else { "" },
applied,
},
});
}
AllowedResult::Error => {
let allowed_targets =
accept.allowed_targets.allowed_targets();
let (applied, only) = allowed_targets_applied(
allowed_targets,
target,
self.features,
);
self.dcx().emit_err(InvalidTarget {
span: attr.span,
name: parts[0],
target: target.plural_name(),
only: if only { "only " } else { "" },
applied,
});
}
}
}
}
} else {
// If we're here, we must be compiling a tool attribute... Or someone
// forgot to parse their fancy new attribute. Let's warn them in any case.
// If you are that person, and you really think your attribute should
// remain unparsed, carefully read the documentation in this module and if
// you still think so you can add an exception to this assertion.
// FIXME(jdonszelmann): convert other attributes, and check with this that
// we caught em all
// const FIXME_TEMPORARY_ATTR_ALLOWLIST: &[Symbol] = &[sym::cfg];
// assert!(
// self.tools.contains(&parts[0]) || true,
// // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
// "attribute {path} wasn't parsed and isn't a know tool attribute",
// );
attributes.push(Attribute::Unparsed(Box::new(AttrItem {
path: AttrPath::from_ast(&n.item.path),
args: self.lower_attr_args(&n.item.args, lower_span),
id: HashIgnoredAttrId { attr_id: attr.id },
style: attr.style,
span: lower_span(attr.span),
})));
}
}
}
}
let mut parsed_attributes = Vec::new();
for f in &S::parsers().finalizers {
if let Some(attr) = f(&mut FinalizeContext {
shared: SharedContext {
cx: self,
target_span,
target_id,
emit_lint: &mut emit_lint,
},
all_attrs: &attr_paths,
}) {
parsed_attributes.push(Attribute::Parsed(attr));
}
}
attributes.extend(parsed_attributes);
attributes
}
/// Returns whether there is a parser for an attribute with this name
pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
Late::parsers().accepters.contains_key(path)
}
fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
match args {
ast::AttrArgs::Empty => AttrArgs::Empty,
ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
// This is an inert key-value attribute - it will never be visible to macros
// after it gets lowered to HIR. Therefore, we can extract literals to handle
// nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
ast::AttrArgs::Eq { eq_span, expr } => {
// In valid code the value always ends up as a single literal. Otherwise, a dummy
// literal suffices because the error is handled elsewhere.
let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
&& let Ok(lit) =
ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
{
lit
} else {
let guar = self.dcx().span_delayed_bug(
args.span().unwrap_or(DUMMY_SP),
"expr in place where literal is expected (builtin attr parsing)",
);
ast::MetaItemLit {
symbol: sym::dummy,
suffix: None,
kind: ast::LitKind::Err(guar),
span: DUMMY_SP,
}
};
AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
}
}
}
}
/// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
/// Does some heuristic-based filtering to remove uninteresting targets, and formats the targets into a string
pub(crate) fn allowed_targets_applied(
mut allowed_targets: Vec<Target>,
target: Target,
features: Option<&Features>,
) -> (String, bool) {
// Remove unstable targets from `allowed_targets` if their features are not enabled
if let Some(features) = features {
if !features.fn_delegation() {
allowed_targets.retain(|t| !matches!(t, Target::Delegation { .. }));
}
if !features.stmt_expr_attributes() {
allowed_targets.retain(|t| !matches!(t, Target::Expression | Target::Statement));
}
if !features.extern_types() {
allowed_targets.retain(|t| !matches!(t, Target::ForeignTy));
}
}
// We define groups of "similar" targets.
// If at least two of the targets are allowed, and the `target` is not in the group,
// we collapse the entire group to a single entry to simplify the target list
const FUNCTION_LIKE: &[Target] = &[
Target::Fn,
Target::Closure,
Target::ForeignFn,
Target::Method(MethodKind::Inherent),
Target::Method(MethodKind::Trait { body: false }),
Target::Method(MethodKind::Trait { body: true }),
Target::Method(MethodKind::TraitImpl),
];
const METHOD_LIKE: &[Target] = &[
Target::Method(MethodKind::Inherent),
Target::Method(MethodKind::Trait { body: false }),
Target::Method(MethodKind::Trait { body: true }),
Target::Method(MethodKind::TraitImpl),
];
const IMPL_LIKE: &[Target] =
&[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }];
const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum];
let mut added_fake_targets = Vec::new();
filter_targets(
&mut allowed_targets,
FUNCTION_LIKE,
"functions",
target,
&mut added_fake_targets,
);
filter_targets(&mut allowed_targets, METHOD_LIKE, "methods", target, &mut added_fake_targets);
filter_targets(&mut allowed_targets, IMPL_LIKE, "impl blocks", target, &mut added_fake_targets);
filter_targets(&mut allowed_targets, ADT_LIKE, "data types", target, &mut added_fake_targets);
// If there is now only 1 target left, show that as the only possible target
(
added_fake_targets
.iter()
.copied()
.chain(allowed_targets.iter().map(|t| t.plural_name()))
.join(", "),
allowed_targets.len() + added_fake_targets.len() == 1,
)
}
fn filter_targets(
allowed_targets: &mut Vec<Target>,
target_group: &'static [Target],
target_group_name: &'static str,
target: Target,
added_fake_targets: &mut Vec<&'static str>,
) {
if target_group.contains(&target) {
return;
}
if allowed_targets.iter().filter(|at| target_group.contains(at)).count() < 2 {
return;
}
allowed_targets.retain(|t| !target_group.contains(t));
added_fake_targets.push(target_group_name);
}
/// This is the list of all targets to which a attribute can be applied
/// This is used for:
/// - `rustc_dummy`, which can be applied to all targets
/// - Attributes that are not parted to the new target system yet can use this list as a placeholder
pub(crate) const ALL_TARGETS: &'static [MaybeWarn] = &[
Allow(Target::ExternCrate),
Allow(Target::Use),
Allow(Target::Static),
Allow(Target::Const),
Allow(Target::Fn),
Allow(Target::Closure),
Allow(Target::Mod),
Allow(Target::ForeignMod),
Allow(Target::GlobalAsm),
Allow(Target::TyAlias),
Allow(Target::Enum),
Allow(Target::Variant),
Allow(Target::Struct),
Allow(Target::Field),
Allow(Target::Union),
Allow(Target::Trait),
Allow(Target::TraitAlias),
Allow(Target::Impl { of_trait: false }),
Allow(Target::Impl { of_trait: true }),
Allow(Target::Expression),
Allow(Target::Statement),
Allow(Target::Arm),
Allow(Target::AssocConst),
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: false })),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
Allow(Target::AssocTy),
Allow(Target::ForeignFn),
Allow(Target::ForeignStatic),
Allow(Target::ForeignTy),
Allow(Target::MacroDef),
Allow(Target::Param),
Allow(Target::PatField),
Allow(Target::ExprField),
Allow(Target::WherePredicate),
Allow(Target::MacroCall),
Allow(Target::Crate),
Allow(Target::Delegation { mac: false }),
Allow(Target::Delegation { mac: true }),
];
/// Parse a single integer.
///
/// Used by attributes that take a single integer as argument, such as
/// `#[link_ordinal]` and `#[rustc_layout_scalar_valid_range_start]`.
/// `cx` is the context given to the attribute.
/// `args` is the parser for the attribute arguments.
pub(crate) fn parse_single_integer<S: Stage>(
cx: &mut AcceptContext<'_, '_, S>,
args: &ArgParser<'_>,
) -> Option<u128> {
let Some(list) = args.list() else {
cx.expected_list(cx.attr_span);
return None;
};
let Some(single) = list.single() else {
cx.expected_single_argument(list.span);
return None;
};
let Some(lit) = single.lit() else {
cx.expected_integer_literal(single.span());
return None;
};
let LitKind::Int(num, _ty) = lit.kind else {
cx.expected_integer_literal(single.span());
return None;
};
Some(num.0)
}

View File

@ -0,0 +1,321 @@
use rustc_ast as ast;
use rustc_ast::NodeId;
use rustc_errors::DiagCtxtHandle;
use rustc_feature::{AttributeTemplate, Features};
use rustc_hir::attrs::AttributeKind;
use rustc_hir::lints::AttributeLint;
use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId, Target};
use rustc_session::Session;
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
use crate::context::{AcceptContext, FinalizeContext, SharedContext, Stage};
use crate::parser::{ArgParser, MetaItemParser, PathParser};
use crate::{Early, Late, OmitDoc, ShouldEmit};
/// Context created once, for example as part of the ast lowering
/// context, through which all attributes can be lowered.
pub struct AttributeParser<'sess, S: Stage = Late> {
pub(crate) tools: Vec<Symbol>,
pub(crate) features: Option<&'sess Features>,
pub(crate) sess: &'sess Session,
pub(crate) stage: S,
/// *Only* parse attributes with this symbol.
///
/// Used in cases where we want the lowering infrastructure for parse just a single attribute.
parse_only: Option<Symbol>,
}
impl<'sess> AttributeParser<'sess, Early> {
/// This method allows you to parse attributes *before* you have access to features or tools.
/// One example where this is necessary, is to parse `feature` attributes themselves for
/// example.
///
/// Try to use this as little as possible. Attributes *should* be lowered during
/// `rustc_ast_lowering`. Some attributes require access to features to parse, which would
/// crash if you tried to do so through [`parse_limited`](Self::parse_limited).
///
/// To make sure use is limited, supply a `Symbol` you'd like to parse. Only attributes with
/// that symbol are picked out of the list of instructions and parsed. Those are returned.
///
/// No diagnostics will be emitted when parsing limited. Lints are not emitted at all, while
/// errors will be emitted as a delayed bugs. in other words, we *expect* attributes parsed
/// with `parse_limited` to be reparsed later during ast lowering where we *do* emit the errors
pub fn parse_limited(
sess: &'sess Session,
attrs: &[ast::Attribute],
sym: Symbol,
target_span: Span,
target_node_id: NodeId,
features: Option<&'sess Features>,
) -> Option<Attribute> {
let mut p = Self {
features,
tools: Vec::new(),
parse_only: Some(sym),
sess,
stage: Early { emit_errors: ShouldEmit::Nothing },
};
let mut parsed = p.parse_attribute_list(
attrs,
target_span,
target_node_id,
Target::Crate, // Does not matter, we're not going to emit errors anyways
OmitDoc::Skip,
std::convert::identity,
|_lint| {
panic!("can't emit lints here for now (nothing uses this atm)");
},
);
assert!(parsed.len() <= 1);
parsed.pop()
}
pub fn parse_single<T>(
sess: &'sess Session,
attr: &ast::Attribute,
target_span: Span,
target_node_id: NodeId,
features: Option<&'sess Features>,
emit_errors: ShouldEmit,
parse_fn: fn(cx: &mut AcceptContext<'_, '_, Early>, item: &ArgParser<'_>) -> T,
template: &AttributeTemplate,
) -> T {
let mut parser = Self {
features,
tools: Vec::new(),
parse_only: None,
sess,
stage: Early { emit_errors },
};
let ast::AttrKind::Normal(normal_attr) = &attr.kind else {
panic!("parse_single called on a doc attr")
};
let meta_parser = MetaItemParser::from_attr(normal_attr, parser.dcx());
let path = meta_parser.path();
let args = meta_parser.args();
let mut cx: AcceptContext<'_, 'sess, Early> = AcceptContext {
shared: SharedContext {
cx: &mut parser,
target_span,
target_id: target_node_id,
emit_lint: &mut |_lint| {
panic!("can't emit lints here for now (nothing uses this atm)");
},
},
attr_span: attr.span,
attr_style: attr.style,
template,
attr_path: path.get_attribute_path(),
};
parse_fn(&mut cx, args)
}
}
impl<'sess, S: Stage> AttributeParser<'sess, S> {
pub fn new(
sess: &'sess Session,
features: &'sess Features,
tools: Vec<Symbol>,
stage: S,
) -> Self {
Self { features: Some(features), tools, parse_only: None, sess, stage }
}
pub(crate) fn sess(&self) -> &'sess Session {
&self.sess
}
pub(crate) fn features(&self) -> &'sess Features {
self.features.expect("features not available at this point in the compiler")
}
pub(crate) fn features_option(&self) -> Option<&'sess Features> {
self.features
}
pub(crate) fn dcx(&self) -> DiagCtxtHandle<'sess> {
self.sess().dcx()
}
/// Parse a list of attributes.
///
/// `target_span` is the span of the thing this list of attributes is applied to,
/// and when `omit_doc` is set, doc attributes are filtered out.
pub fn parse_attribute_list(
&mut self,
attrs: &[ast::Attribute],
target_span: Span,
target_id: S::Id,
target: Target,
omit_doc: OmitDoc,
lower_span: impl Copy + Fn(Span) -> Span,
mut emit_lint: impl FnMut(AttributeLint<S::Id>),
) -> Vec<Attribute> {
let mut attributes = Vec::new();
let mut attr_paths = Vec::new();
for attr in attrs {
// If we're only looking for a single attribute, skip all the ones we don't care about.
if let Some(expected) = self.parse_only {
if !attr.has_name(expected) {
continue;
}
}
// Sometimes, for example for `#![doc = include_str!("readme.md")]`,
// doc still contains a non-literal. You might say, when we're lowering attributes
// that's expanded right? But no, sometimes, when parsing attributes on macros,
// we already use the lowering logic and these are still there. So, when `omit_doc`
// is set we *also* want to ignore these.
if omit_doc == OmitDoc::Skip && attr.has_name(sym::doc) {
continue;
}
match &attr.kind {
ast::AttrKind::DocComment(comment_kind, symbol) => {
if omit_doc == OmitDoc::Skip {
continue;
}
attributes.push(Attribute::Parsed(AttributeKind::DocComment {
style: attr.style,
kind: *comment_kind,
span: lower_span(attr.span),
comment: *symbol,
}))
}
// // FIXME: make doc attributes go through a proper attribute parser
// ast::AttrKind::Normal(n) if n.has_name(sym::doc) => {
// let p = GenericMetaItemParser::from_attr(&n, self.dcx());
//
// attributes.push(Attribute::Parsed(AttributeKind::DocComment {
// style: attr.style,
// kind: CommentKind::Line,
// span: attr.span,
// comment: p.args().name_value(),
// }))
// }
ast::AttrKind::Normal(n) => {
attr_paths.push(PathParser::Ast(&n.item.path));
let parser = MetaItemParser::from_attr(n, self.dcx());
let path = parser.path();
let args = parser.args();
let path_parts = path.segments().map(|i| i.name).collect::<Vec<_>>();
if let Some(accepts) = S::parsers().accepters.get(path_parts.as_slice()) {
for accept in accepts {
let mut cx: AcceptContext<'_, 'sess, S> = AcceptContext {
shared: SharedContext {
cx: self,
target_span,
target_id,
emit_lint: &mut emit_lint,
},
attr_span: lower_span(attr.span),
attr_style: attr.style,
template: &accept.template,
attr_path: path.get_attribute_path(),
};
(accept.accept_fn)(&mut cx, args);
if self.stage.should_emit().should_emit() {
self.check_target(
path.get_attribute_path(),
attr.span,
&accept.allowed_targets,
target,
target_id,
&mut emit_lint,
);
}
}
} else {
// If we're here, we must be compiling a tool attribute... Or someone
// forgot to parse their fancy new attribute. Let's warn them in any case.
// If you are that person, and you really think your attribute should
// remain unparsed, carefully read the documentation in this module and if
// you still think so you can add an exception to this assertion.
// FIXME(jdonszelmann): convert other attributes, and check with this that
// we caught em all
// const FIXME_TEMPORARY_ATTR_ALLOWLIST: &[Symbol] = &[sym::cfg];
// assert!(
// self.tools.contains(&parts[0]) || true,
// // || FIXME_TEMPORARY_ATTR_ALLOWLIST.contains(&parts[0]),
// "attribute {path} wasn't parsed and isn't a know tool attribute",
// );
attributes.push(Attribute::Unparsed(Box::new(AttrItem {
path: AttrPath::from_ast(&n.item.path),
args: self.lower_attr_args(&n.item.args, lower_span),
id: HashIgnoredAttrId { attr_id: attr.id },
style: attr.style,
span: lower_span(attr.span),
})));
}
}
}
}
let mut parsed_attributes = Vec::new();
for f in &S::parsers().finalizers {
if let Some(attr) = f(&mut FinalizeContext {
shared: SharedContext {
cx: self,
target_span,
target_id,
emit_lint: &mut emit_lint,
},
all_attrs: &attr_paths,
}) {
parsed_attributes.push(Attribute::Parsed(attr));
}
}
attributes.extend(parsed_attributes);
attributes
}
/// Returns whether there is a parser for an attribute with this name
pub fn is_parsed_attribute(path: &[Symbol]) -> bool {
Late::parsers().accepters.contains_key(path)
}
fn lower_attr_args(&self, args: &ast::AttrArgs, lower_span: impl Fn(Span) -> Span) -> AttrArgs {
match args {
ast::AttrArgs::Empty => AttrArgs::Empty,
ast::AttrArgs::Delimited(args) => AttrArgs::Delimited(args.clone()),
// This is an inert key-value attribute - it will never be visible to macros
// after it gets lowered to HIR. Therefore, we can extract literals to handle
// nonterminals in `#[doc]` (e.g. `#[doc = $e]`).
ast::AttrArgs::Eq { eq_span, expr } => {
// In valid code the value always ends up as a single literal. Otherwise, a dummy
// literal suffices because the error is handled elsewhere.
let lit = if let ast::ExprKind::Lit(token_lit) = expr.kind
&& let Ok(lit) =
ast::MetaItemLit::from_token_lit(token_lit, lower_span(expr.span))
{
lit
} else {
let guar = self.dcx().span_delayed_bug(
args.span().unwrap_or(DUMMY_SP),
"expr in place where literal is expected (builtin attr parsing)",
);
ast::MetaItemLit {
symbol: sym::dummy,
suffix: None,
kind: ast::LitKind::Err(guar),
span: DUMMY_SP,
}
};
AttrArgs::Eq { eq_span: lower_span(*eq_span), expr: lit }
}
}
}
}

View File

@ -84,18 +84,32 @@
// tidy-alphabetical-end
#[macro_use]
/// All the individual attribute parsers for each of rustc's built-in attributes.
mod attributes;
/// All the important types given to attribute parsers when parsing
pub(crate) mod context;
mod lints;
/// Code that other crates interact with, to actually parse a list (or sometimes single)
/// attribute.
mod interface;
/// Despite this entire module called attribute parsing and the term being a little overloaded,
/// in this module the code lives that actually breaks up tokenstreams into semantic pieces of attributes,
/// like lists or name-value pairs.
pub mod parser;
mod lints;
mod session_diagnostics;
mod target_checking;
pub use attributes::cfg::{CFG_TEMPLATE, EvalConfigResult, eval_config_entry, parse_cfg_attr};
pub use attributes::cfg_old::*;
pub use attributes::util::{
find_crate_name, is_builtin_attr, is_doc_alias_attrs_contain_symbol, parse_version,
};
pub use context::{AttributeParser, Early, Late, OmitDoc, ShouldEmit};
pub use context::{Early, Late, OmitDoc, ShouldEmit};
pub use interface::AttributeParser;
pub use lints::emit_attribute_lint;
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }

View File

@ -1,3 +1,5 @@
use std::borrow::Cow;
use rustc_errors::{DiagArgValue, LintEmitter};
use rustc_hir::lints::{AttributeLint, AttributeLintKind};
use rustc_hir::{HirId, Target};
@ -35,12 +37,12 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
*first_span,
session_diagnostics::EmptyAttributeList { attr_span: *first_span },
),
&AttributeLintKind::InvalidTarget { name, target, ref applied, only } => lint_emitter
AttributeLintKind::InvalidTarget { name, target, applied, only } => lint_emitter
.emit_node_span_lint(
// This check is here because `deprecated` had its own lint group and removing this would be a breaking change
if name == sym::deprecated
if name.segments[0].name == sym::deprecated
&& ![Target::Closure, Target::Expression, Target::Statement, Target::Arm]
.contains(&target)
.contains(target)
{
rustc_session::lint::builtin::USELESS_DEPRECATED
} else {
@ -51,7 +53,9 @@ pub fn emit_attribute_lint<L: LintEmitter>(lint: &AttributeLint<HirId>, lint_emi
session_diagnostics::InvalidTargetLint {
name,
target: target.plural_name(),
applied: applied.clone(),
applied: DiagArgValue::StrListSepByAnd(
applied.into_iter().map(|i| Cow::Owned(i.to_string())).collect(),
),
only,
attr_span: *span,
},

View File

@ -484,10 +484,10 @@ pub(crate) struct EmptyAttributeList {
#[diag(attr_parsing_invalid_target_lint)]
#[warning]
#[help]
pub(crate) struct InvalidTargetLint {
pub name: Symbol,
pub target: &'static str,
pub applied: String,
pub(crate) struct InvalidTargetLint<'a> {
pub name: &'a AttrPath,
pub target: &'a str,
pub applied: DiagArgValue,
pub only: &'static str,
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
pub attr_span: Span,
@ -500,9 +500,9 @@ pub(crate) struct InvalidTarget {
#[primary_span]
#[suggestion(code = "", applicability = "machine-applicable", style = "tool-only")]
pub span: Span,
pub name: Symbol,
pub name: AttrPath,
pub target: &'static str,
pub applied: String,
pub applied: DiagArgValue,
pub only: &'static str,
}

View File

@ -0,0 +1,247 @@
use std::borrow::Cow;
use rustc_errors::DiagArgValue;
use rustc_feature::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::session_diagnostics::InvalidTarget;
#[derive(Debug)]
pub(crate) enum AllowedTargets {
AllowList(&'static [Policy]),
AllowListWarnRest(&'static [Policy]),
}
pub(crate) enum AllowedResult {
Allowed,
Warn,
Error,
}
impl AllowedTargets {
pub(crate) fn is_allowed(&self, target: Target) -> AllowedResult {
match self {
AllowedTargets::AllowList(list) => {
if list.contains(&Policy::Allow(target)) {
AllowedResult::Allowed
} else if list.contains(&Policy::Warn(target)) {
AllowedResult::Warn
} else {
AllowedResult::Error
}
}
AllowedTargets::AllowListWarnRest(list) => {
if list.contains(&Policy::Allow(target)) {
AllowedResult::Allowed
} else if list.contains(&Policy::Error(target)) {
AllowedResult::Error
} else {
AllowedResult::Warn
}
}
}
}
pub(crate) fn allowed_targets(&self) -> Vec<Target> {
match self {
AllowedTargets::AllowList(list) => list,
AllowedTargets::AllowListWarnRest(list) => list,
}
.iter()
.filter_map(|target| match target {
Policy::Allow(target) => Some(*target),
Policy::Warn(_) => None,
Policy::Error(_) => None,
})
.collect()
}
}
#[derive(Debug, Eq, PartialEq)]
pub(crate) enum Policy {
Allow(Target),
Warn(Target),
Error(Target),
}
impl<S: Stage> AttributeParser<'_, S> {
pub(crate) fn check_target(
&self,
attr_name: AttrPath,
attr_span: Span,
allowed_targets: &AllowedTargets,
target: Target,
target_id: S::Id,
mut emit_lint: impl FnMut(AttributeLint<S::Id>),
) {
match allowed_targets.is_allowed(target) {
AllowedResult::Allowed => {}
AllowedResult::Warn => {
let allowed_targets = allowed_targets.allowed_targets();
let (applied, only) =
allowed_targets_applied(allowed_targets, target, self.features);
emit_lint(AttributeLint {
id: target_id,
span: attr_span,
kind: AttributeLintKind::InvalidTarget {
name: attr_name,
target,
only: if only { "only " } else { "" },
applied,
},
});
}
AllowedResult::Error => {
let allowed_targets = allowed_targets.allowed_targets();
let (applied, only) =
allowed_targets_applied(allowed_targets, target, self.features);
self.dcx().emit_err(InvalidTarget {
span: attr_span,
name: attr_name,
target: target.plural_name(),
only: if only { "only " } else { "" },
applied: DiagArgValue::StrListSepByAnd(
applied.into_iter().map(Cow::Owned).collect(),
),
});
}
}
}
}
/// Takes a list of `allowed_targets` for an attribute, and the `target` the attribute was applied to.
/// Does some heuristic-based filtering to remove uninteresting targets, and formats the targets into a string
pub(crate) fn allowed_targets_applied(
mut allowed_targets: Vec<Target>,
target: Target,
features: Option<&Features>,
) -> (Vec<String>, bool) {
// Remove unstable targets from `allowed_targets` if their features are not enabled
if let Some(features) = features {
if !features.fn_delegation() {
allowed_targets.retain(|t| !matches!(t, Target::Delegation { .. }));
}
if !features.stmt_expr_attributes() {
allowed_targets.retain(|t| !matches!(t, Target::Expression | Target::Statement));
}
if !features.extern_types() {
allowed_targets.retain(|t| !matches!(t, Target::ForeignTy));
}
}
// We define groups of "similar" targets.
// If at least two of the targets are allowed, and the `target` is not in the group,
// we collapse the entire group to a single entry to simplify the target list
const FUNCTION_LIKE: &[Target] = &[
Target::Fn,
Target::Closure,
Target::ForeignFn,
Target::Method(MethodKind::Inherent),
Target::Method(MethodKind::Trait { body: false }),
Target::Method(MethodKind::Trait { body: true }),
Target::Method(MethodKind::TraitImpl),
];
const METHOD_LIKE: &[Target] = &[
Target::Method(MethodKind::Inherent),
Target::Method(MethodKind::Trait { body: false }),
Target::Method(MethodKind::Trait { body: true }),
Target::Method(MethodKind::TraitImpl),
];
const IMPL_LIKE: &[Target] =
&[Target::Impl { of_trait: false }, Target::Impl { of_trait: true }];
const ADT_LIKE: &[Target] = &[Target::Struct, Target::Enum];
let mut added_fake_targets = Vec::new();
filter_targets(
&mut allowed_targets,
FUNCTION_LIKE,
"functions",
target,
&mut added_fake_targets,
);
filter_targets(&mut allowed_targets, METHOD_LIKE, "methods", target, &mut added_fake_targets);
filter_targets(&mut allowed_targets, IMPL_LIKE, "impl blocks", target, &mut added_fake_targets);
filter_targets(&mut allowed_targets, ADT_LIKE, "data types", target, &mut added_fake_targets);
// If there is now only 1 target left, show that as the only possible target
(
added_fake_targets
.iter()
.copied()
.chain(allowed_targets.iter().map(|t| t.plural_name()))
.map(|i| i.to_string())
.collect(),
allowed_targets.len() + added_fake_targets.len() == 1,
)
}
fn filter_targets(
allowed_targets: &mut Vec<Target>,
target_group: &'static [Target],
target_group_name: &'static str,
target: Target,
added_fake_targets: &mut Vec<&'static str>,
) {
if target_group.contains(&target) {
return;
}
if allowed_targets.iter().filter(|at| target_group.contains(at)).count() < 2 {
return;
}
allowed_targets.retain(|t| !target_group.contains(t));
added_fake_targets.push(target_group_name);
}
/// This is the list of all targets to which a attribute can be applied
/// This is used for:
/// - `rustc_dummy`, which can be applied to all targets
/// - Attributes that are not parted to the new target system yet can use this list as a placeholder
pub(crate) const ALL_TARGETS: &'static [Policy] = {
use Policy::Allow;
&[
Allow(Target::ExternCrate),
Allow(Target::Use),
Allow(Target::Static),
Allow(Target::Const),
Allow(Target::Fn),
Allow(Target::Closure),
Allow(Target::Mod),
Allow(Target::ForeignMod),
Allow(Target::GlobalAsm),
Allow(Target::TyAlias),
Allow(Target::Enum),
Allow(Target::Variant),
Allow(Target::Struct),
Allow(Target::Field),
Allow(Target::Union),
Allow(Target::Trait),
Allow(Target::TraitAlias),
Allow(Target::Impl { of_trait: false }),
Allow(Target::Impl { of_trait: true }),
Allow(Target::Expression),
Allow(Target::Statement),
Allow(Target::Arm),
Allow(Target::AssocConst),
Allow(Target::Method(MethodKind::Inherent)),
Allow(Target::Method(MethodKind::Trait { body: false })),
Allow(Target::Method(MethodKind::Trait { body: true })),
Allow(Target::Method(MethodKind::TraitImpl)),
Allow(Target::AssocTy),
Allow(Target::ForeignFn),
Allow(Target::ForeignStatic),
Allow(Target::ForeignTy),
Allow(Target::MacroDef),
Allow(Target::Param),
Allow(Target::PatField),
Allow(Target::ExprField),
Allow(Target::WherePredicate),
Allow(Target::MacroCall),
Allow(Target::Crate),
Allow(Target::Delegation { mac: false }),
Allow(Target::Delegation { mac: true }),
]
};

View File

@ -330,7 +330,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> {
_ => bug!(),
};
let ptr = args[0].immediate();
let locality = fn_args.const_at(1).to_value().valtree.unwrap_leaf().to_u32() as i32;
let locality = fn_args.const_at(1).to_value().valtree.unwrap_leaf().to_i32();
self.call_intrinsic(
"llvm.prefetch",
&[self.val_ty(ptr)],

View File

@ -164,12 +164,12 @@ impl<'tcx> Printer<'tcx> for TypeNamePrinter<'tcx> {
}
impl<'tcx> PrettyPrinter<'tcx> for TypeNamePrinter<'tcx> {
fn should_print_optional_region(&self, _region: ty::Region<'_>) -> bool {
fn should_print_optional_region(&self, region: ty::Region<'_>) -> bool {
// Bound regions are always printed (as `'_`), which gives some idea that they are special,
// even though the `for` is omitted by the pretty printer.
// E.g. `for<'a, 'b> fn(&'a u32, &'b u32)` is printed as "fn(&'_ u32, &'_ u32)".
match _region.kind() {
ty::ReErased => false,
match region.kind() {
ty::ReErased | ty::ReEarlyParam(_) => false,
ty::ReBound(..) => true,
_ => unreachable!(),
}

View File

@ -1161,6 +1161,12 @@ pub struct AttrPath {
pub span: Span,
}
impl IntoDiagArg for AttrPath {
fn into_diag_arg(self, path: &mut Option<std::path::PathBuf>) -> DiagArgValue {
self.to_string().into_diag_arg(path)
}
}
impl AttrPath {
pub fn from_ast(path: &ast::Path) -> Self {
AttrPath {

View File

@ -1,8 +1,8 @@
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_macros::HashStable_Generic;
use rustc_span::{Span, Symbol};
use rustc_span::Span;
use crate::{HirId, Target};
use crate::{AttrPath, HirId, Target};
#[derive(Debug)]
pub struct DelayedLints {
@ -34,5 +34,5 @@ pub enum AttributeLintKind {
UnusedDuplicate { this: Span, other: Span, warning: bool },
IllFormedAttributeInput { suggestions: Vec<String> },
EmptyAttribute { first_span: Span },
InvalidTarget { name: Symbol, target: Target, applied: String, only: &'static str },
InvalidTarget { name: AttrPath, target: Target, applied: Vec<String>, only: &'static str },
}

View File

@ -4,7 +4,7 @@
use rustc_hir::def::Res;
use rustc_hir::def_id::DefId;
use rustc_hir::{Expr, ExprKind, HirId};
use rustc_middle::ty::{self, ClauseKind, GenericArgsRef, PredicatePolarity, TraitPredicate, Ty};
use rustc_middle::ty::{self, GenericArgsRef, PredicatePolarity, Ty};
use rustc_session::{declare_lint_pass, declare_tool_lint};
use rustc_span::hygiene::{ExpnKind, MacroKind};
use rustc_span::{Span, sym};
@ -129,18 +129,23 @@ fn has_unstable_into_iter_predicate<'tcx>(
};
let predicates = cx.tcx.predicates_of(callee_def_id).instantiate(cx.tcx, generic_args);
for (predicate, _) in predicates {
let ClauseKind::Trait(TraitPredicate { trait_ref, polarity: PredicatePolarity::Positive }) =
predicate.kind().skip_binder()
else {
let Some(trait_pred) = predicate.as_trait_clause() else {
continue;
};
// Does the function or method require any of its arguments to implement `IntoIterator`?
if trait_ref.def_id != into_iterator_def_id {
if trait_pred.def_id() != into_iterator_def_id
|| trait_pred.polarity() != PredicatePolarity::Positive
{
continue;
}
let Ok(Some(instance)) =
ty::Instance::try_resolve(cx.tcx, cx.typing_env(), into_iter_fn_def_id, trait_ref.args)
else {
// `IntoIterator::into_iter` has no additional method args.
let into_iter_fn_args =
cx.tcx.instantiate_bound_regions_with_erased(trait_pred).trait_ref.args;
let Ok(Some(instance)) = ty::Instance::try_resolve(
cx.tcx,
cx.typing_env(),
into_iter_fn_def_id,
into_iter_fn_args,
) else {
continue;
};
// Does the input type's `IntoIterator` implementation have the

View File

@ -157,6 +157,21 @@ impl CoverageInfoBuilder {
// if there's nothing interesting in it.
Box::new(CoverageInfoHi { num_block_markers, branch_spans })
}
pub(crate) fn as_done(&self) -> Box<CoverageInfoHi> {
let &Self { nots: _, markers: BlockMarkerGen { num_block_markers }, ref branch_info } =
self;
let branch_spans = branch_info
.as_ref()
.map(|branch_info| branch_info.branch_spans.as_slice())
.unwrap_or_default()
.to_owned();
// For simplicity, always return an info struct (without Option), even
// if there's nothing interesting in it.
Box::new(CoverageInfoHi { num_block_markers, branch_spans })
}
}
impl<'tcx> Builder<'_, 'tcx> {

View File

@ -790,6 +790,28 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
builder
}
#[allow(dead_code)]
fn dump_for_debugging(&self) {
let mut body = Body::new(
MirSource::item(self.def_id.to_def_id()),
self.cfg.basic_blocks.clone(),
self.source_scopes.clone(),
self.local_decls.clone(),
self.canonical_user_type_annotations.clone(),
self.arg_count.clone(),
self.var_debug_info.clone(),
self.fn_span.clone(),
self.coroutine.clone(),
None,
);
body.coverage_info_hi = self.coverage_info.as_ref().map(|b| b.as_done());
use rustc_middle::mir::pretty;
let options = pretty::PrettyPrintMirOptions::from_cli(self.tcx);
pretty::write_mir_fn(self.tcx, &body, &mut |_, _| Ok(()), &mut std::io::stdout(), options)
.unwrap();
}
fn finish(self) -> Body<'tcx> {
let mut body = Body::new(
MirSource::item(self.def_id.to_def_id()),

View File

@ -2409,8 +2409,12 @@ impl<'a> Parser<'a> {
let constness = self.parse_closure_constness();
let movability =
if self.eat_keyword(exp!(Static)) { Movability::Static } else { Movability::Movable };
let movability = if self.eat_keyword(exp!(Static)) {
self.psess.gated_spans.gate(sym::coroutines, self.prev_token.span);
Movability::Static
} else {
Movability::Movable
};
let coroutine_kind = if self.token_uninterpolated_span().at_least_rust_2018() {
self.parse_coroutine_kind(Case::Sensitive)

View File

@ -19,7 +19,7 @@ pub(crate) fn target() -> Target {
data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(),
arch: "aarch64".into(),
options: TargetOptions {
features: "+v8a".into(),
features: "+v8a,+neon,+crypto,+crc".into(),
linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes),
linker: Some("rust-lld".into()),
link_script: Some(LINKER_SCRIPT.into()),

View File

@ -154,7 +154,7 @@ pub enum RegionKind<I: Interner> {
/// parameters via `tcx.liberate_late_bound_regions`. They are then treated
/// the same way as `ReEarlyParam` while inside of the function.
///
/// See <https://rustc-dev-guide.rust-lang.org/early-late-bound-params/early-late-bound-summary.html> for
/// See <https://rustc-dev-guide.rust-lang.org/early_late_parameters.html> for
/// more info about early and late bound lifetime parameters.
ReLateParam(I::LateParamRegion),

View File

@ -192,7 +192,6 @@ name = "panic_unwind"
version = "0.0.0"
dependencies = [
"alloc",
"cfg-if",
"libc",
"rustc-std-workspace-core",
"unwind",

View File

@ -34,53 +34,44 @@ where
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
const fn slice_start_index_len_fail(index: usize, len: usize) -> ! {
const_panic!(
"slice start index is out of range for slice",
"range start index {index} out of range for slice of length {len}",
index: usize,
len: usize,
)
}
const fn slice_index_fail(start: usize, end: usize, len: usize) -> ! {
if start > len {
const_panic!(
"slice start index is out of range for slice",
"range start index {start} out of range for slice of length {len}",
start: usize,
len: usize,
)
}
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
const fn slice_end_index_len_fail(index: usize, len: usize) -> ! {
if end > len {
const_panic!(
"slice end index is out of range for slice",
"range end index {end} out of range for slice of length {len}",
end: usize,
len: usize,
)
}
if start > end {
const_panic!(
"slice index start is larger than end",
"slice index starts at {start} but ends at {end}",
start: usize,
end: usize,
)
}
// Only reachable if the range was a `RangeInclusive` or a
// `RangeToInclusive`, with `end == len`.
const_panic!(
"slice end index is out of range for slice",
"range end index {index} out of range for slice of length {len}",
index: usize,
"range end index {end} out of range for slice of length {len}",
end: usize,
len: usize,
)
}
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
const fn slice_index_order_fail(index: usize, end: usize) -> ! {
const_panic!(
"slice index start is larger than end",
"slice index starts at {index} but ends at {end}",
index: usize,
end: usize,
)
}
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
const fn slice_start_index_overflow_fail() -> ! {
panic!("attempted to index slice from after maximum usize");
}
#[cfg_attr(not(feature = "panic_immediate_abort"), inline(never), cold)]
#[cfg_attr(feature = "panic_immediate_abort", inline)]
#[track_caller]
const fn slice_end_index_overflow_fail() -> ! {
panic!("attempted to index slice up to maximum usize");
}
// The UbChecks are great for catching bugs in the unsafe methods, but including
// them in safe indexing is unnecessary and hurts inlining and debug runtime perf.
// Both the safe and unsafe public methods share these helpers,
@ -341,7 +332,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &*get_offset_len_noubcheck(slice, self.start(), self.len()) }
} else {
slice_end_index_len_fail(self.end(), slice.len())
slice_index_fail(self.start(), self.end(), slice.len())
}
}
@ -351,7 +342,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::IndexRange {
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start(), self.len()) }
} else {
slice_end_index_len_fail(self.end(), slice.len())
slice_index_fail(self.start(), self.end(), slice.len())
}
}
}
@ -436,26 +427,27 @@ unsafe impl<T> const SliceIndex<[T]> for ops::Range<usize> {
#[inline(always)]
fn index(self, slice: &[T]) -> &[T] {
// Using checked_sub is a safe way to get `SubUnchecked` in MIR
let Some(new_len) = usize::checked_sub(self.end, self.start) else {
slice_index_order_fail(self.start, self.end)
};
if self.end > slice.len() {
slice_end_index_len_fail(self.end, slice.len());
if let Some(new_len) = usize::checked_sub(self.end, self.start)
&& self.end <= slice.len()
{
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &*get_offset_len_noubcheck(slice, self.start, new_len) }
} else {
slice_index_fail(self.start, self.end, slice.len())
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &*get_offset_len_noubcheck(slice, self.start, new_len) }
}
#[inline]
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
let Some(new_len) = usize::checked_sub(self.end, self.start) else {
slice_index_order_fail(self.start, self.end)
};
if self.end > slice.len() {
slice_end_index_len_fail(self.end, slice.len());
// Using checked_sub is a safe way to get `SubUnchecked` in MIR
if let Some(new_len) = usize::checked_sub(self.end, self.start)
&& self.end <= slice.len()
{
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start, new_len) }
} else {
slice_index_fail(self.start, self.end, slice.len())
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &mut *get_offset_len_mut_noubcheck(slice, self.start, new_len) }
}
}
@ -567,7 +559,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
#[inline]
fn index(self, slice: &[T]) -> &[T] {
if self.start > slice.len() {
slice_start_index_len_fail(self.start, slice.len());
slice_index_fail(self.start, slice.len(), slice.len())
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &*self.get_unchecked(slice) }
@ -576,7 +568,7 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeFrom<usize> {
#[inline]
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
if self.start > slice.len() {
slice_start_index_len_fail(self.start, slice.len());
slice_index_fail(self.start, slice.len(), slice.len())
}
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { &mut *self.get_unchecked_mut(slice) }
@ -690,18 +682,32 @@ unsafe impl<T> const SliceIndex<[T]> for ops::RangeInclusive<usize> {
#[inline]
fn index(self, slice: &[T]) -> &[T] {
if *self.end() == usize::MAX {
slice_end_index_overflow_fail();
let Self { mut start, mut end, exhausted } = self;
let len = slice.len();
if end < len {
end = end + 1;
start = if exhausted { end } else { start };
if let Some(new_len) = usize::checked_sub(end, start) {
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { return &*get_offset_len_noubcheck(slice, start, new_len) }
}
}
self.into_slice_range().index(slice)
slice_index_fail(start, end, slice.len())
}
#[inline]
fn index_mut(self, slice: &mut [T]) -> &mut [T] {
if *self.end() == usize::MAX {
slice_end_index_overflow_fail();
let Self { mut start, mut end, exhausted } = self;
let len = slice.len();
if end < len {
end = end + 1;
start = if exhausted { end } else { start };
if let Some(new_len) = usize::checked_sub(end, start) {
// SAFETY: `self` is checked to be valid and in bounds above.
unsafe { return &mut *get_offset_len_mut_noubcheck(slice, start, new_len) }
}
}
self.into_slice_range().index_mut(slice)
slice_index_fail(start, end, slice.len())
}
}
@ -852,28 +858,26 @@ where
{
let len = bounds.end;
let start = match range.start_bound() {
ops::Bound::Included(&start) => start,
ops::Bound::Excluded(start) => {
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
}
ops::Bound::Unbounded => 0,
};
let end = match range.end_bound() {
ops::Bound::Included(end) => {
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
}
ops::Bound::Included(&end) if end >= len => slice_index_fail(0, end, len),
// Cannot overflow because `end < len` implies `end < usize::MAX`.
ops::Bound::Included(&end) => end + 1,
ops::Bound::Excluded(&end) if end > len => slice_index_fail(0, end, len),
ops::Bound::Excluded(&end) => end,
ops::Bound::Unbounded => len,
};
if start > end {
slice_index_order_fail(start, end);
}
if end > len {
slice_end_index_len_fail(end, len);
}
let start = match range.start_bound() {
ops::Bound::Excluded(&start) if start >= end => slice_index_fail(start, end, len),
// Cannot overflow because `start < end` implies `start < usize::MAX`.
ops::Bound::Excluded(&start) => start + 1,
ops::Bound::Included(&start) if start > end => slice_index_fail(start, end, len),
ops::Bound::Included(&start) => start,
ops::Bound::Unbounded => 0,
};
ops::Range { start, end }
}
@ -982,25 +986,27 @@ pub(crate) fn into_slice_range(
len: usize,
(start, end): (ops::Bound<usize>, ops::Bound<usize>),
) -> ops::Range<usize> {
use ops::Bound;
let start = match start {
Bound::Included(start) => start,
Bound::Excluded(start) => {
start.checked_add(1).unwrap_or_else(|| slice_start_index_overflow_fail())
}
Bound::Unbounded => 0,
};
let end = match end {
Bound::Included(end) => {
end.checked_add(1).unwrap_or_else(|| slice_end_index_overflow_fail())
}
Bound::Excluded(end) => end,
Bound::Unbounded => len,
ops::Bound::Included(end) if end >= len => slice_index_fail(0, end, len),
// Cannot overflow because `end < len` implies `end < usize::MAX`.
ops::Bound::Included(end) => end + 1,
ops::Bound::Excluded(end) if end > len => slice_index_fail(0, end, len),
ops::Bound::Excluded(end) => end,
ops::Bound::Unbounded => len,
};
// Don't bother with checking `start < end` and `end <= len`
// since these checks are handled by `Range` impls
let start = match start {
ops::Bound::Excluded(start) if start >= end => slice_index_fail(start, end, len),
// Cannot overflow because `start < end` implies `start < usize::MAX`.
ops::Bound::Excluded(start) => start + 1,
ops::Bound::Included(start) if start > end => slice_index_fail(start, end, len),
ops::Bound::Included(start) => start,
ops::Bound::Unbounded => 0,
};
start..end
}

View File

@ -1492,28 +1492,28 @@ mod slice_index {
// note: using 0 specifically ensures that the result of overflowing is 0..0,
// so that `get` doesn't simply return None for the wrong reason.
bad: data[0 ..= usize::MAX];
message: "maximum usize";
message: "out of range";
}
in mod rangetoinclusive_overflow {
data: [0, 1];
bad: data[..= usize::MAX];
message: "maximum usize";
message: "out of range";
}
in mod boundpair_overflow_end {
data: [0; 1];
bad: data[(Bound::Unbounded, Bound::Included(usize::MAX))];
message: "maximum usize";
message: "out of range";
}
in mod boundpair_overflow_start {
data: [0; 1];
bad: data[(Bound::Excluded(usize::MAX), Bound::Unbounded)];
message: "maximum usize";
message: "out of range";
}
} // panic_cases!
}
@ -2008,7 +2008,7 @@ fn test_copy_within_panics_src_inverted() {
bytes.copy_within(2..1, 0);
}
#[test]
#[should_panic(expected = "attempted to index slice up to maximum usize")]
#[should_panic(expected = "out of range")]
fn test_copy_within_panics_src_out_of_bounds() {
let mut bytes = *b"Hello, World!";
// an inclusive range ending at usize::MAX would make src_end overflow

View File

@ -13,7 +13,6 @@ doc = false
[dependencies]
alloc = { path = "../alloc" }
cfg-if = { version = "1.0", features = ['rustc-dep-of-std'] }
core = { path = "../rustc-std-workspace-core", package = "rustc-std-workspace-core" }
unwind = { path = "../unwind" }

View File

@ -15,6 +15,7 @@
#![unstable(feature = "panic_unwind", issue = "32837")]
#![doc(issue_tracker_base_url = "https://github.com/rust-lang/rust/issues/")]
#![feature(cfg_emscripten_wasm_eh)]
#![feature(cfg_select)]
#![feature(core_intrinsics)]
#![feature(lang_items)]
#![feature(panic_unwind)]
@ -33,18 +34,21 @@ use alloc::boxed::Box;
use core::any::Any;
use core::panic::PanicPayload;
cfg_if::cfg_if! {
if #[cfg(all(target_os = "emscripten", not(emscripten_wasm_eh)))] {
cfg_select! {
all(target_os = "emscripten", not(emscripten_wasm_eh)) => {
#[path = "emcc.rs"]
mod imp;
} else if #[cfg(target_os = "hermit")] {
}
target_os = "hermit" => {
#[path = "hermit.rs"]
mod imp;
} else if #[cfg(target_os = "l4re")] {
}
target_os = "l4re" => {
// L4Re is unix family but does not yet support unwinding.
#[path = "dummy.rs"]
mod imp;
} else if #[cfg(any(
}
any(
all(target_family = "windows", target_env = "gnu"),
target_os = "psp",
target_os = "xous",
@ -52,19 +56,22 @@ cfg_if::cfg_if! {
all(target_family = "unix", not(any(target_os = "espidf", target_os = "nuttx"))),
all(target_vendor = "fortanix", target_env = "sgx"),
target_family = "wasm",
))] {
) => {
#[path = "gcc.rs"]
mod imp;
} else if #[cfg(miri)] {
}
miri => {
// Use the Miri runtime on Windows as miri doesn't support funclet based unwinding,
// only landingpad based unwinding. Also use the Miri runtime on unsupported platforms.
#[path = "miri.rs"]
mod imp;
} else if #[cfg(all(target_env = "msvc", not(target_arch = "arm")))] {
}
all(target_env = "msvc", not(target_arch = "arm")) => {
// LLVM does not support unwinding on 32 bit ARM msvc (thumbv7a-pc-windows-msvc)
#[path = "seh.rs"]
mod imp;
} else {
}
_ => {
// Targets that don't support unwinding.
// - os=none ("bare metal" targets)
// - os=uefi

View File

@ -289,10 +289,11 @@ macro_rules! define_cleanup {
}
}
}
cfg_if::cfg_if! {
if #[cfg(target_arch = "x86")] {
cfg_select! {
target_arch = "x86" => {
define_cleanup!("thiscall" "thiscall-unwind");
} else {
}
_ => {
define_cleanup!("C" "C-unwind");
}
}

View File

@ -59,6 +59,30 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
}
unsafe fn sanitize_standard_fds() {
#[allow(dead_code, unused_variables, unused_mut)]
let mut opened_devnull = -1;
#[allow(dead_code, unused_variables, unused_mut)]
let mut open_devnull = || {
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
use libc::open;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use libc::open64 as open;
if opened_devnull != -1 {
if libc::dup(opened_devnull) != -1 {
return;
}
}
opened_devnull = open(c"/dev/null".as_ptr(), libc::O_RDWR, 0);
if opened_devnull == -1 {
// If the stream is closed but we failed to reopen it, abort the
// process. Otherwise we wouldn't preserve the safety of
// operations on the corresponding Rust object Stdin, Stdout, or
// Stderr.
libc::abort();
}
};
// fast path with a single syscall for systems with poll()
#[cfg(not(any(
miri,
@ -74,11 +98,6 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
target_vendor = "apple",
)))]
'poll: {
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
use libc::open as open64;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use libc::open64;
use crate::sys::os::errno;
let pfds: &mut [_] = &mut [
libc::pollfd { fd: 0, events: 0, revents: 0 },
@ -106,13 +125,7 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
if pfd.revents & libc::POLLNVAL == 0 {
continue;
}
if open64(c"/dev/null".as_ptr(), libc::O_RDWR, 0) == -1 {
// If the stream is closed but we failed to reopen it, abort the
// process. Otherwise we wouldn't preserve the safety of
// operations on the corresponding Rust object Stdin, Stdout, or
// Stderr.
libc::abort();
}
open_devnull();
}
return;
}
@ -129,21 +142,10 @@ pub unsafe fn init(argc: isize, argv: *const *const u8, sigpipe: u8) {
target_os = "vita",
)))]
{
#[cfg(not(all(target_os = "linux", target_env = "gnu")))]
use libc::open as open64;
#[cfg(all(target_os = "linux", target_env = "gnu"))]
use libc::open64;
use crate::sys::os::errno;
for fd in 0..3 {
if libc::fcntl(fd, libc::F_GETFD) == -1 && errno() == libc::EBADF {
if open64(c"/dev/null".as_ptr(), libc::O_RDWR, 0) == -1 {
// If the stream is closed but we failed to reopen it, abort the
// process. Otherwise we wouldn't preserve the safety of
// operations on the corresponding Rust object Stdin, Stdout, or
// Stderr.
libc::abort();
}
open_devnull();
}
}
}

View File

@ -220,10 +220,6 @@ pub(crate) fn is_ci_llvm_available_for_target(
("armv7-unknown-linux-gnueabihf", false),
("loongarch64-unknown-linux-gnu", false),
("loongarch64-unknown-linux-musl", false),
("mips-unknown-linux-gnu", false),
("mips64-unknown-linux-gnuabi64", false),
("mips64el-unknown-linux-gnuabi64", false),
("mipsel-unknown-linux-gnu", false),
("powerpc-unknown-linux-gnu", false),
("powerpc64-unknown-linux-gnu", false),
("powerpc64le-unknown-linux-gnu", false),

View File

@ -28,7 +28,6 @@ runners:
- &job-windows
os: windows-2025
free_disk: true
<<: *base-job
- &job-windows-8c

View File

@ -1,72 +0,0 @@
"""
Start freeing disk space on Windows in the background by launching
the PowerShell cleanup script, and recording the PID in a file,
so later steps can wait for completion.
"""
import subprocess
from pathlib import Path
from free_disk_space_windows_util import get_pid_file, get_log_file, run_main
def get_cleanup_script() -> Path:
script_dir = Path(__file__).resolve().parent
cleanup_script = script_dir / "free-disk-space-windows.ps1"
if not cleanup_script.exists():
raise Exception(f"Cleanup script '{cleanup_script}' not found")
return cleanup_script
def write_pid(pid: int):
pid_file = get_pid_file()
if pid_file.exists():
raise Exception(f"Pid file '{pid_file}' already exists")
pid_file.write_text(str(pid))
print(f"wrote pid {pid} in file {pid_file}")
def launch_cleanup_process():
cleanup_script = get_cleanup_script()
log_file_path = get_log_file()
# Launch the PowerShell cleanup in the background and redirect logs.
try:
with open(log_file_path, "w", encoding="utf-8") as log_file:
proc = subprocess.Popen(
[
"pwsh",
# Suppress PowerShell startup banner/logo for cleaner logs.
"-NoLogo",
# Don't load user/system profiles. Ensures a clean, predictable environment.
"-NoProfile",
# Disable interactive prompts. Required for CI to avoid hangs.
"-NonInteractive",
# Execute the specified script file (next argument).
"-File",
str(cleanup_script),
],
# Write child stdout to the log file.
stdout=log_file,
# Merge stderr into stdout for a single, ordered log stream.
stderr=subprocess.STDOUT,
)
print(
f"Started free-disk-space cleanup in background. "
f"pid={proc.pid}; log_file={log_file_path}"
)
return proc
except FileNotFoundError as e:
raise Exception("pwsh not found on PATH; cannot start disk cleanup.") from e
def main() -> int:
proc = launch_cleanup_process()
# Write pid of the process to a file, so that later steps can read it and wait
# until the process completes.
write_pid(proc.pid)
return 0
if __name__ == "__main__":
run_main(main)

View File

@ -1,92 +0,0 @@
"""
Wait for the background Windows disk cleanup process.
"""
import ctypes
import time
from free_disk_space_windows_util import get_pid_file, get_log_file, run_main
def is_process_running(pid: int) -> bool:
PROCESS_QUERY_LIMITED_INFORMATION = 0x1000
processHandle = ctypes.windll.kernel32.OpenProcess(
PROCESS_QUERY_LIMITED_INFORMATION, 0, pid
)
if processHandle == 0:
# The process is not running.
# If you don't have the sufficient rights to check if a process is running,
# zero is also returned. But in GitHub Actions we have these rights.
return False
else:
ctypes.windll.kernel32.CloseHandle(processHandle)
return True
def print_logs():
"""Print the logs from the cleanup script."""
log_file = get_log_file()
if log_file.exists():
print("free-disk-space logs:")
# Print entire log; replace undecodable bytes to avoid exceptions.
try:
with open(log_file, "r", encoding="utf-8", errors="replace") as f:
print(f.read())
except Exception as e:
raise Exception(f"Failed to read log file '{log_file}'") from e
else:
print(f"::warning::Log file '{log_file}' not found")
def read_pid_from_file() -> int:
"""Read the PID from the pid file."""
pid_file = get_pid_file()
if not pid_file.exists():
raise Exception(
f"No background free-disk-space process to wait for: pid file {pid_file} not found"
)
pid_file_content = pid_file.read_text().strip()
# Delete the file if it exists
pid_file.unlink(missing_ok=True)
try:
# Read the first line and convert to int.
pid = int(pid_file_content.splitlines()[0])
return pid
except Exception as e:
raise Exception(
f"Error while parsing the pid file with content '{pid_file_content!r}'"
) from e
def wait_for_process(pid: int):
timeout_duration_seconds = 5 * 60
interval_seconds = 3
max_attempts = timeout_duration_seconds / interval_seconds
attempts = 0
# Poll until process exits
while is_process_running(pid):
if attempts >= max_attempts:
print(
"::warning::Timeout expired while waiting for the disk cleanup process to finish."
)
break
time.sleep(interval_seconds)
attempts += 1
def main() -> int:
pid = read_pid_from_file()
wait_for_process(pid)
print_logs()
return 0
if __name__ == "__main__":
run_main(main)

View File

@ -1,35 +0,0 @@
# Free disk space on Windows GitHub action runners.
$ErrorActionPreference = 'Stop'
Get-Volume | Out-String | Write-Output
$available = $(Get-Volume C).SizeRemaining
$dirs = 'C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm',
'C:\rtools45', 'C:\ghcup', 'C:\Program Files (x86)\Android',
'C:\Program Files\Google\Chrome', 'C:\Program Files (x86)\Microsoft\Edge',
'C:\Program Files\Mozilla Firefox', 'C:\Program Files\MySQL', 'C:\Julia',
'C:\Program Files\MongoDB', 'C:\Program Files\Azure Cosmos DB Emulator',
'C:\Program Files\PostgreSQL', 'C:\Program Files\Unity Hub',
'C:\Strawberry', 'C:\hostedtoolcache\windows\Java_Temurin-Hotspot_jdk'
foreach ($dir in $dirs) {
Start-ThreadJob -InputObject $dir {
Remove-Item -Recurse -Force -LiteralPath $input
} | Out-Null
}
foreach ($job in Get-Job) {
Wait-Job $job | Out-Null
if ($job.Error) {
Write-Output "::warning file=$PSCommandPath::$($job.Error)"
}
Remove-Job $job
}
Get-Volume | Out-String | Write-Output
$saved = ($(Get-Volume C).SizeRemaining - $available) / 1gb
$savedRounded = [math]::Round($saved, 3)
Write-Output "total space saved: $savedRounded GB"

View File

@ -1,10 +0,0 @@
#!/bin/bash
set -euo pipefail
script_dir=$(dirname "$0")
if [[ "${RUNNER_OS:-}" == "Windows" ]]; then
python3 "$script_dir/free-disk-space-windows-start.py"
else
$script_dir/free-disk-space-linux.sh
fi

View File

@ -1,29 +0,0 @@
"""
Utilities for Windows disk space cleanup scripts.
"""
import os
from pathlib import Path
import sys
def get_temp_dir() -> Path:
"""Get the temporary directory set by GitHub Actions."""
return Path(os.environ.get("RUNNER_TEMP"))
def get_pid_file() -> Path:
return get_temp_dir() / "free-disk-space.pid"
def get_log_file() -> Path:
return get_temp_dir() / "free-disk-space.log"
def run_main(main_fn):
exit_code = 1
try:
exit_code = main_fn()
except Exception as e:
print(f"::error::{e}")
sys.exit(exit_code)

View File

@ -194,6 +194,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"only-bpf",
"only-cdb",
"only-dist",
"only-eabihf",
"only-elf",
"only-emscripten",
"only-gnu",

View File

@ -1,5 +1,5 @@
thread 'main' ($TID) panicked at tests/panic/oob_subslice.rs:LL:CC:
range end index 5 out of range for slice of length 4
range end index 4 out of range for slice of length 4
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
note: in Miri, you may have to set `MIRIFLAGS=-Zmiri-env-forward=RUST_BACKTRACE` for the environment variable to have an effect

View File

@ -592,6 +592,8 @@ pub fn check(root: &Path, cargo: &Path, bless: bool, bad: &mut bool) {
if workspace == "library" {
check_runtime_license_exceptions(&metadata, bad);
check_runtime_no_duplicate_dependencies(&metadata, bad);
check_runtime_no_proc_macros(&metadata, bad);
checked_runtime_licenses = true;
}
}
@ -790,6 +792,37 @@ fn check_license_exceptions(
}
}
fn check_runtime_no_duplicate_dependencies(metadata: &Metadata, bad: &mut bool) {
let mut seen_pkgs = HashSet::new();
for pkg in &metadata.packages {
if pkg.source.is_none() {
continue;
}
if !seen_pkgs.insert(&*pkg.name) {
tidy_error!(
bad,
"duplicate package `{}` is not allowed for the standard library",
pkg.name
);
}
}
}
fn check_runtime_no_proc_macros(metadata: &Metadata, bad: &mut bool) {
for pkg in &metadata.packages {
if pkg.targets.iter().any(|target| target.is_proc_macro()) {
tidy_error!(
bad,
"proc macro `{}` is not allowed as standard library dependency.\n\
Using proc macros in the standard library would break cross-compilation \
as proc-macros don't get shipped for the host tuple.",
pkg.name
);
}
}
}
/// Checks the dependency of `restricted_dependency_crates` at the given path. Changes `bad` to
/// `true` if a check failed.
///

View File

@ -1,4 +1,5 @@
//@ revisions: z10 z10_vector z13 z13_no_vector
//@ add-core-stubs
// ignore-tidy-linelength
//@ assembly-output: emit-asm
//@ compile-flags: -Copt-level=3 -Z merge-functions=disabled
@ -18,24 +19,8 @@
// Cases where vector feature is disabled are rejected.
// See tests/ui/simd-abi-checks-s390x.rs for test for them.
#[lang = "pointee_sized"]
pub trait PointeeSized {}
#[lang = "meta_sized"]
pub trait MetaSized: PointeeSized {}
#[lang = "sized"]
pub trait Sized: MetaSized {}
#[lang = "copy"]
pub trait Copy {}
#[lang = "freeze"]
pub trait Freeze {}
impl<T: Copy, const N: usize> Copy for [T; N] {}
#[lang = "phantom_data"]
pub struct PhantomData<T: ?Sized>;
impl<T: ?Sized> Copy for PhantomData<T> {}
extern crate minicore;
use minicore::*;
#[repr(simd)]
pub struct i8x8([i8; 8]);
@ -52,8 +37,6 @@ pub struct WrapperWithZst<T>(T, PhantomData<()>);
#[repr(transparent)]
pub struct TransparentWrapper<T>(T);
impl Copy for i8 {}
impl Copy for i64 {}
impl Copy for i8x8 {}
impl Copy for i8x16 {}
impl Copy for i8x32 {}
@ -221,7 +204,7 @@ unsafe extern "C" fn vector_transparent_wrapper_ret_large(
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_arg_small(x: i8x8) -> i64 {
unsafe { *(&x as *const i8x8 as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_arg:
// CHECK: vlgvg %r2, %v24, 0
@ -229,7 +212,7 @@ unsafe extern "C" fn vector_arg_small(x: i8x8) -> i64 {
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_arg(x: i8x16) -> i64 {
unsafe { *(&x as *const i8x16 as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_arg_large:
// CHECK: lg %r2, 0(%r2)
@ -237,7 +220,7 @@ unsafe extern "C" fn vector_arg(x: i8x16) -> i64 {
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_arg_large(x: i8x32) -> i64 {
unsafe { *(&x as *const i8x32 as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_wrapper_arg_small:
@ -246,7 +229,7 @@ unsafe extern "C" fn vector_arg_large(x: i8x32) -> i64 {
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
unsafe { *(&x as *const Wrapper<i8x8> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_wrapper_arg:
// CHECK: vlgvg %r2, %v24, 0
@ -254,7 +237,7 @@ unsafe extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
unsafe { *(&x as *const Wrapper<i8x16> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_wrapper_arg_large:
// CHECK: lg %r2, 0(%r2)
@ -262,7 +245,7 @@ unsafe extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_wrapper_arg_large(x: Wrapper<i8x32>) -> i64 {
unsafe { *(&x as *const Wrapper<i8x32> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// https://github.com/rust-lang/rust/pull/131586#discussion_r1837071121
@ -272,7 +255,7 @@ unsafe extern "C" fn vector_wrapper_arg_large(x: Wrapper<i8x32>) -> i64 {
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_wrapper_padding_arg(x: WrapperAlign16<i8x8>) -> i64 {
unsafe { *(&x as *const WrapperAlign16<i8x8> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_wrapper_with_zst_arg_small:
@ -282,7 +265,7 @@ unsafe extern "C" fn vector_wrapper_padding_arg(x: WrapperAlign16<i8x8>) -> i64
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_wrapper_with_zst_arg_small(x: WrapperWithZst<i8x8>) -> i64 {
unsafe { *(&x as *const WrapperWithZst<i8x8> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_wrapper_with_zst_arg:
// CHECK: lg %r2, 0(%r2)
@ -290,7 +273,7 @@ unsafe extern "C" fn vector_wrapper_with_zst_arg_small(x: WrapperWithZst<i8x8>)
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_wrapper_with_zst_arg(x: WrapperWithZst<i8x16>) -> i64 {
unsafe { *(&x as *const WrapperWithZst<i8x16> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_wrapper_with_zst_arg_large:
// CHECK: lg %r2, 0(%r2)
@ -298,7 +281,7 @@ unsafe extern "C" fn vector_wrapper_with_zst_arg(x: WrapperWithZst<i8x16>) -> i6
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_wrapper_with_zst_arg_large(x: WrapperWithZst<i8x32>) -> i64 {
unsafe { *(&x as *const WrapperWithZst<i8x32> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_transparent_wrapper_arg_small:
@ -307,7 +290,7 @@ unsafe extern "C" fn vector_wrapper_with_zst_arg_large(x: WrapperWithZst<i8x32>)
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
unsafe { *(&x as *const TransparentWrapper<i8x8> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_transparent_wrapper_arg:
// CHECK: vlgvg %r2, %v24, 0
@ -315,7 +298,7 @@ unsafe extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
unsafe { *(&x as *const TransparentWrapper<i8x16> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
// CHECK-LABEL: vector_transparent_wrapper_arg_large:
// CHECK: lg %r2, 0(%r2)
@ -323,5 +306,5 @@ unsafe extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>
#[cfg_attr(no_vector, target_feature(enable = "vector"))]
#[no_mangle]
unsafe extern "C" fn vector_transparent_wrapper_arg_large(x: TransparentWrapper<i8x32>) -> i64 {
unsafe { *(&x as *const TransparentWrapper<i8x32> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}

View File

@ -8,8 +8,7 @@
#[no_mangle]
pub fn binary_search_index_no_bounds_check(s: &[u8]) -> u8 {
// CHECK-NOT: panic
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: panic_bounds_check
if let Ok(idx) = s.binary_search(&b'\\') { s[idx] } else { 42 }
}

View File

@ -10,7 +10,7 @@ pub struct S1<'a> {
// CHECK-LABEL: @slice_no_index_order
#[no_mangle]
pub fn slice_no_index_order<'a>(s: &'a mut S1, n: usize) -> &'a [u8] {
// CHECK-NOT: slice_index_order_fail
// CHECK-COUNT-1: slice_index_fail
let d = &s.data[s.position..s.position + n];
s.position += n;
return d;
@ -19,6 +19,6 @@ pub fn slice_no_index_order<'a>(s: &'a mut S1, n: usize) -> &'a [u8] {
// CHECK-LABEL: @test_check
#[no_mangle]
pub fn test_check<'a>(s: &'a mut S1, x: usize, y: usize) -> &'a [u8] {
// CHECK: slice_index_order_fail
// CHECK-COUNT-1: slice_index_fail
&s.data[x..y]
}

View File

@ -5,7 +5,7 @@
use std::cmp::max;
// CHECK-LABEL: @foo
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: unreachable
#[no_mangle]
pub fn foo(v: &mut Vec<u8>, size: usize) -> Option<&mut [u8]> {

View File

@ -6,7 +6,7 @@
#[no_mangle]
pub fn trim_in_place(a: &mut &[u8]) {
while a.first() == Some(&42) {
// CHECK-NOT: slice_index_order_fail
// CHECK-NOT: slice_index_fail
*a = &a[1..];
}
}
@ -15,7 +15,7 @@ pub fn trim_in_place(a: &mut &[u8]) {
#[no_mangle]
pub fn trim_in_place2(a: &mut &[u8]) {
while let Some(&42) = a.first() {
// CHECK-NOT: slice_index_order_fail
// CHECK-COUNT-1: slice_index_fail
*a = &a[2..];
}
}

View File

@ -10,7 +10,7 @@
// CHECK-LABEL: @already_sliced_no_bounds_check
#[no_mangle]
pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
// CHECK: slice_end_index_len_fail
// CHECK: slice_index_fail
// CHECK-NOT: panic_bounds_check
let _ = (&a[..2048], &b[..2048], &mut c[..2048]);
for i in 0..1024 {
@ -21,7 +21,7 @@ pub fn already_sliced_no_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
// CHECK-LABEL: @already_sliced_no_bounds_check_exact
#[no_mangle]
pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
// CHECK: slice_end_index_len_fail
// CHECK: slice_index_fail
// CHECK-NOT: panic_bounds_check
let _ = (&a[..1024], &b[..1024], &mut c[..1024]);
for i in 0..1024 {
@ -33,7 +33,7 @@ pub fn already_sliced_no_bounds_check_exact(a: &[u8], b: &[u8], c: &mut [u8]) {
// CHECK-LABEL: @already_sliced_bounds_check
#[no_mangle]
pub fn already_sliced_bounds_check(a: &[u8], b: &[u8], c: &mut [u8]) {
// CHECK: slice_end_index_len_fail
// CHECK: slice_index_fail
// CHECK: panic_bounds_check
let _ = (&a[..1023], &b[..2048], &mut c[..2048]);
for i in 0..1024 {

View File

@ -8,8 +8,7 @@
#[no_mangle]
pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
// CHECK-NOT: panic
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: unreachable
if let Some(idx) = s.iter().position(|b| *b == b'\\') { &s[..idx] } else { s }
@ -19,8 +18,7 @@ pub fn position_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
// CHECK-NOT: panic
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: unreachable
if let Some(idx) = s.iter().position(|b| *b == b'\\') { &s[idx..] } else { s }
@ -30,8 +28,7 @@ pub fn position_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
// CHECK-NOT: panic
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: unreachable
if let Some(idx) = s.iter().position(|b| *b == b'\\') { s[idx] } else { 42 }
@ -40,8 +37,7 @@ pub fn position_index_no_bounds_check(s: &[u8]) -> u8 {
#[no_mangle]
pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
// CHECK-NOT: panic
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: unreachable
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { &s[..idx] } else { s }
@ -51,8 +47,7 @@ pub fn rposition_slice_to_no_bounds_check(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
// CHECK-NOT: panic
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: unreachable
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { &s[idx..] } else { s }
@ -62,8 +57,7 @@ pub fn rposition_slice_from_no_bounds_check(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn rposition_index_no_bounds_check(s: &[u8]) -> u8 {
// CHECK-NOT: panic
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: unreachable
if let Some(idx) = s.iter().rposition(|b| *b == b'\\') { s[idx] } else { 42 }

View File

@ -6,7 +6,7 @@
#![crate_type = "rlib"]
#![feature(no_core, asm_experimental_arch)]
#![feature(s390x_target_feature, simd_ffi, link_llvm_intrinsics, repr_simd)]
#![feature(s390x_target_feature, simd_ffi, intrinsics, repr_simd)]
#![no_core]
extern crate minicore;
@ -30,16 +30,20 @@ struct f32x4([f32; 4]);
#[repr(simd)]
struct f64x2([f64; 2]);
#[allow(improper_ctypes)]
extern "C" {
#[link_name = "llvm.smax.v16i8"]
fn vmxb(a: i8x16, b: i8x16) -> i8x16;
#[link_name = "llvm.smax.v8i16"]
fn vmxh(a: i16x8, b: i16x8) -> i16x8;
#[link_name = "llvm.smax.v4i32"]
fn vmxf(a: i32x4, b: i32x4) -> i32x4;
#[link_name = "llvm.smax.v2i64"]
fn vmxg(a: i64x2, b: i64x2) -> i64x2;
impl Copy for i8x16 {}
impl Copy for i16x8 {}
impl Copy for i32x4 {}
impl Copy for i64x2 {}
#[rustc_intrinsic]
unsafe fn simd_ge<T, U>(x: T, y: T) -> U;
#[rustc_intrinsic]
unsafe fn simd_select<M, V>(mask: M, a: V, b: V) -> V;
#[inline(always)]
unsafe fn simd_max<T: Copy>(a: T, b: T) -> T {
simd_select(simd_ge::<T, T>(a, b), a, b)
}
// CHECK-LABEL: define <16 x i8> @max_i8x16
@ -48,7 +52,7 @@ extern "C" {
#[no_mangle]
#[target_feature(enable = "vector")]
pub unsafe extern "C" fn max_i8x16(a: i8x16, b: i8x16) -> i8x16 {
vmxb(a, b)
simd_max(a, b)
}
// CHECK-LABEL: define <8 x i16> @max_i16x8
@ -57,7 +61,7 @@ pub unsafe extern "C" fn max_i8x16(a: i8x16, b: i8x16) -> i8x16 {
#[no_mangle]
#[target_feature(enable = "vector")]
pub unsafe extern "C" fn max_i16x8(a: i16x8, b: i16x8) -> i16x8 {
vmxh(a, b)
simd_max(a, b)
}
// CHECK-LABEL: define <4 x i32> @max_i32x4
@ -66,7 +70,7 @@ pub unsafe extern "C" fn max_i16x8(a: i16x8, b: i16x8) -> i16x8 {
#[no_mangle]
#[target_feature(enable = "vector")]
pub unsafe extern "C" fn max_i32x4(a: i32x4, b: i32x4) -> i32x4 {
vmxf(a, b)
simd_max(a, b)
}
// CHECK-LABEL: define <2 x i64> @max_i64x2
@ -75,7 +79,7 @@ pub unsafe extern "C" fn max_i32x4(a: i32x4, b: i32x4) -> i32x4 {
#[no_mangle]
#[target_feature(enable = "vector")]
pub unsafe extern "C" fn max_i64x2(a: i64x2, b: i64x2) -> i64x2 {
vmxg(a, b)
simd_max(a, b)
}
// CHECK-LABEL: define <4 x float> @choose_f32x4
@ -108,7 +112,7 @@ pub unsafe extern "C" fn max_wrapper_i8x16(a: Wrapper<i8x16>, b: Wrapper<i8x16>)
// CHECK: call <16 x i8> @llvm.smax.v16i8
// CHECK-SAME: <16 x i8>
// CHECK-SAME: <16 x i8>
Wrapper(vmxb(a.0, b.0))
Wrapper(simd_max(a.0, b.0))
}
#[no_mangle]
@ -122,7 +126,7 @@ pub unsafe extern "C" fn max_wrapper_i64x2(a: Wrapper<i64x2>, b: Wrapper<i64x2>)
// CHECK: call <2 x i64> @llvm.smax.v2i64
// CHECK-SAME: <2 x i64>
// CHECK-SAME: <2 x i64>
Wrapper(vmxg(a.0, b.0))
Wrapper(simd_max(a.0, b.0))
}
#[no_mangle]

View File

@ -1,19 +1,18 @@
//@ compile-flags: -Copt-level=3
//@ only-x86_64
//@ min-llvm-version: 20
#![crate_type = "lib"]
// This test verifies that LLVM 20 properly optimizes the bounds check
// when accessing the last few elements of a slice with proper conditions.
// Previously, this would generate an unreachable branch to
// slice_start_index_len_fail even when the bounds check was provably safe.
// slice_index_fail even when the bounds check was provably safe.
// CHECK-LABEL: @last_four_initial(
#[no_mangle]
pub fn last_four_initial(s: &[u8]) -> &[u8] {
// Previously this would generate a branch to slice_start_index_len_fail
// Previously this would generate a branch to slice_index_fail
// that is unreachable. The LLVM 20 fix should eliminate this branch.
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: unreachable
let start = if s.len() <= 4 { 0 } else { s.len() - 4 };
&s[start..]
@ -23,7 +22,7 @@ pub fn last_four_initial(s: &[u8]) -> &[u8] {
#[no_mangle]
pub fn last_four_optimized(s: &[u8]) -> &[u8] {
// This version was already correctly optimized before the fix in LLVM 20.
// CHECK-NOT: slice_start_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK-NOT: unreachable
if s.len() <= 4 { &s[0..] } else { &s[s.len() - 4..] }
}
@ -32,6 +31,6 @@ pub fn last_four_optimized(s: &[u8]) -> &[u8] {
// CHECK-LABEL: @test_bounds_check_happens(
#[no_mangle]
pub fn test_bounds_check_happens(s: &[u8], i: usize) -> &[u8] {
// CHECK: slice_start_index_len_fail
// CHECK: slice_index_fail
&s[i..]
}

View File

@ -8,10 +8,10 @@
#[no_mangle]
pub fn slice_reverse_u8(slice: &mut [u8]) {
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK: shufflevector <{{[0-9]+}} x i8>
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
slice.reverse();
}
@ -19,9 +19,9 @@ pub fn slice_reverse_u8(slice: &mut [u8]) {
#[no_mangle]
pub fn slice_reverse_i32(slice: &mut [i32]) {
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
// CHECK: shufflevector <{{[0-9]+}} x i32>
// CHECK-NOT: panic_bounds_check
// CHECK-NOT: slice_end_index_len_fail
// CHECK-NOT: slice_index_fail
slice.reverse();
}

View File

@ -4,14 +4,81 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range<usize>) -> &[u32] {
debug slice => _1;
debug index => _2;
let mut _0: &[u32];
let mut _3: usize;
let mut _4: usize;
scope 1 (inlined #[track_caller] core::slice::index::<impl Index<std::ops::Range<usize>> for [u32]>::index) {
scope 2 (inlined #[track_caller] <std::ops::Range<usize> as SliceIndex<[u32]>>::index) {
let mut _7: usize;
let mut _8: bool;
let mut _9: *const [u32];
let _12: *const [u32];
let mut _13: usize;
let mut _14: !;
scope 3 (inlined core::num::<impl usize>::checked_sub) {
let mut _5: bool;
let mut _6: usize;
}
scope 4 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
let _10: *const u32;
scope 5 {
let _11: *const u32;
scope 6 {
}
}
}
}
}
bb0: {
_0 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, move _1) -> [return: bb1, unwind unreachable];
_3 = move (_2.0: usize);
_4 = move (_2.1: usize);
StorageLive(_5);
_5 = Lt(copy _4, copy _3);
switchInt(move _5) -> [0: bb1, otherwise: bb4];
}
bb1: {
_6 = SubUnchecked(copy _4, copy _3);
StorageDead(_5);
StorageLive(_8);
StorageLive(_7);
_7 = PtrMetadata(copy _1);
_8 = Le(copy _4, move _7);
switchInt(move _8) -> [0: bb2, otherwise: bb3];
}
bb2: {
StorageDead(_7);
goto -> bb5;
}
bb3: {
StorageDead(_7);
StorageLive(_12);
StorageLive(_9);
_9 = &raw const (*_1);
StorageLive(_10);
StorageLive(_11);
_10 = copy _9 as *const u32 (PtrToPtr);
_11 = Offset(copy _10, copy _3);
_12 = *const [u32] from (copy _11, copy _6);
StorageDead(_11);
StorageDead(_10);
StorageDead(_9);
_0 = &(*_12);
StorageDead(_12);
StorageDead(_8);
return;
}
bb4: {
StorageDead(_5);
goto -> bb5;
}
bb5: {
StorageLive(_13);
_13 = PtrMetadata(copy _1);
_14 = core::slice::index::slice_index_fail(move _3, move _4, move _13) -> unwind unreachable;
}
}

View File

@ -4,14 +4,81 @@ fn slice_index_range(_1: &[u32], _2: std::ops::Range<usize>) -> &[u32] {
debug slice => _1;
debug index => _2;
let mut _0: &[u32];
let mut _3: usize;
let mut _4: usize;
scope 1 (inlined #[track_caller] core::slice::index::<impl Index<std::ops::Range<usize>> for [u32]>::index) {
scope 2 (inlined #[track_caller] <std::ops::Range<usize> as SliceIndex<[u32]>>::index) {
let mut _7: usize;
let mut _8: bool;
let mut _9: *const [u32];
let _12: *const [u32];
let mut _13: usize;
let mut _14: !;
scope 3 (inlined core::num::<impl usize>::checked_sub) {
let mut _5: bool;
let mut _6: usize;
}
scope 4 (inlined core::slice::index::get_offset_len_noubcheck::<u32>) {
let _10: *const u32;
scope 5 {
let _11: *const u32;
scope 6 {
}
}
}
}
}
bb0: {
_0 = <std::ops::Range<usize> as SliceIndex<[u32]>>::index(move _2, move _1) -> [return: bb1, unwind continue];
_3 = move (_2.0: usize);
_4 = move (_2.1: usize);
StorageLive(_5);
_5 = Lt(copy _4, copy _3);
switchInt(move _5) -> [0: bb1, otherwise: bb4];
}
bb1: {
_6 = SubUnchecked(copy _4, copy _3);
StorageDead(_5);
StorageLive(_8);
StorageLive(_7);
_7 = PtrMetadata(copy _1);
_8 = Le(copy _4, move _7);
switchInt(move _8) -> [0: bb2, otherwise: bb3];
}
bb2: {
StorageDead(_7);
goto -> bb5;
}
bb3: {
StorageDead(_7);
StorageLive(_12);
StorageLive(_9);
_9 = &raw const (*_1);
StorageLive(_10);
StorageLive(_11);
_10 = copy _9 as *const u32 (PtrToPtr);
_11 = Offset(copy _10, copy _3);
_12 = *const [u32] from (copy _11, copy _6);
StorageDead(_11);
StorageDead(_10);
StorageDead(_9);
_0 = &(*_12);
StorageDead(_12);
StorageDead(_8);
return;
}
bb4: {
StorageDead(_5);
goto -> bb5;
}
bb5: {
StorageLive(_13);
_13 = PtrMetadata(copy _1);
_14 = core::slice::index::slice_index_fail(move _3, move _4, move _13) -> unwind continue;
}
}

View File

@ -110,47 +110,47 @@ extern "C" fn vector_transparent_wrapper_ret_large(
#[no_mangle]
extern "C" fn vector_arg_small(x: i8x8) -> i64 {
//~^ ERROR requires the `vector` target feature, which is not enabled
unsafe { *(&x as *const i8x8 as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
#[no_mangle]
extern "C" fn vector_arg(x: i8x16) -> i64 {
//~^ ERROR requires the `vector` target feature, which is not enabled
unsafe { *(&x as *const i8x16 as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
#[no_mangle]
extern "C" fn vector_arg_large(x: i8x32) -> i64 {
// Ok
unsafe { *(&x as *const i8x32 as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
#[no_mangle]
extern "C" fn vector_wrapper_arg_small(x: Wrapper<i8x8>) -> i64 {
//~^ ERROR requires the `vector` target feature, which is not enabled
unsafe { *(&x as *const Wrapper<i8x8> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
#[no_mangle]
extern "C" fn vector_wrapper_arg(x: Wrapper<i8x16>) -> i64 {
//~^ ERROR requires the `vector` target feature, which is not enabled
unsafe { *(&x as *const Wrapper<i8x16> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
#[no_mangle]
extern "C" fn vector_wrapper_arg_large(x: Wrapper<i8x32>) -> i64 {
// Ok
unsafe { *(&x as *const Wrapper<i8x32> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
#[no_mangle]
extern "C" fn vector_transparent_wrapper_arg_small(x: TransparentWrapper<i8x8>) -> i64 {
//~^ ERROR requires the `vector` target feature, which is not enabled
unsafe { *(&x as *const TransparentWrapper<i8x8> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
#[no_mangle]
extern "C" fn vector_transparent_wrapper_arg(x: TransparentWrapper<i8x16>) -> i64 {
//~^ ERROR requires the `vector` target feature, which is not enabled
unsafe { *(&x as *const TransparentWrapper<i8x16> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}
#[no_mangle]
extern "C" fn vector_transparent_wrapper_arg_large(x: TransparentWrapper<i8x32>) -> i64 {
// Ok
unsafe { *(&x as *const TransparentWrapper<i8x32> as *const i64) }
unsafe { *(&raw const x as *const i64) }
}

View File

@ -18,7 +18,7 @@ error: `#[naked]` attribute cannot be used on foreign functions
LL | #[unsafe(naked)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[naked]` can be applied to methods, functions
= help: `#[naked]` can be applied to methods and functions
error: `#[naked]` attribute cannot be used on structs
--> $DIR/naked-invalid-attr.rs:13:1
@ -42,7 +42,7 @@ error: `#[naked]` attribute cannot be used on required trait methods
LL | #[unsafe(naked)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[naked]` can be applied to functions, inherent methods, provided trait methods, trait methods in impl blocks
= help: `#[naked]` can be applied to functions, inherent methods, provided trait methods, and trait methods in impl blocks
error: `#[naked]` attribute cannot be used on closures
--> $DIR/naked-invalid-attr.rs:51:5
@ -50,7 +50,7 @@ error: `#[naked]` attribute cannot be used on closures
LL | #[unsafe(naked)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[naked]` can be applied to methods, functions
= help: `#[naked]` can be applied to methods and functions
error[E0736]: attribute incompatible with `#[unsafe(naked)]`
--> $DIR/naked-invalid-attr.rs:56:3

View File

@ -4,7 +4,7 @@ error: `#[linkage]` attribute cannot be used on type aliases
LL | #[linkage = "weak"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[linkage]` can be applied to functions, statics, foreign statics
= help: `#[linkage]` can be applied to functions, statics, and foreign statics
error: `#[linkage]` attribute cannot be used on modules
--> $DIR/linkage.rs:9:1
@ -12,7 +12,7 @@ error: `#[linkage]` attribute cannot be used on modules
LL | #[linkage = "weak"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[linkage]` can be applied to functions, statics, foreign statics
= help: `#[linkage]` can be applied to functions, statics, and foreign statics
error: `#[linkage]` attribute cannot be used on structs
--> $DIR/linkage.rs:12:1
@ -20,7 +20,7 @@ error: `#[linkage]` attribute cannot be used on structs
LL | #[linkage = "weak"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[linkage]` can be applied to functions, statics, foreign statics
= help: `#[linkage]` can be applied to functions, statics, and foreign statics
error: `#[linkage]` attribute cannot be used on inherent impl blocks
--> $DIR/linkage.rs:15:1
@ -28,7 +28,7 @@ error: `#[linkage]` attribute cannot be used on inherent impl blocks
LL | #[linkage = "weak"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[linkage]` can be applied to functions, statics, foreign statics
= help: `#[linkage]` can be applied to functions, statics, and foreign statics
error: `#[linkage]` attribute cannot be used on expressions
--> $DIR/linkage.rs:23:5
@ -36,7 +36,7 @@ error: `#[linkage]` attribute cannot be used on expressions
LL | #[linkage = "weak"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[linkage]` can be applied to functions, statics, foreign statics
= help: `#[linkage]` can be applied to functions, statics, and foreign statics
error: `#[linkage]` attribute cannot be used on closures
--> $DIR/linkage.rs:39:13
@ -44,7 +44,7 @@ error: `#[linkage]` attribute cannot be used on closures
LL | let _ = #[linkage = "weak"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[linkage]` can be applied to methods, functions, statics, foreign statics, foreign functions
= help: `#[linkage]` can be applied to methods, functions, statics, foreign statics, and foreign functions
error: aborting due to 6 previous errors

View File

@ -0,0 +1,77 @@
#![feature(extended_varargs_abi_support)]
//@ run-pass
//@ only-arm
//@ ignore-thumb (this test uses arm assembly)
//@ only-eabihf (the assembly below requires float hardware support)
// Check that multiple c-variadic calling conventions can be used in the same program.
//
// Clang and gcc reject defining functions with a non-default calling convention and a variable
// argument list, so C programs that use multiple c-variadic calling conventions are unlikely
// to come up. Here we validate that our codegen backends do in fact generate correct code.
extern "C" {
fn variadic_c(_: f64, _: ...) -> f64;
}
extern "aapcs" {
fn variadic_aapcs(_: f64, _: ...) -> f64;
}
fn main() {
unsafe {
assert_eq!(variadic_c(1.0, 2.0, 3.0), 1.0 + 2.0 + 3.0);
assert_eq!(variadic_aapcs(1.0, 2.0, 3.0), 1.0 + 2.0 + 3.0);
}
}
// This assembly was generated using https://godbolt.org/z/xcW6a1Tj5, and corresponds to the
// following code compiled for the `armv7-unknown-linux-gnueabihf` target:
//
// ```rust
// #![feature(c_variadic)]
//
// #[unsafe(no_mangle)]
// unsafe extern "C" fn variadic(a: f64, mut args: ...) -> f64 {
// let b = args.arg::<f64>();
// let c = args.arg::<f64>();
//
// a + b + c
// }
// ```
//
// This function uses floats (and passes one normal float argument) because the aapcs and C calling
// conventions differ in how floats are passed, e.g. https://godbolt.org/z/sz799f51x. However, for
// c-variadic functions, both ABIs actually behave the same, based on:
//
// https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#65parameter-passing
//
// > A variadic function is always marshaled as for the base standard.
//
// https://github.com/ARM-software/abi-aa/blob/main/aapcs32/aapcs32.rst#7the-standard-variants
//
// > This section applies only to non-variadic functions. For a variadic function the base standard
// > is always used both for argument passing and result return.
core::arch::global_asm!(
r#"
{variadic_c}:
{variadic_aapcs}:
sub sp, sp, #12
stmib sp, {{r2, r3}}
vmov d0, r0, r1
add r0, sp, #4
vldr d1, [sp, #4]
add r0, r0, #15
bic r0, r0, #7
vadd.f64 d0, d0, d1
add r1, r0, #8
str r1, [sp]
vldr d1, [r0]
vadd.f64 d0, d0, d1
vmov r0, r1, d0
add sp, sp, #12
bx lr
"#,
variadic_c = sym variadic_c,
variadic_aapcs = sym variadic_aapcs,
);

View File

@ -0,0 +1,10 @@
// Tests that static closures are not stable in the parser grammar unless the
// coroutine feature is enabled.
#[cfg(any())]
fn foo() {
let _ = static || {};
//~^ ERROR coroutine syntax is experimental
}
fn main() {}

View File

@ -0,0 +1,13 @@
error[E0658]: coroutine syntax is experimental
--> $DIR/static-closure-unexpanded.rs:6:13
|
LL | let _ = static || {};
| ^^^^^^
|
= note: see issue #43122 <https://github.com/rust-lang/rust/issues/43122> for more information
= help: add `#![feature(coroutines)]` 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: aborting due to 1 previous error
For more information about this error, try `rustc --explain E0658`.

View File

@ -14,7 +14,7 @@ error: `#[coverage]` attribute cannot be used on type aliases
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on traits
--> $DIR/allowed-positions.rs:17:1
@ -22,7 +22,7 @@ error: `#[coverage]` attribute cannot be used on traits
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on associated consts
--> $DIR/allowed-positions.rs:19:5
@ -30,7 +30,7 @@ error: `#[coverage]` attribute cannot be used on associated consts
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on associated types
--> $DIR/allowed-positions.rs:22:5
@ -38,7 +38,7 @@ error: `#[coverage]` attribute cannot be used on associated types
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on required trait methods
--> $DIR/allowed-positions.rs:25:5
@ -46,7 +46,7 @@ error: `#[coverage]` attribute cannot be used on required trait methods
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to impl blocks, functions, closures, provided trait methods, trait methods in impl blocks, inherent methods, modules, crates
= help: `#[coverage]` can be applied to impl blocks, functions, closures, provided trait methods, trait methods in impl blocks, inherent methods, modules, and crates
error: `#[coverage]` attribute cannot be used on required trait methods
--> $DIR/allowed-positions.rs:31:5
@ -54,7 +54,7 @@ error: `#[coverage]` attribute cannot be used on required trait methods
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to impl blocks, functions, closures, provided trait methods, trait methods in impl blocks, inherent methods, modules, crates
= help: `#[coverage]` can be applied to impl blocks, functions, closures, provided trait methods, trait methods in impl blocks, inherent methods, modules, and crates
error: `#[coverage]` attribute cannot be used on associated types
--> $DIR/allowed-positions.rs:39:5
@ -62,7 +62,7 @@ error: `#[coverage]` attribute cannot be used on associated types
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on associated types
--> $DIR/allowed-positions.rs:56:5
@ -70,7 +70,7 @@ error: `#[coverage]` attribute cannot be used on associated types
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on structs
--> $DIR/allowed-positions.rs:61:1
@ -78,7 +78,7 @@ error: `#[coverage]` attribute cannot be used on structs
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on struct fields
--> $DIR/allowed-positions.rs:63:5
@ -86,7 +86,7 @@ error: `#[coverage]` attribute cannot be used on struct fields
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on foreign statics
--> $DIR/allowed-positions.rs:76:5
@ -94,7 +94,7 @@ error: `#[coverage]` attribute cannot be used on foreign statics
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on foreign types
--> $DIR/allowed-positions.rs:79:5
@ -102,7 +102,7 @@ error: `#[coverage]` attribute cannot be used on foreign types
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on foreign functions
--> $DIR/allowed-positions.rs:82:5
@ -110,7 +110,7 @@ error: `#[coverage]` attribute cannot be used on foreign functions
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to methods, impl blocks, functions, closures, modules, crates
= help: `#[coverage]` can be applied to methods, impl blocks, functions, closures, modules, and crates
error: `#[coverage]` attribute cannot be used on statements
--> $DIR/allowed-positions.rs:88:5
@ -118,7 +118,7 @@ error: `#[coverage]` attribute cannot be used on statements
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on statements
--> $DIR/allowed-positions.rs:94:5
@ -126,7 +126,7 @@ error: `#[coverage]` attribute cannot be used on statements
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on match arms
--> $DIR/allowed-positions.rs:110:9
@ -134,7 +134,7 @@ error: `#[coverage]` attribute cannot be used on match arms
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: `#[coverage]` attribute cannot be used on expressions
--> $DIR/allowed-positions.rs:114:5
@ -142,7 +142,7 @@ error: `#[coverage]` attribute cannot be used on expressions
LL | #[coverage(off)]
| ^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error: aborting due to 18 previous errors

View File

@ -49,7 +49,7 @@ error: `#[coverage]` attribute cannot be used on structs
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:26:1
@ -87,7 +87,7 @@ error: `#[coverage]` attribute cannot be used on associated consts
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:35:1
@ -110,7 +110,7 @@ error: `#[coverage]` attribute cannot be used on traits
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:39:5
@ -133,7 +133,7 @@ error: `#[coverage]` attribute cannot be used on associated consts
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:44:5
@ -156,7 +156,7 @@ error: `#[coverage]` attribute cannot be used on associated types
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:50:1
@ -194,7 +194,7 @@ error: `#[coverage]` attribute cannot be used on associated consts
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:58:5
@ -217,7 +217,7 @@ error: `#[coverage]` attribute cannot be used on associated types
LL | #[coverage = "off"]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/name-value.rs:64:1

View File

@ -43,7 +43,7 @@ error: `#[coverage]` attribute cannot be used on structs
LL | #[coverage]
| ^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:26:1
@ -77,7 +77,7 @@ error: `#[coverage]` attribute cannot be used on associated consts
LL | #[coverage]
| ^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:35:1
@ -98,7 +98,7 @@ error: `#[coverage]` attribute cannot be used on traits
LL | #[coverage]
| ^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:39:5
@ -119,7 +119,7 @@ error: `#[coverage]` attribute cannot be used on associated consts
LL | #[coverage]
| ^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:44:5
@ -140,7 +140,7 @@ error: `#[coverage]` attribute cannot be used on associated types
LL | #[coverage]
| ^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:50:1
@ -174,7 +174,7 @@ error: `#[coverage]` attribute cannot be used on associated consts
LL | #[coverage]
| ^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:58:5
@ -195,7 +195,7 @@ error: `#[coverage]` attribute cannot be used on associated types
LL | #[coverage]
| ^^^^^^^^^^^
|
= help: `#[coverage]` can be applied to functions, impl blocks, modules, crates
= help: `#[coverage]` can be applied to functions, impl blocks, modules, and crates
error[E0539]: malformed `coverage` attribute input
--> $DIR/word-only.rs:64:1

View File

@ -177,7 +177,7 @@ LL | #[deprecated = "hello"]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, foreign statics, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, crates
= help: `#[deprecated]` can be applied to functions, data types, modules, unions, constants, statics, macro defs, type aliases, use statements, foreign statics, struct fields, traits, associated types, associated consts, enum variants, inherent impl blocks, and crates
= note: `#[deny(useless_deprecated)]` on by default
error: aborting due to 10 previous errors

View File

@ -5,7 +5,7 @@ LL | #[no_mangle]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics
= help: `#[no_mangle]` can be applied to functions and statics
note: the lint level is defined here
--> $DIR/extern-no-mangle.rs:1:9
|
@ -19,7 +19,7 @@ LL | #[no_mangle]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to methods, functions, statics
= help: `#[no_mangle]` can be applied to methods, functions, and statics
warning: `#[no_mangle]` attribute cannot be used on statements
--> $DIR/extern-no-mangle.rs:24:5
@ -28,7 +28,7 @@ LL | #[no_mangle]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics
= help: `#[no_mangle]` can be applied to functions and statics
warning: 3 warnings emitted

View File

@ -13,7 +13,7 @@ LL | #[link_name = "foo"]
| ^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
note: the lint level is defined here
--> $DIR/issue-47725.rs:1:9
|
@ -27,7 +27,7 @@ LL | #[link_name = "foobar"]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on foreign modules
--> $DIR/issue-47725.rs:19:1
@ -36,7 +36,7 @@ LL | #[link_name]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
error: aborting due to 1 previous error; 3 warnings emitted

View File

@ -13,7 +13,7 @@ error: `#[allow_internal_unstable]` attribute cannot be used on structs
LL | #[allow_internal_unstable(something)]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[allow_internal_unstable]` can be applied to macro defs, functions
= help: `#[allow_internal_unstable]` can be applied to macro defs and functions
error: aborting due to 2 previous errors

View File

@ -30,7 +30,7 @@ error: `#[export_name]` attribute cannot be used on crates
LL | #![export_name = "2200"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[export_name]` can be applied to functions, statics
= help: `#[export_name]` can be applied to functions and statics
error: `#[inline]` attribute cannot be used on crates
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:28:1
@ -86,7 +86,7 @@ error: `#[export_name]` attribute cannot be used on modules
LL | #[export_name = "2200"]
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[export_name]` can be applied to functions, statics
= help: `#[export_name]` can be applied to functions and statics
error: `#[export_name]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:85:17
@ -94,7 +94,7 @@ error: `#[export_name]` attribute cannot be used on modules
LL | mod inner { #![export_name="2200"] }
| ^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[export_name]` can be applied to functions, statics
= help: `#[export_name]` can be applied to functions and statics
error: `#[export_name]` attribute cannot be used on structs
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:90:5
@ -102,7 +102,7 @@ error: `#[export_name]` attribute cannot be used on structs
LL | #[export_name = "2200"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[export_name]` can be applied to functions, statics
= help: `#[export_name]` can be applied to functions and statics
error: `#[export_name]` attribute cannot be used on type aliases
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:93:5
@ -110,7 +110,7 @@ error: `#[export_name]` attribute cannot be used on type aliases
LL | #[export_name = "2200"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[export_name]` can be applied to functions, statics
= help: `#[export_name]` can be applied to functions and statics
error: `#[export_name]` attribute cannot be used on inherent impl blocks
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:96:5
@ -118,7 +118,7 @@ error: `#[export_name]` attribute cannot be used on inherent impl blocks
LL | #[export_name = "2200"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[export_name]` can be applied to functions, statics
= help: `#[export_name]` can be applied to functions and statics
error: `#[export_name]` attribute cannot be used on required trait methods
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:100:9
@ -126,7 +126,7 @@ error: `#[export_name]` attribute cannot be used on required trait methods
LL | #[export_name = "2200"] fn foo();
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[export_name]` can be applied to statics, functions, inherent methods, provided trait methods, trait methods in impl blocks
= help: `#[export_name]` can be applied to statics, functions, inherent methods, provided trait methods, and trait methods in impl blocks
error: attribute should be applied to an `extern crate` item
--> $DIR/issue-43106-gating-of-builtin-attrs-error.rs:56:1

View File

@ -675,7 +675,7 @@ LL | #[macro_use] fn f() { }
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_use]` can be applied to modules, extern crates, crates
= help: `#[macro_use]` can be applied to modules, extern crates, and crates
warning: `#[macro_use]` attribute cannot be used on structs
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:197:5
@ -684,7 +684,7 @@ LL | #[macro_use] struct S;
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_use]` can be applied to modules, extern crates, crates
= help: `#[macro_use]` can be applied to modules, extern crates, and crates
warning: `#[macro_use]` attribute cannot be used on type aliases
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:203:5
@ -693,7 +693,7 @@ LL | #[macro_use] type T = S;
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_use]` can be applied to modules, extern crates, crates
= help: `#[macro_use]` can be applied to modules, extern crates, and crates
warning: `#[macro_use]` attribute cannot be used on inherent impl blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:209:5
@ -702,7 +702,7 @@ LL | #[macro_use] impl S { }
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_use]` can be applied to modules, extern crates, crates
= help: `#[macro_use]` can be applied to modules, extern crates, and crates
warning: `#[path]` attribute cannot be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:271:5
@ -810,7 +810,7 @@ LL | #[no_mangle]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics
= help: `#[no_mangle]` can be applied to functions and statics
warning: `#[no_mangle]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:347:17
@ -819,7 +819,7 @@ LL | mod inner { #![no_mangle] }
| ^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics
= help: `#[no_mangle]` can be applied to functions and statics
warning: `#[no_mangle]` attribute cannot be used on structs
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:355:5
@ -828,7 +828,7 @@ LL | #[no_mangle] struct S;
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics
= help: `#[no_mangle]` can be applied to functions and statics
warning: `#[no_mangle]` attribute cannot be used on type aliases
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:361:5
@ -837,7 +837,7 @@ LL | #[no_mangle] type T = S;
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics
= help: `#[no_mangle]` can be applied to functions and statics
warning: `#[no_mangle]` attribute cannot be used on inherent impl blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:367:5
@ -846,7 +846,7 @@ LL | #[no_mangle] impl S { }
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics
= help: `#[no_mangle]` can be applied to functions and statics
warning: `#[no_mangle]` attribute cannot be used on required trait methods
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:374:9
@ -855,7 +855,7 @@ LL | #[no_mangle] fn foo();
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics, inherent methods, trait methods in impl blocks
= help: `#[no_mangle]` can be applied to functions, statics, inherent methods, and trait methods in impl blocks
warning: `#[no_mangle]` attribute cannot be used on provided trait methods
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:380:9
@ -864,7 +864,7 @@ LL | #[no_mangle] fn bar() {}
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_mangle]` can be applied to functions, statics, inherent methods, trait methods in impl blocks
= help: `#[no_mangle]` can be applied to functions, statics, inherent methods, and trait methods in impl blocks
warning: `#[should_panic]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:388:1
@ -963,7 +963,7 @@ LL | #[no_implicit_prelude] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_implicit_prelude]` can be applied to modules, crates
= help: `#[no_implicit_prelude]` can be applied to modules and crates
warning: `#[no_implicit_prelude]` attribute cannot be used on structs
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:464:5
@ -972,7 +972,7 @@ LL | #[no_implicit_prelude] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_implicit_prelude]` can be applied to modules, crates
= help: `#[no_implicit_prelude]` can be applied to modules and crates
warning: `#[no_implicit_prelude]` attribute cannot be used on type aliases
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:470:5
@ -981,7 +981,7 @@ LL | #[no_implicit_prelude] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_implicit_prelude]` can be applied to modules, crates
= help: `#[no_implicit_prelude]` can be applied to modules and crates
warning: `#[no_implicit_prelude]` attribute cannot be used on inherent impl blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:476:5
@ -990,7 +990,7 @@ LL | #[no_implicit_prelude] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[no_implicit_prelude]` can be applied to modules, crates
= help: `#[no_implicit_prelude]` can be applied to modules and crates
warning: `#[macro_escape]` attribute cannot be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:510:5
@ -999,7 +999,7 @@ LL | #[macro_escape] fn f() { }
| ^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_escape]` can be applied to modules, extern crates, crates
= help: `#[macro_escape]` can be applied to modules, extern crates, and crates
warning: `#[macro_escape]` attribute cannot be used on structs
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:516:5
@ -1008,7 +1008,7 @@ LL | #[macro_escape] struct S;
| ^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_escape]` can be applied to modules, extern crates, crates
= help: `#[macro_escape]` can be applied to modules, extern crates, and crates
warning: `#[macro_escape]` attribute cannot be used on type aliases
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:522:5
@ -1017,7 +1017,7 @@ LL | #[macro_escape] type T = S;
| ^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_escape]` can be applied to modules, extern crates, crates
= help: `#[macro_escape]` can be applied to modules, extern crates, and crates
warning: `#[macro_escape]` attribute cannot be used on inherent impl blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:528:5
@ -1026,7 +1026,7 @@ LL | #[macro_escape] impl S { }
| ^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_escape]` can be applied to modules, extern crates, crates
= help: `#[macro_escape]` can be applied to modules, extern crates, and crates
warning: `#[cold]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:571:1
@ -1080,7 +1080,7 @@ LL | #[link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on foreign modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:611:5
@ -1089,7 +1089,7 @@ LL | #[link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:618:17
@ -1098,7 +1098,7 @@ LL | mod inner { #![link_name="1900"] }
| ^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on functions
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:624:5
@ -1107,7 +1107,7 @@ LL | #[link_name = "1900"] fn f() { }
| ^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on structs
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:630:5
@ -1116,7 +1116,7 @@ LL | #[link_name = "1900"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on type aliases
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:636:5
@ -1125,7 +1125,7 @@ LL | #[link_name = "1900"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_name]` attribute cannot be used on inherent impl blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:642:5
@ -1134,7 +1134,7 @@ LL | #[link_name = "1900"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_section]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:649:1
@ -1143,7 +1143,7 @@ LL | #[link_section = "1800"]
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_section]` can be applied to statics, functions
= help: `#[link_section]` can be applied to statics and functions
warning: `#[link_section]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:655:17
@ -1152,7 +1152,7 @@ LL | mod inner { #![link_section="1800"] }
| ^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_section]` can be applied to statics, functions
= help: `#[link_section]` can be applied to statics and functions
warning: `#[link_section]` attribute cannot be used on structs
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:663:5
@ -1161,7 +1161,7 @@ LL | #[link_section = "1800"] struct S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_section]` can be applied to statics, functions
= help: `#[link_section]` can be applied to statics and functions
warning: `#[link_section]` attribute cannot be used on type aliases
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:669:5
@ -1170,7 +1170,7 @@ LL | #[link_section = "1800"] type T = S;
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_section]` can be applied to statics, functions
= help: `#[link_section]` can be applied to statics and functions
warning: `#[link_section]` attribute cannot be used on inherent impl blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:675:5
@ -1179,7 +1179,7 @@ LL | #[link_section = "1800"] impl S { }
| ^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_section]` can be applied to statics, functions
= help: `#[link_section]` can be applied to statics and functions
warning: `#[must_use]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:736:1
@ -1188,7 +1188,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
warning: `#[must_use]` attribute cannot be used on modules
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:741:17
@ -1197,7 +1197,7 @@ LL | mod inner { #![must_use] }
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
warning: `#[must_use]` attribute cannot be used on type aliases
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:750:5
@ -1206,7 +1206,7 @@ LL | #[must_use] type T = S;
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
warning: `#[must_use]` attribute cannot be used on inherent impl blocks
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:755:5
@ -1215,7 +1215,7 @@ LL | #[must_use] impl S { }
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
warning: `#[should_panic]` attribute cannot be used on crates
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:50:1
@ -1260,7 +1260,7 @@ LL | #![link_name = "1900"]
| ^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_name]` can be applied to foreign functions, foreign statics
= help: `#[link_name]` can be applied to foreign functions and foreign statics
warning: `#[link_section]` attribute cannot be used on crates
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:79:1
@ -1269,7 +1269,7 @@ LL | #![link_section = "1800"]
| ^^^^^^^^^^^^^^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[link_section]` can be applied to statics, functions
= help: `#[link_section]` can be applied to statics and functions
warning: `#[must_use]` attribute cannot be used on crates
--> $DIR/issue-43106-gating-of-builtin-attrs.rs:84:1
@ -1278,7 +1278,7 @@ LL | #![must_use]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
warning: 173 warnings emitted

View File

@ -4,7 +4,7 @@ error: `#[link_ordinal]` attribute cannot be used on structs
LL | #[link_ordinal(123)]
| ^^^^^^^^^^^^^^^^^^^^
|
= help: `#[link_ordinal]` can be applied to foreign functions, foreign statics
= help: `#[link_ordinal]` can be applied to foreign functions and foreign statics
error: `#[link_ordinal]` attribute cannot be used on functions
--> $DIR/link-ordinal-not-foreign-fn.rs:5:1
@ -12,7 +12,7 @@ error: `#[link_ordinal]` attribute cannot be used on functions
LL | #[link_ordinal(123)]
| ^^^^^^^^^^^^^^^^^^^^
|
= help: `#[link_ordinal]` can be applied to foreign functions, foreign statics
= help: `#[link_ordinal]` can be applied to foreign functions and foreign statics
error: `#[link_ordinal]` attribute cannot be used on statics
--> $DIR/link-ordinal-not-foreign-fn.rs:9:1
@ -20,7 +20,7 @@ error: `#[link_ordinal]` attribute cannot be used on statics
LL | #[link_ordinal(42)]
| ^^^^^^^^^^^^^^^^^^^
|
= help: `#[link_ordinal]` can be applied to foreign functions, foreign statics
= help: `#[link_ordinal]` can be applied to foreign functions and foreign statics
error: aborting due to 3 previous errors

View File

@ -0,0 +1,11 @@
//@ check-pass
//@ compile-flags: -Zunstable-options
// Make sure we don't try to resolve instances for trait refs that have escaping
// bound vars when computing the query instability lint.
fn foo<T>() where for<'a> &'a [T]: IntoIterator<Item = &'a T> {}
fn main() {
foo::<()>();
}

View File

@ -17,7 +17,7 @@ LL | #[macro_use]
| ^^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[macro_use]` can be applied to modules, extern crates, crates
= help: `#[macro_use]` can be applied to modules, extern crates, and crates
error: `#[path]` attribute cannot be used on macro defs
--> $DIR/unused-attr-macro-rules.rs:9:1

View File

@ -22,7 +22,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on modules
--> $DIR/unused_attributes-must_use.rs:11:1
@ -31,7 +31,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on use statements
--> $DIR/unused_attributes-must_use.rs:15:1
@ -40,7 +40,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on constants
--> $DIR/unused_attributes-must_use.rs:19:1
@ -49,7 +49,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on statics
--> $DIR/unused_attributes-must_use.rs:22:1
@ -58,7 +58,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on inherent impl blocks
--> $DIR/unused_attributes-must_use.rs:40:1
@ -67,7 +67,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on foreign modules
--> $DIR/unused_attributes-must_use.rs:55:1
@ -76,7 +76,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on foreign statics
--> $DIR/unused_attributes-must_use.rs:59:5
@ -85,7 +85,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on type aliases
--> $DIR/unused_attributes-must_use.rs:71:1
@ -94,7 +94,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on function params
--> $DIR/unused_attributes-must_use.rs:75:8
@ -103,7 +103,7 @@ LL | fn qux<#[must_use] T>(_: T) {}
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on associated consts
--> $DIR/unused_attributes-must_use.rs:80:5
@ -112,7 +112,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on associated types
--> $DIR/unused_attributes-must_use.rs:83:5
@ -121,7 +121,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on trait impl blocks
--> $DIR/unused_attributes-must_use.rs:93:1
@ -130,7 +130,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on trait methods in impl blocks
--> $DIR/unused_attributes-must_use.rs:98:5
@ -139,7 +139,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to data types, functions, unions, required trait methods, provided trait methods, inherent methods, foreign functions, traits
= help: `#[must_use]` can be applied to data types, functions, unions, required trait methods, provided trait methods, inherent methods, foreign functions, and traits
error: `#[must_use]` attribute cannot be used on trait aliases
--> $DIR/unused_attributes-must_use.rs:105:1
@ -148,7 +148,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on macro defs
--> $DIR/unused_attributes-must_use.rs:109:1
@ -157,7 +157,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on statements
--> $DIR/unused_attributes-must_use.rs:118:5
@ -166,7 +166,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on closures
--> $DIR/unused_attributes-must_use.rs:123:13
@ -175,7 +175,7 @@ LL | let x = #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to methods, data types, functions, unions, foreign functions, traits
= help: `#[must_use]` can be applied to methods, data types, functions, unions, foreign functions, and traits
error: `#[must_use]` attribute cannot be used on match arms
--> $DIR/unused_attributes-must_use.rs:146:9
@ -184,7 +184,7 @@ LL | #[must_use]
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on struct fields
--> $DIR/unused_attributes-must_use.rs:155:28
@ -193,7 +193,7 @@ LL | let s = PatternField { #[must_use] foo: 123 };
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: `#[must_use]` attribute cannot be used on pattern fields
--> $DIR/unused_attributes-must_use.rs:157:24
@ -202,7 +202,7 @@ LL | let PatternField { #[must_use] foo } = s;
| ^^^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[must_use]` can be applied to functions, data types, unions, traits
= help: `#[must_use]` can be applied to functions, data types, unions, and traits
error: unused `X` that must be used
--> $DIR/unused_attributes-must_use.rs:128:5

View File

@ -5,7 +5,7 @@ LL | #[inline]
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[inline]` can be applied to functions, inherent methods, provided trait methods, trait methods in impl blocks, closures
= help: `#[inline]` can be applied to functions, inherent methods, provided trait methods, trait methods in impl blocks, and closures
note: the lint level is defined here
--> $DIR/warn-unused-inline-on-fn-prototypes.rs:1:9
|
@ -19,7 +19,7 @@ LL | #[inline]
| ^^^^^^^^^
|
= warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
= help: `#[inline]` can be applied to methods, functions, closures
= help: `#[inline]` can be applied to methods, functions, and closures
error: aborting due to 2 previous errors

View File

@ -4,7 +4,7 @@ error: `#[target_feature]` attribute cannot be used on closures
LL | #[target_feature(enable = "")]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
= help: `#[target_feature]` can be applied to methods, functions
= help: `#[target_feature]` can be applied to methods and functions
error[E0658]: `#[track_caller]` on closures is currently unstable
--> $DIR/issue-68060.rs:6:13

View File

@ -13,7 +13,7 @@ error: `#[non_exhaustive]` attribute cannot be used on traits
LL | #[non_exhaustive]
| ^^^^^^^^^^^^^^^^^
|
= help: `#[non_exhaustive]` can be applied to data types, enum variants
= help: `#[non_exhaustive]` can be applied to data types and enum variants
error: `#[non_exhaustive]` attribute cannot be used on unions
--> $DIR/invalid-attribute.rs:9:1
@ -21,7 +21,7 @@ error: `#[non_exhaustive]` attribute cannot be used on unions
LL | #[non_exhaustive]
| ^^^^^^^^^^^^^^^^^
|
= help: `#[non_exhaustive]` can be applied to data types, enum variants
= help: `#[non_exhaustive]` can be applied to data types and enum variants
error: aborting due to 3 previous errors

View File

@ -1,4 +1,5 @@
fn main() {
static || {};
//~^ ERROR closures cannot be static
//~| ERROR coroutine syntax is experimental
}

Some files were not shown because too many files have changed in this diff Show More