mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-21 14:23:45 +00:00
Auto merge of #132954 - matthiaskrgr:rollup-x3rww9h, r=matthiaskrgr
Rollup of 7 pull requests Successful merges: - #131831 (extend the "if-unchanged" logic for compiler builds) - #132541 (Proper support for cross-crate recursive const stability checks) - #132657 (AIX: add run-make support) - #132901 (Warn about invalid `mir-enable-passes` pass names) - #132923 (Triagebot: Consolidate the T-compiler ad hoc assignment groups) - #132938 (Make precise capturing suggestion machine-applicable only if it has no APITs) - #132947 (clarify `must_produce_diag` ICE for debugging) r? `@ghost` `@rustbot` modify labels: rollup
This commit is contained in:
commit
f7273e0044
@ -2,12 +2,12 @@
|
||||
resolver = "2"
|
||||
members = [
|
||||
"compiler/rustc",
|
||||
"src/build_helper",
|
||||
"src/etc/test-float-parse",
|
||||
"src/rustc-std-workspace/rustc-std-workspace-core",
|
||||
"src/rustc-std-workspace/rustc-std-workspace-alloc",
|
||||
"src/rustc-std-workspace/rustc-std-workspace-std",
|
||||
"src/rustdoc-json-types",
|
||||
"src/tools/build_helper",
|
||||
"src/tools/cargotest",
|
||||
"src/tools/clippy",
|
||||
"src/tools/clippy/clippy_dev",
|
||||
|
@ -16,9 +16,9 @@ use rustc_session::lint::BuiltinLintDiag;
|
||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||
use rustc_session::parse::feature_err;
|
||||
use rustc_session::{RustcVersion, Session};
|
||||
use rustc_span::Span;
|
||||
use rustc_span::hygiene::Transparency;
|
||||
use rustc_span::symbol::{Symbol, kw, sym};
|
||||
use rustc_span::{DUMMY_SP, Span};
|
||||
|
||||
use crate::fluent_generated;
|
||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||
@ -92,9 +92,7 @@ impl Stability {
|
||||
#[derive(HashStable_Generic)]
|
||||
pub struct ConstStability {
|
||||
pub level: StabilityLevel,
|
||||
/// This can be `None` for functions that do not have an explicit const feature.
|
||||
/// We still track them for recursive const stability checks.
|
||||
pub feature: Option<Symbol>,
|
||||
pub feature: Symbol,
|
||||
/// This is true iff the `const_stable_indirect` attribute is present.
|
||||
pub const_stable_indirect: bool,
|
||||
/// whether the function has a `#[rustc_promotable]` attribute
|
||||
@ -272,22 +270,19 @@ pub fn find_stability(
|
||||
|
||||
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
|
||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
||||
///
|
||||
/// `is_const_fn` indicates whether this is a function marked as `const`.
|
||||
pub fn find_const_stability(
|
||||
sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
item_sp: Span,
|
||||
is_const_fn: bool,
|
||||
) -> Option<(ConstStability, Span)> {
|
||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||
let mut promotable = false;
|
||||
let mut const_stable_indirect = None;
|
||||
let mut const_stable_indirect = false;
|
||||
|
||||
for attr in attrs {
|
||||
match attr.name_or_empty() {
|
||||
sym::rustc_promotable => promotable = true,
|
||||
sym::rustc_const_stable_indirect => const_stable_indirect = Some(attr.span),
|
||||
sym::rustc_const_stable_indirect => const_stable_indirect = true,
|
||||
sym::rustc_const_unstable => {
|
||||
if const_stab.is_some() {
|
||||
sess.dcx()
|
||||
@ -299,7 +294,7 @@ pub fn find_const_stability(
|
||||
const_stab = Some((
|
||||
ConstStability {
|
||||
level,
|
||||
feature: Some(feature),
|
||||
feature,
|
||||
const_stable_indirect: false,
|
||||
promotable: false,
|
||||
},
|
||||
@ -317,7 +312,7 @@ pub fn find_const_stability(
|
||||
const_stab = Some((
|
||||
ConstStability {
|
||||
level,
|
||||
feature: Some(feature),
|
||||
feature,
|
||||
const_stable_indirect: false,
|
||||
promotable: false,
|
||||
},
|
||||
@ -340,7 +335,7 @@ pub fn find_const_stability(
|
||||
}
|
||||
}
|
||||
}
|
||||
if const_stable_indirect.is_some() {
|
||||
if const_stable_indirect {
|
||||
match &mut const_stab {
|
||||
Some((stab, _)) => {
|
||||
if stab.is_const_unstable() {
|
||||
@ -351,36 +346,37 @@ pub fn find_const_stability(
|
||||
})
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
_ => {
|
||||
// This function has no const stability attribute, but has `const_stable_indirect`.
|
||||
// We ignore that; unmarked functions are subject to recursive const stability
|
||||
// checks by default so we do carry out the user's intent.
|
||||
}
|
||||
}
|
||||
}
|
||||
// Make sure if `const_stable_indirect` is present, that is recorded. Also make sure all `const
|
||||
// fn` get *some* marker, since we are a staged_api crate and therefore will do recursive const
|
||||
// stability checks for them. We need to do this because the default for whether an unmarked
|
||||
// function enforces recursive stability differs between staged-api crates and force-unmarked
|
||||
// crates: in force-unmarked crates, only functions *explicitly* marked `const_stable_indirect`
|
||||
// enforce recursive stability. Therefore when `lookup_const_stability` is `None`, we have to
|
||||
// assume the function does not have recursive stability. All functions that *do* have recursive
|
||||
// stability must explicitly record this, and so that's what we do for all `const fn` in a
|
||||
// staged_api crate.
|
||||
if (is_const_fn || const_stable_indirect.is_some()) && const_stab.is_none() {
|
||||
let c = ConstStability {
|
||||
feature: None,
|
||||
const_stable_indirect: const_stable_indirect.is_some(),
|
||||
promotable: false,
|
||||
level: StabilityLevel::Unstable {
|
||||
reason: UnstableReason::Default,
|
||||
issue: None,
|
||||
is_soft: false,
|
||||
implied_by: None,
|
||||
},
|
||||
};
|
||||
const_stab = Some((c, const_stable_indirect.unwrap_or(DUMMY_SP)));
|
||||
}
|
||||
|
||||
const_stab
|
||||
}
|
||||
|
||||
/// Calculates the const stability for a const function in a `-Zforce-unstable-if-unmarked` crate
|
||||
/// without the `staged_api` feature.
|
||||
pub fn unmarked_crate_const_stab(
|
||||
_sess: &Session,
|
||||
attrs: &[Attribute],
|
||||
regular_stab: Stability,
|
||||
) -> ConstStability {
|
||||
assert!(regular_stab.level.is_unstable());
|
||||
// The only attribute that matters here is `rustc_const_stable_indirect`.
|
||||
// We enforce recursive const stability rules for those functions.
|
||||
let const_stable_indirect =
|
||||
attrs.iter().any(|a| a.name_or_empty() == sym::rustc_const_stable_indirect);
|
||||
ConstStability {
|
||||
feature: regular_stab.feature,
|
||||
const_stable_indirect,
|
||||
promotable: false,
|
||||
level: regular_stab.level,
|
||||
}
|
||||
}
|
||||
|
||||
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
|
||||
/// Returns `None` if no stability attributes are found.
|
||||
pub fn find_body_stability(
|
||||
|
@ -3,6 +3,7 @@
|
||||
use std::assert_matches::assert_matches;
|
||||
use std::borrow::Cow;
|
||||
use std::mem;
|
||||
use std::num::NonZero;
|
||||
use std::ops::Deref;
|
||||
|
||||
use rustc_attr::{ConstStability, StabilityLevel};
|
||||
@ -709,6 +710,13 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
|
||||
// Intrinsics are language primitives, not regular calls, so treat them separately.
|
||||
if let Some(intrinsic) = tcx.intrinsic(callee) {
|
||||
if !tcx.is_const_fn(callee) {
|
||||
// Non-const intrinsic.
|
||||
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
|
||||
// If we allowed this, we're in miri-unleashed mode, so we might
|
||||
// as well skip the remaining checks.
|
||||
return;
|
||||
}
|
||||
// We use `intrinsic.const_stable` to determine if this can be safely exposed to
|
||||
// stable code, rather than `const_stable_indirect`. This is to make
|
||||
// `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
|
||||
@ -716,17 +724,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
// fallback body is safe to expose on stable.
|
||||
let is_const_stable = intrinsic.const_stable
|
||||
|| (!intrinsic.must_be_overridden
|
||||
&& tcx.is_const_fn(callee)
|
||||
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
|
||||
match tcx.lookup_const_stability(callee) {
|
||||
None => {
|
||||
// Non-const intrinsic.
|
||||
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
|
||||
}
|
||||
Some(ConstStability { feature: None, .. }) => {
|
||||
// Intrinsic does not need a separate feature gate (we rely on the
|
||||
// regular stability checker). However, we have to worry about recursive
|
||||
// const stability.
|
||||
// This doesn't need a separate const-stability check -- const-stability equals
|
||||
// regular stability, and regular stability is checked separately.
|
||||
// However, we *do* have to worry about *recursive* const stability.
|
||||
if !is_const_stable && self.enforce_recursive_const_stability() {
|
||||
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
|
||||
span: self.span,
|
||||
@ -735,8 +738,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
Some(ConstStability {
|
||||
feature: Some(feature),
|
||||
level: StabilityLevel::Unstable { .. },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
self.check_op(ops::IntrinsicUnstable {
|
||||
@ -773,7 +776,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
||||
// All good.
|
||||
}
|
||||
None | Some(ConstStability { feature: None, .. }) => {
|
||||
None => {
|
||||
// This doesn't need a separate const-stability check -- const-stability equals
|
||||
// regular stability, and regular stability is checked separately.
|
||||
// However, we *do* have to worry about *recursive* const stability.
|
||||
@ -787,8 +790,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
}
|
||||
}
|
||||
Some(ConstStability {
|
||||
feature: Some(feature),
|
||||
level: StabilityLevel::Unstable { implied_by: implied_feature, .. },
|
||||
level: StabilityLevel::Unstable { implied_by: implied_feature, issue, .. },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
// An unstable const fn with a feature gate.
|
||||
@ -810,7 +813,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
||||
// to allow this.
|
||||
let feature_enabled = callee.is_local()
|
||||
|| tcx.features().enabled(feature)
|
||||
|| implied_feature.is_some_and(|f| tcx.features().enabled(f));
|
||||
|| implied_feature.is_some_and(|f| tcx.features().enabled(f))
|
||||
|| {
|
||||
// When we're compiling the compiler itself we may pull in
|
||||
// crates from crates.io, but those crates may depend on other
|
||||
// crates also pulled in from crates.io. We want to ideally be
|
||||
// able to compile everything without requiring upstream
|
||||
// modifications, so in the case that this looks like a
|
||||
// `rustc_private` crate (e.g., a compiler crate) and we also have
|
||||
// the `-Z force-unstable-if-unmarked` flag present (we're
|
||||
// compiling a compiler crate), then let this missing feature
|
||||
// annotation slide.
|
||||
// This matches what we do in `eval_stability_allow_unstable` for
|
||||
// regular stability.
|
||||
feature == sym::rustc_private
|
||||
&& issue == NonZero::new(27812)
|
||||
&& self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked
|
||||
};
|
||||
// We do *not* honor this if we are in the "danger zone": we have to enforce
|
||||
// recursive const-stability and the callee is not safe-to-expose. In that
|
||||
// case we need `check_op` to do the check.
|
||||
|
@ -53,10 +53,11 @@ impl<'mir, 'tcx> ConstCx<'mir, 'tcx> {
|
||||
}
|
||||
|
||||
pub fn enforce_recursive_const_stability(&self) -> bool {
|
||||
// We can skip this if `staged_api` is not enabled, since in such crates
|
||||
// `lookup_const_stability` will always be `None`.
|
||||
// We can skip this if neither `staged_api` nor `-Zforce-unstable-if-unmarked` are enabled,
|
||||
// since in such crates `lookup_const_stability` will always be `None`.
|
||||
self.const_kind == Some(hir::ConstContext::ConstFn)
|
||||
&& self.tcx.features().staged_api()
|
||||
&& (self.tcx.features().staged_api()
|
||||
|| self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked)
|
||||
&& is_safe_to_expose_on_stable_const_fn(self.tcx, self.def_id().to_def_id())
|
||||
}
|
||||
|
||||
@ -109,14 +110,15 @@ pub fn is_safe_to_expose_on_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> b
|
||||
|
||||
match tcx.lookup_const_stability(def_id) {
|
||||
None => {
|
||||
// Only marked functions can be trusted. Note that this may be a function in a
|
||||
// non-staged-API crate where no recursive checks were done!
|
||||
false
|
||||
// In a `staged_api` crate, we do enforce recursive const stability for all unmarked
|
||||
// functions, so we can trust local functions. But in another crate we don't know which
|
||||
// rules were applied, so we can't trust that.
|
||||
def_id.is_local() && tcx.features().staged_api()
|
||||
}
|
||||
Some(stab) => {
|
||||
// We consider things safe-to-expose if they are stable, if they don't have any explicit
|
||||
// const stability attribute, or if they are marked as `const_stable_indirect`.
|
||||
stab.is_const_stable() || stab.feature.is_none() || stab.const_stable_indirect
|
||||
// We consider things safe-to-expose if they are stable or if they are marked as
|
||||
// `const_stable_indirect`.
|
||||
stab.is_const_stable() || stab.const_stable_indirect
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -623,12 +623,25 @@ impl Drop for DiagCtxtInner {
|
||||
self.flush_delayed()
|
||||
}
|
||||
|
||||
// Sanity check: did we use some of the expensive `trimmed_def_paths` functions
|
||||
// unexpectedly, that is, without producing diagnostics? If so, for debugging purposes, we
|
||||
// suggest where this happened and how to avoid it.
|
||||
if !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
|
||||
if let Some(backtrace) = &self.must_produce_diag {
|
||||
let suggestion = match backtrace.status() {
|
||||
BacktraceStatus::Disabled => String::from(
|
||||
"Backtraces are currently disabled: set `RUST_BACKTRACE=1` and re-run \
|
||||
to see where it happened.",
|
||||
),
|
||||
BacktraceStatus::Captured => format!(
|
||||
"This happened in the following `must_produce_diag` call's backtrace:\n\
|
||||
{backtrace}",
|
||||
),
|
||||
_ => String::from("(impossible to capture backtrace where this happened)"),
|
||||
};
|
||||
panic!(
|
||||
"must_produce_diag: `trimmed_def_paths` called but no diagnostics emitted; \
|
||||
`with_no_trimmed_paths` for debugging. \
|
||||
called at: {backtrace}"
|
||||
"`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
|
||||
Use `with_no_trimmed_paths` for debugging. {suggestion}"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -866,9 +866,7 @@ impl SyntaxExtension {
|
||||
})
|
||||
.unwrap_or_else(|| (None, helper_attrs));
|
||||
let stability = attr::find_stability(sess, attrs, span);
|
||||
// We set `is_const_fn` false to avoid getting any implicit const stability.
|
||||
let const_stability =
|
||||
attr::find_const_stability(sess, attrs, span, /* is_const_fn */ false);
|
||||
let const_stability = attr::find_const_stability(sess, attrs, span);
|
||||
let body_stability = attr::find_body_stability(sess, attrs);
|
||||
if let Some((_, sp)) = const_stability {
|
||||
sess.dcx().emit_err(errors::MacroConstStability {
|
||||
|
@ -34,3 +34,5 @@ mir_transform_undefined_transmute = pointers cannot be transmuted to integers du
|
||||
.note = at compile-time, pointers do not have an integer value
|
||||
.note2 = avoiding this restriction via `union` or raw pointers leads to compile-time undefined behavior
|
||||
.help = for more information, see https://doc.rust-lang.org/std/mem/fn.transmute.html
|
||||
|
||||
mir_transform_unknown_pass_name = MIR pass `{$name}` is unknown and will be ignored
|
||||
|
@ -38,6 +38,12 @@ pub(crate) struct UnalignedPackedRef {
|
||||
pub span: Span,
|
||||
}
|
||||
|
||||
#[derive(Diagnostic)]
|
||||
#[diag(mir_transform_unknown_pass_name)]
|
||||
pub(crate) struct UnknownPassName<'a> {
|
||||
pub(crate) name: &'a str,
|
||||
}
|
||||
|
||||
pub(crate) struct AssertLint<P> {
|
||||
pub span: Span,
|
||||
pub assert_kind: AssertKind<P>,
|
||||
|
@ -40,77 +40,158 @@ use tracing::{debug, trace};
|
||||
#[macro_use]
|
||||
mod pass_manager;
|
||||
|
||||
use std::sync::LazyLock;
|
||||
|
||||
use pass_manager::{self as pm, Lint, MirLint, MirPass, WithMinOptLevel};
|
||||
|
||||
mod abort_unwinding_calls;
|
||||
mod add_call_guards;
|
||||
mod add_moves_for_packed_drops;
|
||||
mod add_retag;
|
||||
mod add_subtyping_projections;
|
||||
mod check_alignment;
|
||||
mod check_const_item_mutation;
|
||||
mod check_packed_ref;
|
||||
mod check_undefined_transmutes;
|
||||
// This pass is public to allow external drivers to perform MIR cleanup
|
||||
pub mod cleanup_post_borrowck;
|
||||
mod copy_prop;
|
||||
mod coroutine;
|
||||
mod cost_checker;
|
||||
mod coverage;
|
||||
mod cross_crate_inline;
|
||||
mod ctfe_limit;
|
||||
mod dataflow_const_prop;
|
||||
mod dead_store_elimination;
|
||||
mod deduce_param_attrs;
|
||||
mod deduplicate_blocks;
|
||||
mod deref_separator;
|
||||
mod dest_prop;
|
||||
pub mod dump_mir;
|
||||
mod early_otherwise_branch;
|
||||
mod elaborate_box_derefs;
|
||||
mod elaborate_drops;
|
||||
mod errors;
|
||||
mod ffi_unwind_calls;
|
||||
mod function_item_references;
|
||||
mod gvn;
|
||||
// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
|
||||
// by custom rustc drivers, running all the steps by themselves. See #114628.
|
||||
pub mod inline;
|
||||
mod instsimplify;
|
||||
mod jump_threading;
|
||||
mod known_panics_lint;
|
||||
mod large_enums;
|
||||
mod lint;
|
||||
mod lower_intrinsics;
|
||||
mod lower_slice_len;
|
||||
mod match_branches;
|
||||
mod mentioned_items;
|
||||
mod multiple_return_terminators;
|
||||
mod nrvo;
|
||||
mod post_drop_elaboration;
|
||||
mod prettify;
|
||||
mod promote_consts;
|
||||
mod ref_prop;
|
||||
mod remove_noop_landing_pads;
|
||||
mod remove_place_mention;
|
||||
mod remove_storage_markers;
|
||||
mod remove_uninit_drops;
|
||||
mod remove_unneeded_drops;
|
||||
mod remove_zsts;
|
||||
mod required_consts;
|
||||
mod reveal_all;
|
||||
mod sanity_check;
|
||||
mod shim;
|
||||
mod ssa;
|
||||
// This pass is public to allow external drivers to perform MIR cleanup
|
||||
pub mod simplify;
|
||||
mod simplify_branches;
|
||||
mod simplify_comparison_integral;
|
||||
mod single_use_consts;
|
||||
mod sroa;
|
||||
mod unreachable_enum_branching;
|
||||
mod unreachable_prop;
|
||||
mod validate;
|
||||
|
||||
/// We import passes via this macro so that we can have a static list of pass names
|
||||
/// (used to verify CLI arguments). It takes a list of modules, followed by the passes
|
||||
/// declared within them.
|
||||
/// ```ignore,macro-test
|
||||
/// declare_passes! {
|
||||
/// // Declare a single pass from the module `abort_unwinding_calls`
|
||||
/// mod abort_unwinding_calls : AbortUnwindingCalls;
|
||||
/// // When passes are grouped together as an enum, declare the two constituent passes
|
||||
/// mod add_call_guards : AddCallGuards {
|
||||
/// AllCallEdges,
|
||||
/// CriticalCallEdges
|
||||
/// };
|
||||
/// // Declares multiple pass groups, each containing their own constituent passes
|
||||
/// mod simplify : SimplifyCfg {
|
||||
/// Initial,
|
||||
/// /* omitted */
|
||||
/// }, SimplifyLocals {
|
||||
/// BeforeConstProp,
|
||||
/// /* omitted */
|
||||
/// };
|
||||
/// }
|
||||
/// ```
|
||||
macro_rules! declare_passes {
|
||||
(
|
||||
$(
|
||||
$vis:vis mod $mod_name:ident : $($pass_name:ident $( { $($ident:ident),* } )?),+ $(,)?;
|
||||
)*
|
||||
) => {
|
||||
$(
|
||||
$vis mod $mod_name;
|
||||
$(
|
||||
// Make sure the type name is correct
|
||||
#[allow(unused_imports)]
|
||||
use $mod_name::$pass_name as _;
|
||||
)+
|
||||
)*
|
||||
|
||||
static PASS_NAMES: LazyLock<FxIndexSet<&str>> = LazyLock::new(|| [
|
||||
// Fake marker pass
|
||||
"PreCodegen",
|
||||
$(
|
||||
$(
|
||||
stringify!($pass_name),
|
||||
$(
|
||||
$(
|
||||
$mod_name::$pass_name::$ident.name(),
|
||||
)*
|
||||
)?
|
||||
)+
|
||||
)*
|
||||
].into_iter().collect());
|
||||
};
|
||||
}
|
||||
|
||||
declare_passes! {
|
||||
mod abort_unwinding_calls : AbortUnwindingCalls;
|
||||
mod add_call_guards : AddCallGuards { AllCallEdges, CriticalCallEdges };
|
||||
mod add_moves_for_packed_drops : AddMovesForPackedDrops;
|
||||
mod add_retag : AddRetag;
|
||||
mod add_subtyping_projections : Subtyper;
|
||||
mod check_alignment : CheckAlignment;
|
||||
mod check_const_item_mutation : CheckConstItemMutation;
|
||||
mod check_packed_ref : CheckPackedRef;
|
||||
mod check_undefined_transmutes : CheckUndefinedTransmutes;
|
||||
// This pass is public to allow external drivers to perform MIR cleanup
|
||||
pub mod cleanup_post_borrowck : CleanupPostBorrowck;
|
||||
|
||||
mod copy_prop : CopyProp;
|
||||
mod coroutine : StateTransform;
|
||||
mod coverage : InstrumentCoverage;
|
||||
mod ctfe_limit : CtfeLimit;
|
||||
mod dataflow_const_prop : DataflowConstProp;
|
||||
mod dead_store_elimination : DeadStoreElimination {
|
||||
Initial,
|
||||
Final
|
||||
};
|
||||
mod deduplicate_blocks : DeduplicateBlocks;
|
||||
mod deref_separator : Derefer;
|
||||
mod dest_prop : DestinationPropagation;
|
||||
pub mod dump_mir : Marker;
|
||||
mod early_otherwise_branch : EarlyOtherwiseBranch;
|
||||
mod elaborate_box_derefs : ElaborateBoxDerefs;
|
||||
mod elaborate_drops : ElaborateDrops;
|
||||
mod function_item_references : FunctionItemReferences;
|
||||
mod gvn : GVN;
|
||||
// Made public so that `mir_drops_elaborated_and_const_checked` can be overridden
|
||||
// by custom rustc drivers, running all the steps by themselves. See #114628.
|
||||
pub mod inline : Inline;
|
||||
mod instsimplify : InstSimplify { BeforeInline, AfterSimplifyCfg };
|
||||
mod jump_threading : JumpThreading;
|
||||
mod known_panics_lint : KnownPanicsLint;
|
||||
mod large_enums : EnumSizeOpt;
|
||||
mod lower_intrinsics : LowerIntrinsics;
|
||||
mod lower_slice_len : LowerSliceLenCalls;
|
||||
mod match_branches : MatchBranchSimplification;
|
||||
mod mentioned_items : MentionedItems;
|
||||
mod multiple_return_terminators : MultipleReturnTerminators;
|
||||
mod nrvo : RenameReturnPlace;
|
||||
mod post_drop_elaboration : CheckLiveDrops;
|
||||
mod prettify : ReorderBasicBlocks, ReorderLocals;
|
||||
mod promote_consts : PromoteTemps;
|
||||
mod ref_prop : ReferencePropagation;
|
||||
mod remove_noop_landing_pads : RemoveNoopLandingPads;
|
||||
mod remove_place_mention : RemovePlaceMention;
|
||||
mod remove_storage_markers : RemoveStorageMarkers;
|
||||
mod remove_uninit_drops : RemoveUninitDrops;
|
||||
mod remove_unneeded_drops : RemoveUnneededDrops;
|
||||
mod remove_zsts : RemoveZsts;
|
||||
mod required_consts : RequiredConstsVisitor;
|
||||
mod reveal_all : RevealAll;
|
||||
mod sanity_check : SanityCheck;
|
||||
// This pass is public to allow external drivers to perform MIR cleanup
|
||||
pub mod simplify :
|
||||
SimplifyCfg {
|
||||
Initial,
|
||||
PromoteConsts,
|
||||
RemoveFalseEdges,
|
||||
PostAnalysis,
|
||||
PreOptimizations,
|
||||
Final,
|
||||
MakeShim,
|
||||
AfterUnreachableEnumBranching
|
||||
},
|
||||
SimplifyLocals {
|
||||
BeforeConstProp,
|
||||
AfterGVN,
|
||||
Final
|
||||
};
|
||||
mod simplify_branches : SimplifyConstCondition {
|
||||
AfterConstProp,
|
||||
Final
|
||||
};
|
||||
mod simplify_comparison_integral : SimplifyComparisonIntegral;
|
||||
mod single_use_consts : SingleUseConsts;
|
||||
mod sroa : ScalarReplacementOfAggregates;
|
||||
mod unreachable_enum_branching : UnreachableEnumBranching;
|
||||
mod unreachable_prop : UnreachablePropagation;
|
||||
mod validate : Validator;
|
||||
}
|
||||
|
||||
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||
|
||||
|
@ -1,24 +1,25 @@
|
||||
use std::cell::RefCell;
|
||||
use std::collections::hash_map::Entry;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
|
||||
use rustc_middle::mir::{self, Body, MirPhase, RuntimePhase};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use tracing::trace;
|
||||
|
||||
use crate::lint::lint_body;
|
||||
use crate::validate;
|
||||
use crate::{errors, validate};
|
||||
|
||||
thread_local! {
|
||||
static PASS_NAMES: RefCell<FxHashMap<&'static str, &'static str>> = {
|
||||
/// Maps MIR pass names to a snake case form to match profiling naming style
|
||||
static PASS_TO_PROFILER_NAMES: RefCell<FxHashMap<&'static str, &'static str>> = {
|
||||
RefCell::new(FxHashMap::default())
|
||||
};
|
||||
}
|
||||
|
||||
/// Converts a MIR pass name into a snake case form to match the profiling naming style.
|
||||
fn to_profiler_name(type_name: &'static str) -> &'static str {
|
||||
PASS_NAMES.with(|names| match names.borrow_mut().entry(type_name) {
|
||||
PASS_TO_PROFILER_NAMES.with(|names| match names.borrow_mut().entry(type_name) {
|
||||
Entry::Occupied(e) => *e.get(),
|
||||
Entry::Vacant(e) => {
|
||||
let snake_case: String = type_name
|
||||
@ -198,6 +199,31 @@ fn run_passes_inner<'tcx>(
|
||||
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
|
||||
trace!(?overridden_passes);
|
||||
|
||||
let named_passes: FxIndexSet<_> =
|
||||
overridden_passes.iter().map(|(name, _)| name.as_str()).collect();
|
||||
|
||||
for &name in named_passes.difference(&*crate::PASS_NAMES) {
|
||||
tcx.dcx().emit_warn(errors::UnknownPassName { name });
|
||||
}
|
||||
|
||||
// Verify that no passes are missing from the `declare_passes` invocation
|
||||
#[cfg(debug_assertions)]
|
||||
#[allow(rustc::diagnostic_outside_of_impl)]
|
||||
#[allow(rustc::untranslatable_diagnostic)]
|
||||
{
|
||||
let used_passes: FxIndexSet<_> = passes.iter().map(|p| p.name()).collect();
|
||||
|
||||
let undeclared = used_passes.difference(&*crate::PASS_NAMES).collect::<Vec<_>>();
|
||||
if let Some((name, rest)) = undeclared.split_first() {
|
||||
let mut err =
|
||||
tcx.dcx().struct_bug(format!("pass `{name}` is not declared in `PASS_NAMES`"));
|
||||
for name in rest {
|
||||
err.note(format!("pass `{name}` is also not declared in `PASS_NAMES`"));
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
||||
let prof_arg = tcx.sess.prof.enabled().then(|| format!("{:?}", body.source.def_id()));
|
||||
|
||||
if !body.should_skip() {
|
||||
|
@ -16,7 +16,7 @@ use rustc_hir::def::{DefKind, Res};
|
||||
use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
|
||||
use rustc_hir::hir_id::CRATE_HIR_ID;
|
||||
use rustc_hir::intravisit::{self, Visitor};
|
||||
use rustc_hir::{Constness, FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
|
||||
use rustc_hir::{FieldDef, Item, ItemKind, TraitRef, Ty, TyKind, Variant};
|
||||
use rustc_middle::hir::nested_filter;
|
||||
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
||||
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
||||
@ -149,6 +149,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
if let Some(stab) = self.parent_stab {
|
||||
if inherit_deprecation.yes() && stab.is_unstable() {
|
||||
self.index.stab_map.insert(def_id, stab);
|
||||
if fn_sig.is_some_and(|s| s.header.is_const()) {
|
||||
let const_stab =
|
||||
attr::unmarked_crate_const_stab(self.tcx.sess, attrs, stab);
|
||||
self.index.const_stab_map.insert(def_id, const_stab);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -161,68 +166,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
return;
|
||||
}
|
||||
|
||||
// # Regular and body stability
|
||||
|
||||
let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
|
||||
let const_stab = attr::find_const_stability(
|
||||
self.tcx.sess,
|
||||
attrs,
|
||||
item_sp,
|
||||
fn_sig.is_some_and(|s| s.header.is_const()),
|
||||
);
|
||||
let body_stab = attr::find_body_stability(self.tcx.sess, attrs);
|
||||
|
||||
// If the current node is a function with const stability attributes (directly given or
|
||||
// implied), check if the function/method is const or the parent impl block is const.
|
||||
if let Some(fn_sig) = fn_sig
|
||||
&& !fn_sig.header.is_const()
|
||||
&& const_stab.is_some()
|
||||
{
|
||||
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
|
||||
}
|
||||
|
||||
// If this is marked const *stable*, it must also be regular-stable.
|
||||
if let Some((const_stab, const_span)) = const_stab
|
||||
&& let Some(fn_sig) = fn_sig
|
||||
&& const_stab.is_const_stable()
|
||||
&& !stab.is_some_and(|(s, _)| s.is_stable())
|
||||
{
|
||||
self.tcx
|
||||
.dcx()
|
||||
.emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
|
||||
}
|
||||
|
||||
// Stable *language* features shouldn't be used as unstable library features.
|
||||
// (Not doing this for stable library features is checked by tidy.)
|
||||
if let Some((
|
||||
ConstStability { level: Unstable { .. }, feature: Some(feature), .. },
|
||||
const_span,
|
||||
)) = const_stab
|
||||
{
|
||||
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
|
||||
self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
|
||||
span: const_span,
|
||||
item_sp,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
let const_stab = const_stab.map(|(const_stab, _span)| {
|
||||
self.index.const_stab_map.insert(def_id, const_stab);
|
||||
const_stab
|
||||
});
|
||||
|
||||
// `impl const Trait for Type` items forward their const stability to their
|
||||
// immediate children.
|
||||
// FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
|
||||
// Currently, once that is set, we do not inherit anything from the parent any more.
|
||||
if const_stab.is_none() {
|
||||
debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
|
||||
if let Some(parent) = self.parent_const_stab {
|
||||
if parent.is_const_unstable() {
|
||||
self.index.const_stab_map.insert(def_id, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if let Some((depr, span)) = &depr
|
||||
&& depr.is_since_rustc_version()
|
||||
&& stab.is_none()
|
||||
@ -289,15 +237,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
self.index.implications.insert(implied_by, feature);
|
||||
}
|
||||
|
||||
if let Some(ConstStability {
|
||||
level: Unstable { implied_by: Some(implied_by), .. },
|
||||
feature,
|
||||
..
|
||||
}) = const_stab
|
||||
{
|
||||
self.index.implications.insert(implied_by, feature.unwrap());
|
||||
}
|
||||
|
||||
self.index.stab_map.insert(def_id, stab);
|
||||
stab
|
||||
});
|
||||
@ -311,6 +250,91 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
let final_stab = self.index.stab_map.get(&def_id);
|
||||
|
||||
// # Const stability
|
||||
|
||||
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item_sp);
|
||||
|
||||
// If the current node is a function with const stability attributes (directly given or
|
||||
// implied), check if the function/method is const.
|
||||
if let Some(fn_sig) = fn_sig
|
||||
&& !fn_sig.header.is_const()
|
||||
&& const_stab.is_some()
|
||||
{
|
||||
self.tcx.dcx().emit_err(errors::MissingConstErr { fn_sig_span: fn_sig.span });
|
||||
}
|
||||
|
||||
// If this is marked const *stable*, it must also be regular-stable.
|
||||
if let Some((const_stab, const_span)) = const_stab
|
||||
&& let Some(fn_sig) = fn_sig
|
||||
&& const_stab.is_const_stable()
|
||||
&& !stab.is_some_and(|s| s.is_stable())
|
||||
{
|
||||
self.tcx
|
||||
.dcx()
|
||||
.emit_err(errors::ConstStableNotStable { fn_sig_span: fn_sig.span, const_span });
|
||||
}
|
||||
|
||||
// Stable *language* features shouldn't be used as unstable library features.
|
||||
// (Not doing this for stable library features is checked by tidy.)
|
||||
if let Some((ConstStability { level: Unstable { .. }, feature, .. }, const_span)) =
|
||||
const_stab
|
||||
{
|
||||
if ACCEPTED_LANG_FEATURES.iter().find(|f| f.name == feature).is_some() {
|
||||
self.tcx.dcx().emit_err(errors::UnstableAttrForAlreadyStableFeature {
|
||||
span: const_span,
|
||||
item_sp,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// After checking the immediate attributes, get rid of the span and compute implied
|
||||
// const stability: inherit feature gate from regular stability.
|
||||
let mut const_stab = const_stab.map(|(stab, _span)| stab);
|
||||
|
||||
// If this is a const fn but not annotated with stability markers, see if we can inherit regular stability.
|
||||
if fn_sig.is_some_and(|s| s.header.is_const()) && const_stab.is_none() &&
|
||||
// We only ever inherit unstable features.
|
||||
let Some(inherit_regular_stab) =
|
||||
final_stab.filter(|s| s.is_unstable())
|
||||
{
|
||||
const_stab = Some(ConstStability {
|
||||
// We subject these implicitly-const functions to recursive const stability.
|
||||
const_stable_indirect: true,
|
||||
promotable: false,
|
||||
level: inherit_regular_stab.level,
|
||||
feature: inherit_regular_stab.feature,
|
||||
});
|
||||
}
|
||||
|
||||
// Now that everything is computed, insert it into the table.
|
||||
const_stab.inspect(|const_stab| {
|
||||
self.index.const_stab_map.insert(def_id, *const_stab);
|
||||
});
|
||||
|
||||
if let Some(ConstStability {
|
||||
level: Unstable { implied_by: Some(implied_by), .. },
|
||||
feature,
|
||||
..
|
||||
}) = const_stab
|
||||
{
|
||||
self.index.implications.insert(implied_by, feature);
|
||||
}
|
||||
|
||||
// `impl const Trait for Type` items forward their const stability to their
|
||||
// immediate children.
|
||||
// FIXME(const_trait_impl): how is this supposed to interact with `#[rustc_const_stable_indirect]`?
|
||||
// Currently, once that is set, we do not inherit anything from the parent any more.
|
||||
if const_stab.is_none() {
|
||||
debug!("annotate: const_stab not found, parent = {:?}", self.parent_const_stab);
|
||||
if let Some(parent) = self.parent_const_stab {
|
||||
if parent.is_const_unstable() {
|
||||
self.index.const_stab_map.insert(def_id, parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
self.recurse_with_stability_attrs(
|
||||
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
|
||||
stab,
|
||||
@ -565,13 +589,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
fn check_missing_or_wrong_const_stability(&self, def_id: LocalDefId, span: Span) {
|
||||
// The visitor runs for "unstable-if-unmarked" crates, but we don't yet support
|
||||
// that on the const side.
|
||||
if !self.tcx.features().staged_api() {
|
||||
return;
|
||||
}
|
||||
|
||||
fn check_missing_const_stability(&self, def_id: LocalDefId, span: Span) {
|
||||
// if the const impl is derived using the `derive_const` attribute,
|
||||
// then it would be "stable" at least for the impl.
|
||||
// We gate usages of it using `feature(const_trait_impl)` anyways
|
||||
@ -582,12 +600,12 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
||||
|
||||
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
|
||||
|| self.tcx.is_const_trait_impl(def_id.to_def_id());
|
||||
let is_stable =
|
||||
self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
|
||||
let missing_const_stability_attribute =
|
||||
self.tcx.lookup_const_stability(def_id).is_none_or(|s| s.feature.is_none());
|
||||
|
||||
if is_const && is_stable && missing_const_stability_attribute {
|
||||
// Reachable const fn must have a stability attribute.
|
||||
if is_const
|
||||
&& self.effective_visibilities.is_reachable(def_id)
|
||||
&& self.tcx.lookup_const_stability(def_id).is_none()
|
||||
{
|
||||
let descr = self.tcx.def_descr(def_id.to_def_id());
|
||||
self.tcx.dcx().emit_err(errors::MissingConstStabAttr { span, descr });
|
||||
}
|
||||
@ -615,7 +633,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
|
||||
}
|
||||
|
||||
// Ensure stable `const fn` have a const stability attribute.
|
||||
self.check_missing_or_wrong_const_stability(i.owner_id.def_id, i.span);
|
||||
self.check_missing_const_stability(i.owner_id.def_id, i.span);
|
||||
|
||||
intravisit::walk_item(self, i)
|
||||
}
|
||||
@ -629,7 +647,7 @@ impl<'tcx> Visitor<'tcx> for MissingStabilityAnnotations<'tcx> {
|
||||
let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id());
|
||||
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
|
||||
self.check_missing_stability(ii.owner_id.def_id, ii.span);
|
||||
self.check_missing_or_wrong_const_stability(ii.owner_id.def_id, ii.span);
|
||||
self.check_missing_const_stability(ii.owner_id.def_id, ii.span);
|
||||
}
|
||||
intravisit::walk_impl_item(self, ii);
|
||||
}
|
||||
@ -760,23 +778,12 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> {
|
||||
// For implementations of traits, check the stability of each item
|
||||
// individually as it's possible to have a stable trait with unstable
|
||||
// items.
|
||||
hir::ItemKind::Impl(hir::Impl {
|
||||
constness,
|
||||
of_trait: Some(ref t),
|
||||
self_ty,
|
||||
items,
|
||||
..
|
||||
}) => {
|
||||
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
|
||||
let features = self.tcx.features();
|
||||
if features.staged_api() {
|
||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
||||
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
|
||||
let const_stab = attr::find_const_stability(
|
||||
self.tcx.sess,
|
||||
attrs,
|
||||
item.span,
|
||||
matches!(constness, Constness::Const),
|
||||
);
|
||||
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
|
||||
|
||||
// If this impl block has an #[unstable] attribute, give an
|
||||
// error if all involved types and traits are stable, because
|
||||
|
@ -1907,10 +1907,18 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture {
|
||||
diag: &mut Diag<'_, G>,
|
||||
_f: &F,
|
||||
) {
|
||||
let applicability = if self.apit_spans.is_empty() {
|
||||
Applicability::MachineApplicable
|
||||
} else {
|
||||
// If there are APIT that are converted to regular parameters,
|
||||
// then this may make the API turbofishable in ways that were
|
||||
// not intended.
|
||||
Applicability::MaybeIncorrect
|
||||
};
|
||||
diag.multipart_suggestion_verbose(
|
||||
fluent::trait_selection_precise_capturing_overcaptures,
|
||||
self.suggs,
|
||||
Applicability::MaybeIncorrect,
|
||||
applicability,
|
||||
);
|
||||
if !self.apit_spans.is_empty() {
|
||||
diag.span_note(
|
||||
|
@ -500,8 +500,9 @@
|
||||
# This is useful if you are working on tools, doc-comments, or library (you will be able to build
|
||||
# the standard library without needing to build the compiler).
|
||||
#
|
||||
# Set this to "if-unchanged" to only download if the compiler (and library if running on CI) have
|
||||
# not been modified.
|
||||
# Set this to "if-unchanged" if you are working on `src/tools`, `tests` or `library` (on CI, `library`
|
||||
# changes triggers in-tree compiler build) to speed up the build process.
|
||||
#
|
||||
# Set this to `true` to download unconditionally.
|
||||
#download-rustc = false
|
||||
|
||||
|
@ -40,7 +40,7 @@ test = false
|
||||
cc = "=1.1.22"
|
||||
cmake = "=0.1.48"
|
||||
|
||||
build_helper = { path = "../tools/build_helper" }
|
||||
build_helper = { path = "../build_helper" }
|
||||
clap = { version = "4.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
|
||||
clap_complete = "4.4"
|
||||
fd-lock = "4.0"
|
||||
|
@ -295,7 +295,7 @@ macro_rules! lint_any {
|
||||
|
||||
lint_any!(
|
||||
Bootstrap, "src/bootstrap", "bootstrap";
|
||||
BuildHelper, "src/tools/build_helper", "build_helper";
|
||||
BuildHelper, "src/build_helper", "build_helper";
|
||||
BuildManifest, "src/tools/build-manifest", "build-manifest";
|
||||
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri";
|
||||
Clippy, "src/tools/clippy", "clippy";
|
||||
|
@ -1030,7 +1030,7 @@ macro_rules! tool_doc {
|
||||
// NOTE: make sure to register these in `Builder::get_step_description`.
|
||||
tool_doc!(
|
||||
BuildHelper,
|
||||
"src/tools/build_helper",
|
||||
"src/build_helper",
|
||||
rustc_tool = false,
|
||||
is_library = true,
|
||||
crates = ["build_helper"]
|
||||
|
@ -1354,7 +1354,7 @@ impl Step for CrateBuildHelper {
|
||||
const ONLY_HOSTS: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.path("src/tools/build_helper")
|
||||
run.path("src/build_helper")
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
@ -1372,7 +1372,7 @@ impl Step for CrateBuildHelper {
|
||||
Mode::ToolBootstrap,
|
||||
host,
|
||||
Kind::Test,
|
||||
"src/tools/build_helper",
|
||||
"src/build_helper",
|
||||
SourceType::InTree,
|
||||
&[],
|
||||
);
|
||||
|
@ -28,6 +28,24 @@ use crate::utils::cache::{INTERNER, Interned};
|
||||
use crate::utils::channel::{self, GitInfo};
|
||||
use crate::utils::helpers::{self, exe, output, t};
|
||||
|
||||
/// Each path in this list is considered "allowed" in the `download-rustc="if-unchanged"` logic.
|
||||
/// This means they can be modified and changes to these paths should never trigger a compiler build
|
||||
/// when "if-unchanged" is set.
|
||||
///
|
||||
/// NOTE: Paths must have the ":!" prefix to tell git to ignore changes in those paths during
|
||||
/// the diff check.
|
||||
///
|
||||
/// WARNING: Be cautious when adding paths to this list. If a path that influences the compiler build
|
||||
/// is added here, it will cause bootstrap to skip necessary rebuilds, which may lead to risky results.
|
||||
/// For example, "src/bootstrap" should never be included in this list as it plays a crucial role in the
|
||||
/// final output/compiler, which can be significantly affected by changes made to the bootstrap sources.
|
||||
#[rustfmt::skip] // We don't want rustfmt to oneline this list
|
||||
pub(crate) const RUSTC_IF_UNCHANGED_ALLOWED_PATHS: &[&str] = &[
|
||||
":!src/tools",
|
||||
":!tests",
|
||||
":!triagebot.toml",
|
||||
];
|
||||
|
||||
macro_rules! check_ci_llvm {
|
||||
($name:expr) => {
|
||||
assert!(
|
||||
@ -2772,32 +2790,33 @@ impl Config {
|
||||
}
|
||||
};
|
||||
|
||||
let mut files_to_track = vec!["compiler", "src/version", "src/stage0", "src/ci/channel"];
|
||||
// RUSTC_IF_UNCHANGED_ALLOWED_PATHS
|
||||
let mut allowed_paths = RUSTC_IF_UNCHANGED_ALLOWED_PATHS.to_vec();
|
||||
|
||||
// In CI, disable ci-rustc if there are changes in the library tree. But for non-CI, ignore
|
||||
// In CI, disable ci-rustc if there are changes in the library tree. But for non-CI, allow
|
||||
// these changes to speed up the build process for library developers. This provides consistent
|
||||
// functionality for library developers between `download-rustc=true` and `download-rustc="if-unchanged"`
|
||||
// options.
|
||||
if CiEnv::is_ci() {
|
||||
files_to_track.push("library");
|
||||
if !CiEnv::is_ci() {
|
||||
allowed_paths.push(":!library");
|
||||
}
|
||||
|
||||
// Look for a version to compare to based on the current commit.
|
||||
// Only commits merged by bors will have CI artifacts.
|
||||
let commit =
|
||||
match self.last_modified_commit(&files_to_track, "download-rustc", if_unchanged) {
|
||||
Some(commit) => commit,
|
||||
None => {
|
||||
if if_unchanged {
|
||||
return None;
|
||||
}
|
||||
println!("ERROR: could not find commit hash for downloading rustc");
|
||||
println!("HELP: maybe your repository history is too shallow?");
|
||||
println!("HELP: consider disabling `download-rustc`");
|
||||
println!("HELP: or fetch enough history to include one upstream commit");
|
||||
crate::exit!(1);
|
||||
let commit = match self.last_modified_commit(&allowed_paths, "download-rustc", if_unchanged)
|
||||
{
|
||||
Some(commit) => commit,
|
||||
None => {
|
||||
if if_unchanged {
|
||||
return None;
|
||||
}
|
||||
};
|
||||
println!("ERROR: could not find commit hash for downloading rustc");
|
||||
println!("HELP: maybe your repository history is too shallow?");
|
||||
println!("HELP: consider setting `rust.download-rustc=false` in config.toml");
|
||||
println!("HELP: or fetch enough history to include one upstream commit");
|
||||
crate::exit!(1);
|
||||
}
|
||||
};
|
||||
|
||||
if CiEnv::is_ci() && {
|
||||
let head_sha =
|
||||
|
@ -8,7 +8,7 @@ use clap::CommandFactory;
|
||||
use serde::Deserialize;
|
||||
|
||||
use super::flags::Flags;
|
||||
use super::{ChangeIdWrapper, Config};
|
||||
use super::{ChangeIdWrapper, Config, RUSTC_IF_UNCHANGED_ALLOWED_PATHS};
|
||||
use crate::core::build_steps::clippy::get_clippy_rules_in_order;
|
||||
use crate::core::build_steps::llvm;
|
||||
use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
|
||||
@ -427,3 +427,18 @@ fn jobs_precedence() {
|
||||
);
|
||||
assert_eq!(config.jobs, Some(123));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn check_rustc_if_unchanged_paths() {
|
||||
let config = parse("");
|
||||
let normalised_allowed_paths: Vec<_> = RUSTC_IF_UNCHANGED_ALLOWED_PATHS
|
||||
.iter()
|
||||
.map(|t| {
|
||||
t.strip_prefix(":!").expect(&format!("{t} doesn't have ':!' prefix, but it should."))
|
||||
})
|
||||
.collect();
|
||||
|
||||
for p in normalised_allowed_paths {
|
||||
assert!(config.src.join(p).exists(), "{p} doesn't exist.");
|
||||
}
|
||||
}
|
||||
|
@ -25,7 +25,7 @@ pub struct Stage0Config {
|
||||
}
|
||||
|
||||
pub fn parse_stage0_file() -> Stage0 {
|
||||
let stage0_content = include_str!("../../../stage0");
|
||||
let stage0_content = include_str!("../../stage0");
|
||||
|
||||
let mut stage0 = Stage0::default();
|
||||
for line in stage0_content.lines() {
|
@ -176,9 +176,7 @@ else
|
||||
fi
|
||||
|
||||
if [ "$NO_DOWNLOAD_CI_RUSTC" = "" ]; then
|
||||
# disabled for now, see https://github.com/rust-lang/rust/issues/131658
|
||||
#RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.download-rustc=if-unchanged"
|
||||
true
|
||||
RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.download-rustc=if-unchanged"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -1011,9 +1011,7 @@ fn render_stability_since_raw_with_extra(
|
||||
// don't display const unstable if entirely unstable
|
||||
None
|
||||
} else {
|
||||
let unstable = if let Some(n) = issue
|
||||
&& let Some(feature) = feature
|
||||
{
|
||||
let unstable = if let Some(n) = issue {
|
||||
format!(
|
||||
"<a \
|
||||
href=\"https://github.com/rust-lang/rust/issues/{n}\" \
|
||||
|
@ -7,7 +7,7 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.34"
|
||||
build_helper = { path = "../build_helper" }
|
||||
build_helper = { path = "../../build_helper" }
|
||||
curl = "0.4.38"
|
||||
indexmap = { version = "2.0.0", features = ["serde"] }
|
||||
serde = { version = "1.0.125", features = ["derive"] }
|
||||
|
@ -393,12 +393,8 @@ fn is_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId, msrv: &Msrv) -> bool {
|
||||
|
||||
msrv.meets(const_stab_rust_version)
|
||||
} else {
|
||||
// Unstable const fn, check if the feature is enabled. We need both the regular stability
|
||||
// feature and (if set) the const stability feature to const-call this function.
|
||||
let stab = tcx.lookup_stability(def_id);
|
||||
let is_enabled = stab.is_some_and(|s| s.is_stable() || tcx.features().enabled(s.feature))
|
||||
&& const_stab.feature.is_none_or(|f| tcx.features().enabled(f));
|
||||
is_enabled && msrv.current().is_none()
|
||||
// Unstable const fn, check if the feature is enabled.
|
||||
tcx.features().enabled(const_stab.feature) && msrv.current().is_none()
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -14,7 +14,7 @@ unified-diff = "0.2.1"
|
||||
getopts = "0.2"
|
||||
indexmap = "2.0.0"
|
||||
miropt-test-tools = { path = "../miropt-test-tools" }
|
||||
build_helper = { path = "../build_helper" }
|
||||
build_helper = { path = "../../build_helper" }
|
||||
tracing = "0.1"
|
||||
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
|
||||
regex = "1.0"
|
||||
|
@ -35,6 +35,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
||||
"ignore-64bit",
|
||||
"ignore-aarch64",
|
||||
"ignore-aarch64-unknown-linux-gnu",
|
||||
"ignore-aix",
|
||||
"ignore-android",
|
||||
"ignore-apple",
|
||||
"ignore-arm",
|
||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
build_helper = { path = "../build_helper" }
|
||||
build_helper = { path = "../../build_helper" }
|
||||
env_logger = "0.11"
|
||||
log = "0.4"
|
||||
anyhow = { version = "1", features = ["backtrace"] }
|
||||
|
@ -10,7 +10,7 @@ similar = "2.5.0"
|
||||
wasmparser = { version = "0.216", default-features = false, features = ["std"] }
|
||||
regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
|
||||
gimli = "0.31.0"
|
||||
build_helper = { path = "../build_helper" }
|
||||
build_helper = { path = "../../build_helper" }
|
||||
serde_json = "1.0"
|
||||
libc = "0.2"
|
||||
|
||||
|
@ -5,7 +5,7 @@ use crate::command::Command;
|
||||
use crate::env::env_var;
|
||||
use crate::path_helpers::cwd;
|
||||
use crate::util::set_host_rpath;
|
||||
use crate::{is_darwin, is_msvc, is_windows, uname};
|
||||
use crate::{is_aix, is_darwin, is_msvc, is_windows, uname};
|
||||
|
||||
/// Construct a new `rustc` invocation. This will automatically set the library
|
||||
/// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this.
|
||||
@ -346,7 +346,7 @@ impl Rustc {
|
||||
// endif
|
||||
// endif
|
||||
// ```
|
||||
let flag = if is_windows() {
|
||||
if is_windows() {
|
||||
// So this is a bit hacky: we can't use the DLL version of libstdc++ because
|
||||
// it pulls in the DLL version of libgcc, which means that we end up with 2
|
||||
// instances of the DW2 unwinding implementation. This is a problem on
|
||||
@ -362,18 +362,19 @@ impl Rustc {
|
||||
// So we end up with the following hack: we link use static:-bundle to only
|
||||
// link the parts of libstdc++ that we actually use, which doesn't include
|
||||
// the dependency on the pthreads DLL.
|
||||
if is_msvc() { None } else { Some("-lstatic:-bundle=stdc++") }
|
||||
if !is_msvc() {
|
||||
self.cmd.arg("-lstatic:-bundle=stdc++");
|
||||
};
|
||||
} else if is_darwin() {
|
||||
Some("-lc++")
|
||||
self.cmd.arg("-lc++");
|
||||
} else if is_aix() {
|
||||
self.cmd.arg("-lc++");
|
||||
self.cmd.arg("-lc++abi");
|
||||
} else {
|
||||
match &uname()[..] {
|
||||
"FreeBSD" | "SunOS" | "OpenBSD" => None,
|
||||
_ => Some("-lstdc++"),
|
||||
}
|
||||
if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
|
||||
self.cmd.arg("-lstdc++");
|
||||
};
|
||||
};
|
||||
if let Some(flag) = flag {
|
||||
self.cmd.arg(flag);
|
||||
}
|
||||
self
|
||||
}
|
||||
}
|
||||
|
@ -78,7 +78,7 @@ pub use env::{env_var, env_var_os, set_current_dir};
|
||||
pub use run::{cmd, run, run_fail, run_with_args};
|
||||
|
||||
/// Helpers for checking target information.
|
||||
pub use targets::{is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os};
|
||||
pub use targets::{is_aix, is_darwin, is_msvc, is_windows, llvm_components_contain, target, uname, apple_os};
|
||||
|
||||
/// Helpers for building names of output artifacts that are potentially target-specific.
|
||||
pub use artifact_names::{
|
||||
|
@ -28,6 +28,12 @@ pub fn is_darwin() -> bool {
|
||||
target().contains("darwin")
|
||||
}
|
||||
|
||||
/// Check if target uses AIX.
|
||||
#[must_use]
|
||||
pub fn is_aix() -> bool {
|
||||
target().contains("aix")
|
||||
}
|
||||
|
||||
/// Get the target OS on Apple operating systems.
|
||||
#[must_use]
|
||||
pub fn apple_os() -> &'static str {
|
||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
build_helper = { path = "../build_helper" }
|
||||
build_helper = { path = "../../build_helper" }
|
||||
compiletest = { path = "../compiletest" }
|
||||
getopts = "0.2"
|
||||
walkdir = "2"
|
||||
|
@ -5,4 +5,4 @@ edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
glob = "0.3.0"
|
||||
build_helper = { version = "0.1.0", path = "../build_helper" }
|
||||
build_helper = { version = "0.1.0", path = "../../build_helper" }
|
||||
|
@ -5,7 +5,7 @@ edition = "2021"
|
||||
autobins = false
|
||||
|
||||
[dependencies]
|
||||
build_helper = { path = "../build_helper" }
|
||||
build_helper = { path = "../../build_helper" }
|
||||
cargo_metadata = "0.18"
|
||||
regex = "1"
|
||||
miropt-test-tools = { path = "../miropt-test-tools" }
|
||||
|
@ -16,13 +16,13 @@ const fn const_main() {
|
||||
unsafe {
|
||||
unstable_intrinsic::size_of_val(&x);
|
||||
//~^ERROR: unstable library feature `unstable`
|
||||
//~|ERROR: cannot be (indirectly) exposed to stable
|
||||
//~|ERROR: not yet stable as a const intrinsic
|
||||
unstable_intrinsic::min_align_of_val(&x);
|
||||
//~^ERROR: unstable library feature `unstable`
|
||||
//~|ERROR: not yet stable as a const intrinsic
|
||||
|
||||
size_of_val(&x);
|
||||
//~^ERROR: cannot be (indirectly) exposed to stable
|
||||
//~^ERROR: cannot use `#[feature(local)]`
|
||||
min_align_of_val(&x);
|
||||
//~^ERROR: cannot use `#[feature(local)]`
|
||||
}
|
||||
@ -59,6 +59,6 @@ mod fallback {
|
||||
#[rustc_intrinsic]
|
||||
const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
|
||||
super::size_of_val(src);
|
||||
//~^ ERROR cannot be (indirectly) exposed to stable
|
||||
//~^ ERROR cannot use `#[feature(local)]`
|
||||
}
|
||||
}
|
||||
|
@ -18,13 +18,13 @@ LL | unstable_intrinsic::min_align_of_val(&x);
|
||||
= help: add `#![feature(unstable)]` 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: intrinsic `unstable_intrinsic::size_of_val` cannot be (indirectly) exposed to stable
|
||||
error: `size_of_val` is not yet stable as a const intrinsic
|
||||
--> $DIR/const-unstable-intrinsic.rs:17:9
|
||||
|
|
||||
LL | unstable_intrinsic::size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
|
||||
error: `min_align_of_val` is not yet stable as a const intrinsic
|
||||
--> $DIR/const-unstable-intrinsic.rs:20:9
|
||||
@ -34,13 +34,22 @@ LL | unstable_intrinsic::min_align_of_val(&x);
|
||||
|
|
||||
= help: add `#![feature(unstable)]` to the crate attributes to enable
|
||||
|
||||
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
|
||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
|
||||
--> $DIR/const-unstable-intrinsic.rs:24:9
|
||||
|
|
||||
LL | size_of_val(&x);
|
||||
| ^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||
|
|
||||
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||
LL | const fn const_main() {
|
||||
|
|
||||
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||
|
|
||||
LL + #[rustc_allow_const_fn_unstable(local)]
|
||||
LL | const fn const_main() {
|
||||
|
|
||||
|
||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
|
||||
--> $DIR/const-unstable-intrinsic.rs:26:9
|
||||
@ -67,13 +76,22 @@ LL | unsafe { copy(src, dst, count) }
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
|
||||
error: intrinsic `size_of_val` cannot be (indirectly) exposed to stable
|
||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
|
||||
--> $DIR/const-unstable-intrinsic.rs:61:9
|
||||
|
|
||||
LL | super::size_of_val(src);
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the caller as `#[rustc_const_unstable]`, or mark the intrinsic `#[rustc_const_stable_intrinsic]` (but this requires team approval)
|
||||
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||
|
|
||||
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||
LL | const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
|
||||
|
|
||||
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||
|
|
||||
LL + #[rustc_allow_const_fn_unstable(local)]
|
||||
LL | const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
|
||||
|
|
||||
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
@ -0,0 +1 @@
|
||||
pub const fn just_a_fn() {}
|
@ -0,0 +1,8 @@
|
||||
//@ compile-flags: -Zforce-unstable-if-unmarked
|
||||
|
||||
#![feature(rustc_attrs)]
|
||||
|
||||
pub const fn not_stably_const() {}
|
||||
|
||||
#[rustc_const_stable_indirect]
|
||||
pub const fn expose_on_stable() {}
|
@ -0,0 +1,21 @@
|
||||
//@ aux-build:unstable_if_unmarked_const_fn_crate.rs
|
||||
//@ aux-build:unmarked_const_fn_crate.rs
|
||||
#![feature(staged_api, rustc_private)]
|
||||
#![stable(since = "1.0.0", feature = "stable")]
|
||||
|
||||
extern crate unmarked_const_fn_crate;
|
||||
extern crate unstable_if_unmarked_const_fn_crate;
|
||||
|
||||
#[stable(feature = "rust1", since = "1.0.0")]
|
||||
#[rustc_const_stable(feature = "rust1", since = "1.0.0")]
|
||||
const fn stable_fn() {
|
||||
// This one is fine.
|
||||
unstable_if_unmarked_const_fn_crate::expose_on_stable();
|
||||
// This one is not.
|
||||
unstable_if_unmarked_const_fn_crate::not_stably_const();
|
||||
//~^ERROR: cannot use `#[feature(rustc_private)]`
|
||||
unmarked_const_fn_crate::just_a_fn();
|
||||
//~^ERROR: cannot be (indirectly) exposed to stable
|
||||
}
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,28 @@
|
||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(rustc_private)]`
|
||||
--> $DIR/recursive_const_stab_unmarked_crate_imports.rs:15:5
|
||||
|
|
||||
LL | unstable_if_unmarked_const_fn_crate::not_stably_const();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||
|
|
||||
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||
LL | const fn stable_fn() {
|
||||
|
|
||||
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||
|
|
||||
LL + #[rustc_allow_const_fn_unstable(rustc_private)]
|
||||
LL | const fn stable_fn() {
|
||||
|
|
||||
|
||||
error: `just_a_fn` cannot be (indirectly) exposed to stable
|
||||
--> $DIR/recursive_const_stab_unmarked_crate_imports.rs:17:5
|
||||
|
|
||||
LL | unmarked_const_fn_crate::just_a_fn();
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: either mark the callee as `#[rustc_const_stable_indirect]`, or the caller as `#[rustc_const_unstable]`
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -0,0 +1,24 @@
|
||||
//@ compile-flags: -Zforce-unstable-if-unmarked
|
||||
//@ edition: 2021
|
||||
#![feature(const_async_blocks, rustc_attrs, rustc_private)]
|
||||
|
||||
pub const fn not_stably_const() {
|
||||
// We need to do something const-unstable here.
|
||||
// For now we use `async`, eventually we might have to add a auxiliary crate
|
||||
// as a dependency just to be sure we have something const-unstable.
|
||||
let _x = async { 15 };
|
||||
}
|
||||
|
||||
#[rustc_const_stable_indirect]
|
||||
pub const fn expose_on_stable() {
|
||||
// Calling `not_stably_const` here is *not* okay.
|
||||
not_stably_const();
|
||||
//~^ERROR: cannot use `#[feature(rustc_private)]`
|
||||
// Also directly using const-unstable things is not okay.
|
||||
let _x = async { 15 };
|
||||
//~^ERROR: cannot use `#[feature(const_async_blocks)]`
|
||||
}
|
||||
|
||||
fn main() {
|
||||
const { expose_on_stable() };
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(rustc_private)]`
|
||||
--> $DIR/recursive_const_stab_unstable_if_unmarked.rs:15:5
|
||||
|
|
||||
LL | not_stably_const();
|
||||
| ^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
= help: mark the callee as `#[rustc_const_stable_indirect]` if it does not itself require any unsafe features
|
||||
help: if the caller is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||
|
|
||||
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||
LL | pub const fn expose_on_stable() {
|
||||
|
|
||||
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||
|
|
||||
LL + #[rustc_allow_const_fn_unstable(rustc_private)]
|
||||
LL | pub const fn expose_on_stable() {
|
||||
|
|
||||
|
||||
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(const_async_blocks)]`
|
||||
--> $DIR/recursive_const_stab_unstable_if_unmarked.rs:18:14
|
||||
|
|
||||
LL | let _x = async { 15 };
|
||||
| ^^^^^^^^^^^^
|
||||
|
|
||||
help: if the function is not (yet) meant to be exposed to stable, add `#[rustc_const_unstable]` (this is what you probably want to do)
|
||||
|
|
||||
LL + #[rustc_const_unstable(feature = "...", issue = "...")]
|
||||
LL | pub const fn expose_on_stable() {
|
||||
|
|
||||
help: otherwise, as a last resort `#[rustc_allow_const_fn_unstable]` can be used to bypass stability checks (this requires team approval)
|
||||
|
|
||||
LL + #[rustc_allow_const_fn_unstable(const_async_blocks)]
|
||||
LL | pub const fn expose_on_stable() {
|
||||
|
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
@ -56,9 +56,3 @@ const fn barfoo_unmarked() {}
|
||||
#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
||||
pub const fn barfoo_unstable() {}
|
||||
//~^ ERROR can only be applied to functions that are declared `#[stable]`
|
||||
|
||||
// `#[rustc_const_stable_indirect]` also requires a const fn
|
||||
#[rustc_const_stable_indirect]
|
||||
#[unstable(feature = "unstable", issue = "none")]
|
||||
pub fn not_a_const_fn() {}
|
||||
//~^ ERROR require the function or method to be `const`
|
||||
|
@ -86,17 +86,5 @@ LL | #[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
||||
LL | pub const fn barfoo_unstable() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: attributes `#[rustc_const_unstable]`, `#[rustc_const_stable]` and `#[rustc_const_stable_indirect]` require the function or method to be `const`
|
||||
--> $DIR/rustc-const-stability-require-const.rs:63:1
|
||||
|
|
||||
LL | pub fn not_a_const_fn() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
|
||||
help: make the function or method const
|
||||
--> $DIR/rustc-const-stability-require-const.rs:63:1
|
||||
|
|
||||
LL | pub fn not_a_const_fn() {}
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 9 previous errors
|
||||
error: aborting due to 8 previous errors
|
||||
|
||||
|
@ -1,17 +1,3 @@
|
||||
error: can't mark as unstable using an already stable feature
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||
|
|
||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
|
||||
LL | const fn my_fun() {}
|
||||
| -------------------- the stability attribute annotates this item
|
||||
|
|
||||
help: consider removing the attribute
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||
|
|
||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: can't mark as unstable using an already stable feature
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
|
||||
|
|
||||
@ -27,5 +13,19 @@ help: consider removing the attribute
|
||||
LL | #[unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: can't mark as unstable using an already stable feature
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||
|
|
||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this feature is already stable
|
||||
LL | const fn my_fun() {}
|
||||
| -------------------- the stability attribute annotates this item
|
||||
|
|
||||
help: consider removing the attribute
|
||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:7:1
|
||||
|
|
||||
LL | #[rustc_const_unstable(feature = "arbitrary_enum_discriminant", issue = "42")]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
||||
error: aborting due to 2 previous errors
|
||||
|
||||
|
@ -0,0 +1,13 @@
|
||||
//@ run-rustfix
|
||||
//@ rustfix-only-machine-applicable
|
||||
|
||||
// Make sure that simple overcapture suggestions remain machine applicable.
|
||||
|
||||
#![allow(unused)]
|
||||
#![deny(impl_trait_overcaptures)]
|
||||
|
||||
fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x }
|
||||
//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
|
||||
//~| WARN this changes meaning in Rust 2024
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,13 @@
|
||||
//@ run-rustfix
|
||||
//@ rustfix-only-machine-applicable
|
||||
|
||||
// Make sure that simple overcapture suggestions remain machine applicable.
|
||||
|
||||
#![allow(unused)]
|
||||
#![deny(impl_trait_overcaptures)]
|
||||
|
||||
fn named<'a>(x: &'a i32) -> impl Sized { *x }
|
||||
//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024
|
||||
//~| WARN this changes meaning in Rust 2024
|
||||
|
||||
fn main() {}
|
@ -0,0 +1,26 @@
|
||||
error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024
|
||||
--> $DIR/overcaptures-2024-machine-applicable.rs:9:29
|
||||
|
|
||||
LL | fn named<'a>(x: &'a i32) -> impl Sized { *x }
|
||||
| ^^^^^^^^^^
|
||||
|
|
||||
= warning: this changes meaning in Rust 2024
|
||||
= note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/rpit-lifetime-capture.html>
|
||||
note: specifically, this lifetime is in scope but not mentioned in the type's bounds
|
||||
--> $DIR/overcaptures-2024-machine-applicable.rs:9:10
|
||||
|
|
||||
LL | fn named<'a>(x: &'a i32) -> impl Sized { *x }
|
||||
| ^^
|
||||
= note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024
|
||||
note: the lint level is defined here
|
||||
--> $DIR/overcaptures-2024-machine-applicable.rs:7:9
|
||||
|
|
||||
LL | #![deny(impl_trait_overcaptures)]
|
||||
| ^^^^^^^^^^^^^^^^^^^^^^^
|
||||
help: use the precise capturing `use<...>` syntax to make the captures explicit
|
||||
|
|
||||
LL | fn named<'a>(x: &'a i32) -> impl Sized + use<> { *x }
|
||||
| +++++++
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
14
tests/ui/mir/enable_passes_validation.all_unknown.stderr
Normal file
14
tests/ui/mir/enable_passes_validation.all_unknown.stderr
Normal file
@ -0,0 +1,14 @@
|
||||
warning: MIR pass `ThisPass` is unknown and will be ignored
|
||||
|
||||
warning: MIR pass `DoesNotExist` is unknown and will be ignored
|
||||
|
||||
warning: MIR pass `ThisPass` is unknown and will be ignored
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: MIR pass `DoesNotExist` is unknown and will be ignored
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: 4 warnings emitted
|
||||
|
2
tests/ui/mir/enable_passes_validation.empty.stderr
Normal file
2
tests/ui/mir/enable_passes_validation.empty.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: incorrect value `` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected
|
||||
|
8
tests/ui/mir/enable_passes_validation.mixed.stderr
Normal file
8
tests/ui/mir/enable_passes_validation.mixed.stderr
Normal file
@ -0,0 +1,8 @@
|
||||
warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored
|
||||
|
||||
warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored
|
||||
|
|
||||
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
|
||||
|
||||
warning: 2 warnings emitted
|
||||
|
21
tests/ui/mir/enable_passes_validation.rs
Normal file
21
tests/ui/mir/enable_passes_validation.rs
Normal file
@ -0,0 +1,21 @@
|
||||
//@ revisions: empty unprefixed all_unknown all_known mixed
|
||||
|
||||
//@[empty] compile-flags: -Zmir-enable-passes=
|
||||
//@[empty] error-pattern error: incorrect value `` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected
|
||||
|
||||
//@[unprefixed] compile-flags: -Zmir-enable-passes=CheckAlignment
|
||||
//@[unprefixed] error-pattern error: incorrect value `CheckAlignment` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected
|
||||
|
||||
//@[all_unknown] check-pass
|
||||
//@[all_unknown] compile-flags: -Zmir-enable-passes=+ThisPass,-DoesNotExist
|
||||
//@[all_unknown] error-pattern: warning: MIR pass `ThisPass` is unknown and will be ignored
|
||||
//@[all_unknown] error-pattern: warning: MIR pass `DoesNotExist` is unknown and will be ignored
|
||||
|
||||
//@[all_known] check-pass
|
||||
//@[all_known] compile-flags: -Zmir-enable-passes=+CheckAlignment,+LowerIntrinsics
|
||||
|
||||
//@[mixed] check-pass
|
||||
//@[mixed] compile-flags: -Zmir-enable-passes=+ThisPassDoesNotExist,+CheckAlignment
|
||||
//@[mixed] error-pattern: warning: MIR pass `ThisPassDoesNotExist` is unknown and will be ignored
|
||||
|
||||
fn main() {}
|
2
tests/ui/mir/enable_passes_validation.unprefixed.stderr
Normal file
2
tests/ui/mir/enable_passes_validation.unprefixed.stderr
Normal file
@ -0,0 +1,2 @@
|
||||
error: incorrect value `CheckAlignment` for unstable option `mir-enable-passes` - a comma-separated list of strings, with elements beginning with + or - was expected
|
||||
|
@ -981,30 +981,24 @@ users_on_vacation = [
|
||||
]
|
||||
|
||||
[assign.adhoc_groups]
|
||||
compiler-team = [
|
||||
"@cjgillot",
|
||||
"@compiler-errors",
|
||||
"@petrochenkov",
|
||||
"@davidtwco",
|
||||
"@estebank",
|
||||
"@lcnr",
|
||||
"@oli-obk",
|
||||
"@pnkfelix",
|
||||
"@wesleywiser",
|
||||
]
|
||||
compiler-team-contributors = [
|
||||
"@TaKO8Ki",
|
||||
"@Nadrieril",
|
||||
"@nnethercote",
|
||||
"@fmease",
|
||||
"@fee1-dead",
|
||||
"@jieyouxu",
|
||||
compiler = [
|
||||
"@BoxyUwU",
|
||||
"@chenyukang",
|
||||
]
|
||||
compiler = [
|
||||
"compiler-team",
|
||||
"compiler-team-contributors",
|
||||
"@cjgillot",
|
||||
"@compiler-errors",
|
||||
"@davidtwco",
|
||||
"@estebank",
|
||||
"@fee1-dead",
|
||||
"@fmease",
|
||||
"@jieyouxu",
|
||||
"@lcnr",
|
||||
"@Nadrieril",
|
||||
"@nnethercote",
|
||||
"@oli-obk",
|
||||
"@petrochenkov",
|
||||
"@pnkfelix",
|
||||
"@TaKO8Ki",
|
||||
"@wesleywiser",
|
||||
]
|
||||
libs = [
|
||||
"@cuviper",
|
||||
|
Loading…
Reference in New Issue
Block a user