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"
|
resolver = "2"
|
||||||
members = [
|
members = [
|
||||||
"compiler/rustc",
|
"compiler/rustc",
|
||||||
|
"src/build_helper",
|
||||||
"src/etc/test-float-parse",
|
"src/etc/test-float-parse",
|
||||||
"src/rustc-std-workspace/rustc-std-workspace-core",
|
"src/rustc-std-workspace/rustc-std-workspace-core",
|
||||||
"src/rustc-std-workspace/rustc-std-workspace-alloc",
|
"src/rustc-std-workspace/rustc-std-workspace-alloc",
|
||||||
"src/rustc-std-workspace/rustc-std-workspace-std",
|
"src/rustc-std-workspace/rustc-std-workspace-std",
|
||||||
"src/rustdoc-json-types",
|
"src/rustdoc-json-types",
|
||||||
"src/tools/build_helper",
|
|
||||||
"src/tools/cargotest",
|
"src/tools/cargotest",
|
||||||
"src/tools/clippy",
|
"src/tools/clippy",
|
||||||
"src/tools/clippy/clippy_dev",
|
"src/tools/clippy/clippy_dev",
|
||||||
|
@ -16,9 +16,9 @@ use rustc_session::lint::BuiltinLintDiag;
|
|||||||
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
use rustc_session::lint::builtin::UNEXPECTED_CFGS;
|
||||||
use rustc_session::parse::feature_err;
|
use rustc_session::parse::feature_err;
|
||||||
use rustc_session::{RustcVersion, Session};
|
use rustc_session::{RustcVersion, Session};
|
||||||
|
use rustc_span::Span;
|
||||||
use rustc_span::hygiene::Transparency;
|
use rustc_span::hygiene::Transparency;
|
||||||
use rustc_span::symbol::{Symbol, kw, sym};
|
use rustc_span::symbol::{Symbol, kw, sym};
|
||||||
use rustc_span::{DUMMY_SP, Span};
|
|
||||||
|
|
||||||
use crate::fluent_generated;
|
use crate::fluent_generated;
|
||||||
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
use crate::session_diagnostics::{self, IncorrectReprFormatGenericCause};
|
||||||
@ -92,9 +92,7 @@ impl Stability {
|
|||||||
#[derive(HashStable_Generic)]
|
#[derive(HashStable_Generic)]
|
||||||
pub struct ConstStability {
|
pub struct ConstStability {
|
||||||
pub level: StabilityLevel,
|
pub level: StabilityLevel,
|
||||||
/// This can be `None` for functions that do not have an explicit const feature.
|
pub feature: Symbol,
|
||||||
/// We still track them for recursive const stability checks.
|
|
||||||
pub feature: Option<Symbol>,
|
|
||||||
/// This is true iff the `const_stable_indirect` attribute is present.
|
/// This is true iff the `const_stable_indirect` attribute is present.
|
||||||
pub const_stable_indirect: bool,
|
pub const_stable_indirect: bool,
|
||||||
/// whether the function has a `#[rustc_promotable]` attribute
|
/// 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`
|
/// Collects stability info from `rustc_const_stable`/`rustc_const_unstable`/`rustc_promotable`
|
||||||
/// attributes in `attrs`. Returns `None` if no stability attributes are found.
|
/// 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(
|
pub fn find_const_stability(
|
||||||
sess: &Session,
|
sess: &Session,
|
||||||
attrs: &[Attribute],
|
attrs: &[Attribute],
|
||||||
item_sp: Span,
|
item_sp: Span,
|
||||||
is_const_fn: bool,
|
|
||||||
) -> Option<(ConstStability, Span)> {
|
) -> Option<(ConstStability, Span)> {
|
||||||
let mut const_stab: Option<(ConstStability, Span)> = None;
|
let mut const_stab: Option<(ConstStability, Span)> = None;
|
||||||
let mut promotable = false;
|
let mut promotable = false;
|
||||||
let mut const_stable_indirect = None;
|
let mut const_stable_indirect = false;
|
||||||
|
|
||||||
for attr in attrs {
|
for attr in attrs {
|
||||||
match attr.name_or_empty() {
|
match attr.name_or_empty() {
|
||||||
sym::rustc_promotable => promotable = true,
|
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 => {
|
sym::rustc_const_unstable => {
|
||||||
if const_stab.is_some() {
|
if const_stab.is_some() {
|
||||||
sess.dcx()
|
sess.dcx()
|
||||||
@ -299,7 +294,7 @@ pub fn find_const_stability(
|
|||||||
const_stab = Some((
|
const_stab = Some((
|
||||||
ConstStability {
|
ConstStability {
|
||||||
level,
|
level,
|
||||||
feature: Some(feature),
|
feature,
|
||||||
const_stable_indirect: false,
|
const_stable_indirect: false,
|
||||||
promotable: false,
|
promotable: false,
|
||||||
},
|
},
|
||||||
@ -317,7 +312,7 @@ pub fn find_const_stability(
|
|||||||
const_stab = Some((
|
const_stab = Some((
|
||||||
ConstStability {
|
ConstStability {
|
||||||
level,
|
level,
|
||||||
feature: Some(feature),
|
feature,
|
||||||
const_stable_indirect: false,
|
const_stable_indirect: false,
|
||||||
promotable: 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 {
|
match &mut const_stab {
|
||||||
Some((stab, _)) => {
|
Some((stab, _)) => {
|
||||||
if stab.is_const_unstable() {
|
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
|
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`.
|
/// Collects stability info from `rustc_default_body_unstable` attributes in `attrs`.
|
||||||
/// Returns `None` if no stability attributes are found.
|
/// Returns `None` if no stability attributes are found.
|
||||||
pub fn find_body_stability(
|
pub fn find_body_stability(
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
use std::assert_matches::assert_matches;
|
use std::assert_matches::assert_matches;
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::num::NonZero;
|
||||||
use std::ops::Deref;
|
use std::ops::Deref;
|
||||||
|
|
||||||
use rustc_attr::{ConstStability, StabilityLevel};
|
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.
|
// Intrinsics are language primitives, not regular calls, so treat them separately.
|
||||||
if let Some(intrinsic) = tcx.intrinsic(callee) {
|
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
|
// 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
|
// stable code, rather than `const_stable_indirect`. This is to make
|
||||||
// `#[rustc_const_stable_indirect]` an attribute that is always safe to add.
|
// `#[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.
|
// fallback body is safe to expose on stable.
|
||||||
let is_const_stable = intrinsic.const_stable
|
let is_const_stable = intrinsic.const_stable
|
||||||
|| (!intrinsic.must_be_overridden
|
|| (!intrinsic.must_be_overridden
|
||||||
&& tcx.is_const_fn(callee)
|
|
||||||
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
|
&& is_safe_to_expose_on_stable_const_fn(tcx, callee));
|
||||||
match tcx.lookup_const_stability(callee) {
|
match tcx.lookup_const_stability(callee) {
|
||||||
None => {
|
None => {
|
||||||
// Non-const intrinsic.
|
// This doesn't need a separate const-stability check -- const-stability equals
|
||||||
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
|
// regular stability, and regular stability is checked separately.
|
||||||
}
|
// However, we *do* have to worry about *recursive* const stability.
|
||||||
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.
|
|
||||||
if !is_const_stable && self.enforce_recursive_const_stability() {
|
if !is_const_stable && self.enforce_recursive_const_stability() {
|
||||||
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
|
self.dcx().emit_err(errors::UnmarkedIntrinsicExposed {
|
||||||
span: self.span,
|
span: self.span,
|
||||||
@ -735,8 +738,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(ConstStability {
|
Some(ConstStability {
|
||||||
feature: Some(feature),
|
|
||||||
level: StabilityLevel::Unstable { .. },
|
level: StabilityLevel::Unstable { .. },
|
||||||
|
feature,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
self.check_op(ops::IntrinsicUnstable {
|
self.check_op(ops::IntrinsicUnstable {
|
||||||
@ -773,7 +776,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => {
|
||||||
// All good.
|
// All good.
|
||||||
}
|
}
|
||||||
None | Some(ConstStability { feature: None, .. }) => {
|
None => {
|
||||||
// This doesn't need a separate const-stability check -- const-stability equals
|
// This doesn't need a separate const-stability check -- const-stability equals
|
||||||
// regular stability, and regular stability is checked separately.
|
// regular stability, and regular stability is checked separately.
|
||||||
// However, we *do* have to worry about *recursive* const stability.
|
// However, we *do* have to worry about *recursive* const stability.
|
||||||
@ -787,8 +790,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
Some(ConstStability {
|
Some(ConstStability {
|
||||||
feature: Some(feature),
|
level: StabilityLevel::Unstable { implied_by: implied_feature, issue, .. },
|
||||||
level: StabilityLevel::Unstable { implied_by: implied_feature, .. },
|
feature,
|
||||||
..
|
..
|
||||||
}) => {
|
}) => {
|
||||||
// An unstable const fn with a feature gate.
|
// An unstable const fn with a feature gate.
|
||||||
@ -810,7 +813,23 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
|
|||||||
// to allow this.
|
// to allow this.
|
||||||
let feature_enabled = callee.is_local()
|
let feature_enabled = callee.is_local()
|
||||||
|| tcx.features().enabled(feature)
|
|| 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
|
// 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
|
// recursive const-stability and the callee is not safe-to-expose. In that
|
||||||
// case we need `check_op` to do the check.
|
// 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 {
|
pub fn enforce_recursive_const_stability(&self) -> bool {
|
||||||
// We can skip this if `staged_api` is not enabled, since in such crates
|
// We can skip this if neither `staged_api` nor `-Zforce-unstable-if-unmarked` are enabled,
|
||||||
// `lookup_const_stability` will always be `None`.
|
// since in such crates `lookup_const_stability` will always be `None`.
|
||||||
self.const_kind == Some(hir::ConstContext::ConstFn)
|
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())
|
&& 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) {
|
match tcx.lookup_const_stability(def_id) {
|
||||||
None => {
|
None => {
|
||||||
// Only marked functions can be trusted. Note that this may be a function in a
|
// In a `staged_api` crate, we do enforce recursive const stability for all unmarked
|
||||||
// non-staged-API crate where no recursive checks were done!
|
// functions, so we can trust local functions. But in another crate we don't know which
|
||||||
false
|
// rules were applied, so we can't trust that.
|
||||||
|
def_id.is_local() && tcx.features().staged_api()
|
||||||
}
|
}
|
||||||
Some(stab) => {
|
Some(stab) => {
|
||||||
// We consider things safe-to-expose if they are stable, if they don't have any explicit
|
// We consider things safe-to-expose if they are stable or if they are marked as
|
||||||
// const stability attribute, or if they are marked as `const_stable_indirect`.
|
// `const_stable_indirect`.
|
||||||
stab.is_const_stable() || stab.feature.is_none() || stab.const_stable_indirect
|
stab.is_const_stable() || stab.const_stable_indirect
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -623,12 +623,25 @@ impl Drop for DiagCtxtInner {
|
|||||||
self.flush_delayed()
|
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 !self.has_printed && !self.suppressed_expected_diag && !std::thread::panicking() {
|
||||||
if let Some(backtrace) = &self.must_produce_diag {
|
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!(
|
panic!(
|
||||||
"must_produce_diag: `trimmed_def_paths` called but no diagnostics emitted; \
|
"`trimmed_def_paths` called, diagnostics were expected but none were emitted. \
|
||||||
`with_no_trimmed_paths` for debugging. \
|
Use `with_no_trimmed_paths` for debugging. {suggestion}"
|
||||||
called at: {backtrace}"
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -866,9 +866,7 @@ impl SyntaxExtension {
|
|||||||
})
|
})
|
||||||
.unwrap_or_else(|| (None, helper_attrs));
|
.unwrap_or_else(|| (None, helper_attrs));
|
||||||
let stability = attr::find_stability(sess, attrs, span);
|
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);
|
||||||
let const_stability =
|
|
||||||
attr::find_const_stability(sess, attrs, span, /* is_const_fn */ false);
|
|
||||||
let body_stability = attr::find_body_stability(sess, attrs);
|
let body_stability = attr::find_body_stability(sess, attrs);
|
||||||
if let Some((_, sp)) = const_stability {
|
if let Some((_, sp)) = const_stability {
|
||||||
sess.dcx().emit_err(errors::MacroConstStability {
|
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
|
.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
|
.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
|
.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,
|
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(crate) struct AssertLint<P> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
pub assert_kind: AssertKind<P>,
|
pub assert_kind: AssertKind<P>,
|
||||||
|
@ -40,77 +40,158 @@ use tracing::{debug, trace};
|
|||||||
#[macro_use]
|
#[macro_use]
|
||||||
mod pass_manager;
|
mod pass_manager;
|
||||||
|
|
||||||
|
use std::sync::LazyLock;
|
||||||
|
|
||||||
use pass_manager::{self as pm, Lint, MirLint, MirPass, WithMinOptLevel};
|
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 cost_checker;
|
||||||
mod coverage;
|
|
||||||
mod cross_crate_inline;
|
mod cross_crate_inline;
|
||||||
mod ctfe_limit;
|
|
||||||
mod dataflow_const_prop;
|
|
||||||
mod dead_store_elimination;
|
|
||||||
mod deduce_param_attrs;
|
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 errors;
|
||||||
mod ffi_unwind_calls;
|
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 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 shim;
|
||||||
mod ssa;
|
mod ssa;
|
||||||
// This pass is public to allow external drivers to perform MIR cleanup
|
|
||||||
pub mod simplify;
|
/// We import passes via this macro so that we can have a static list of pass names
|
||||||
mod simplify_branches;
|
/// (used to verify CLI arguments). It takes a list of modules, followed by the passes
|
||||||
mod simplify_comparison_integral;
|
/// declared within them.
|
||||||
mod single_use_consts;
|
/// ```ignore,macro-test
|
||||||
mod sroa;
|
/// declare_passes! {
|
||||||
mod unreachable_enum_branching;
|
/// // Declare a single pass from the module `abort_unwinding_calls`
|
||||||
mod unreachable_prop;
|
/// mod abort_unwinding_calls : AbortUnwindingCalls;
|
||||||
mod validate;
|
/// // 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" }
|
rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
|
||||||
|
|
||||||
|
@ -1,24 +1,25 @@
|
|||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::collections::hash_map::Entry;
|
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::mir::{self, Body, MirPhase, RuntimePhase};
|
||||||
use rustc_middle::ty::TyCtxt;
|
use rustc_middle::ty::TyCtxt;
|
||||||
use rustc_session::Session;
|
use rustc_session::Session;
|
||||||
use tracing::trace;
|
use tracing::trace;
|
||||||
|
|
||||||
use crate::lint::lint_body;
|
use crate::lint::lint_body;
|
||||||
use crate::validate;
|
use crate::{errors, validate};
|
||||||
|
|
||||||
thread_local! {
|
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())
|
RefCell::new(FxHashMap::default())
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Converts a MIR pass name into a snake case form to match the profiling naming style.
|
/// 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 {
|
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::Occupied(e) => *e.get(),
|
||||||
Entry::Vacant(e) => {
|
Entry::Vacant(e) => {
|
||||||
let snake_case: String = type_name
|
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;
|
let overridden_passes = &tcx.sess.opts.unstable_opts.mir_enable_passes;
|
||||||
trace!(?overridden_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()));
|
let prof_arg = tcx.sess.prof.enabled().then(|| format!("{:?}", body.source.def_id()));
|
||||||
|
|
||||||
if !body.should_skip() {
|
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::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModDefId};
|
||||||
use rustc_hir::hir_id::CRATE_HIR_ID;
|
use rustc_hir::hir_id::CRATE_HIR_ID;
|
||||||
use rustc_hir::intravisit::{self, Visitor};
|
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::hir::nested_filter;
|
||||||
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures};
|
||||||
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
use rustc_middle::middle::privacy::EffectiveVisibilities;
|
||||||
@ -149,6 +149,11 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||||||
if let Some(stab) = self.parent_stab {
|
if let Some(stab) = self.parent_stab {
|
||||||
if inherit_deprecation.yes() && stab.is_unstable() {
|
if inherit_deprecation.yes() && stab.is_unstable() {
|
||||||
self.index.stab_map.insert(def_id, stab);
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// # Regular and body stability
|
||||||
|
|
||||||
let stab = attr::find_stability(self.tcx.sess, attrs, item_sp);
|
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);
|
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
|
if let Some((depr, span)) = &depr
|
||||||
&& depr.is_since_rustc_version()
|
&& depr.is_since_rustc_version()
|
||||||
&& stab.is_none()
|
&& stab.is_none()
|
||||||
@ -289,15 +237,6 @@ impl<'a, 'tcx> Annotator<'a, 'tcx> {
|
|||||||
self.index.implications.insert(implied_by, feature);
|
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);
|
self.index.stab_map.insert(def_id, stab);
|
||||||
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(
|
self.recurse_with_stability_attrs(
|
||||||
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
|
depr.map(|(d, _)| DeprecationEntry::local(d, def_id)),
|
||||||
stab,
|
stab,
|
||||||
@ -565,13 +589,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_missing_or_wrong_const_stability(&self, def_id: LocalDefId, span: Span) {
|
fn check_missing_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;
|
|
||||||
}
|
|
||||||
|
|
||||||
// if the const impl is derived using the `derive_const` attribute,
|
// if the const impl is derived using the `derive_const` attribute,
|
||||||
// then it would be "stable" at least for the impl.
|
// then it would be "stable" at least for the impl.
|
||||||
// We gate usages of it using `feature(const_trait_impl)` anyways
|
// 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())
|
let is_const = self.tcx.is_const_fn(def_id.to_def_id())
|
||||||
|| self.tcx.is_const_trait_impl(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());
|
let descr = self.tcx.def_descr(def_id.to_def_id());
|
||||||
self.tcx.dcx().emit_err(errors::MissingConstStabAttr { span, descr });
|
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.
|
// 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)
|
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());
|
let impl_def_id = self.tcx.hir().get_parent_item(ii.hir_id());
|
||||||
if self.tcx.impl_trait_ref(impl_def_id).is_none() {
|
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_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);
|
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
|
// For implementations of traits, check the stability of each item
|
||||||
// individually as it's possible to have a stable trait with unstable
|
// individually as it's possible to have a stable trait with unstable
|
||||||
// items.
|
// items.
|
||||||
hir::ItemKind::Impl(hir::Impl {
|
hir::ItemKind::Impl(hir::Impl { of_trait: Some(ref t), self_ty, items, .. }) => {
|
||||||
constness,
|
|
||||||
of_trait: Some(ref t),
|
|
||||||
self_ty,
|
|
||||||
items,
|
|
||||||
..
|
|
||||||
}) => {
|
|
||||||
let features = self.tcx.features();
|
let features = self.tcx.features();
|
||||||
if features.staged_api() {
|
if features.staged_api() {
|
||||||
let attrs = self.tcx.hir().attrs(item.hir_id());
|
let attrs = self.tcx.hir().attrs(item.hir_id());
|
||||||
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
|
let stab = attr::find_stability(self.tcx.sess, attrs, item.span);
|
||||||
let const_stab = attr::find_const_stability(
|
let const_stab = attr::find_const_stability(self.tcx.sess, attrs, item.span);
|
||||||
self.tcx.sess,
|
|
||||||
attrs,
|
|
||||||
item.span,
|
|
||||||
matches!(constness, Constness::Const),
|
|
||||||
);
|
|
||||||
|
|
||||||
// If this impl block has an #[unstable] attribute, give an
|
// If this impl block has an #[unstable] attribute, give an
|
||||||
// error if all involved types and traits are stable, because
|
// error if all involved types and traits are stable, because
|
||||||
|
@ -1907,10 +1907,18 @@ impl Subdiagnostic for AddPreciseCapturingForOvercapture {
|
|||||||
diag: &mut Diag<'_, G>,
|
diag: &mut Diag<'_, G>,
|
||||||
_f: &F,
|
_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(
|
diag.multipart_suggestion_verbose(
|
||||||
fluent::trait_selection_precise_capturing_overcaptures,
|
fluent::trait_selection_precise_capturing_overcaptures,
|
||||||
self.suggs,
|
self.suggs,
|
||||||
Applicability::MaybeIncorrect,
|
applicability,
|
||||||
);
|
);
|
||||||
if !self.apit_spans.is_empty() {
|
if !self.apit_spans.is_empty() {
|
||||||
diag.span_note(
|
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
|
# 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).
|
# 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
|
# Set this to "if-unchanged" if you are working on `src/tools`, `tests` or `library` (on CI, `library`
|
||||||
# not been modified.
|
# changes triggers in-tree compiler build) to speed up the build process.
|
||||||
|
#
|
||||||
# Set this to `true` to download unconditionally.
|
# Set this to `true` to download unconditionally.
|
||||||
#download-rustc = false
|
#download-rustc = false
|
||||||
|
|
||||||
|
@ -40,7 +40,7 @@ test = false
|
|||||||
cc = "=1.1.22"
|
cc = "=1.1.22"
|
||||||
cmake = "=0.1.48"
|
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 = { version = "4.4", default-features = false, features = ["std", "usage", "help", "derive", "error-context"] }
|
||||||
clap_complete = "4.4"
|
clap_complete = "4.4"
|
||||||
fd-lock = "4.0"
|
fd-lock = "4.0"
|
||||||
|
@ -295,7 +295,7 @@ macro_rules! lint_any {
|
|||||||
|
|
||||||
lint_any!(
|
lint_any!(
|
||||||
Bootstrap, "src/bootstrap", "bootstrap";
|
Bootstrap, "src/bootstrap", "bootstrap";
|
||||||
BuildHelper, "src/tools/build_helper", "build_helper";
|
BuildHelper, "src/build_helper", "build_helper";
|
||||||
BuildManifest, "src/tools/build-manifest", "build-manifest";
|
BuildManifest, "src/tools/build-manifest", "build-manifest";
|
||||||
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri";
|
CargoMiri, "src/tools/miri/cargo-miri", "cargo-miri";
|
||||||
Clippy, "src/tools/clippy", "clippy";
|
Clippy, "src/tools/clippy", "clippy";
|
||||||
|
@ -1030,7 +1030,7 @@ macro_rules! tool_doc {
|
|||||||
// NOTE: make sure to register these in `Builder::get_step_description`.
|
// NOTE: make sure to register these in `Builder::get_step_description`.
|
||||||
tool_doc!(
|
tool_doc!(
|
||||||
BuildHelper,
|
BuildHelper,
|
||||||
"src/tools/build_helper",
|
"src/build_helper",
|
||||||
rustc_tool = false,
|
rustc_tool = false,
|
||||||
is_library = true,
|
is_library = true,
|
||||||
crates = ["build_helper"]
|
crates = ["build_helper"]
|
||||||
|
@ -1354,7 +1354,7 @@ impl Step for CrateBuildHelper {
|
|||||||
const ONLY_HOSTS: bool = true;
|
const ONLY_HOSTS: bool = true;
|
||||||
|
|
||||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||||
run.path("src/tools/build_helper")
|
run.path("src/build_helper")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn make_run(run: RunConfig<'_>) {
|
fn make_run(run: RunConfig<'_>) {
|
||||||
@ -1372,7 +1372,7 @@ impl Step for CrateBuildHelper {
|
|||||||
Mode::ToolBootstrap,
|
Mode::ToolBootstrap,
|
||||||
host,
|
host,
|
||||||
Kind::Test,
|
Kind::Test,
|
||||||
"src/tools/build_helper",
|
"src/build_helper",
|
||||||
SourceType::InTree,
|
SourceType::InTree,
|
||||||
&[],
|
&[],
|
||||||
);
|
);
|
||||||
|
@ -28,6 +28,24 @@ use crate::utils::cache::{INTERNER, Interned};
|
|||||||
use crate::utils::channel::{self, GitInfo};
|
use crate::utils::channel::{self, GitInfo};
|
||||||
use crate::utils::helpers::{self, exe, output, t};
|
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 {
|
macro_rules! check_ci_llvm {
|
||||||
($name:expr) => {
|
($name:expr) => {
|
||||||
assert!(
|
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
|
// 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"`
|
// functionality for library developers between `download-rustc=true` and `download-rustc="if-unchanged"`
|
||||||
// options.
|
// options.
|
||||||
if CiEnv::is_ci() {
|
if !CiEnv::is_ci() {
|
||||||
files_to_track.push("library");
|
allowed_paths.push(":!library");
|
||||||
}
|
}
|
||||||
|
|
||||||
// Look for a version to compare to based on the current commit.
|
// Look for a version to compare to based on the current commit.
|
||||||
// Only commits merged by bors will have CI artifacts.
|
// Only commits merged by bors will have CI artifacts.
|
||||||
let commit =
|
let commit = match self.last_modified_commit(&allowed_paths, "download-rustc", if_unchanged)
|
||||||
match self.last_modified_commit(&files_to_track, "download-rustc", if_unchanged) {
|
{
|
||||||
Some(commit) => commit,
|
Some(commit) => commit,
|
||||||
None => {
|
None => {
|
||||||
if if_unchanged {
|
if if_unchanged {
|
||||||
return None;
|
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);
|
|
||||||
}
|
}
|
||||||
};
|
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() && {
|
if CiEnv::is_ci() && {
|
||||||
let head_sha =
|
let head_sha =
|
||||||
|
@ -8,7 +8,7 @@ use clap::CommandFactory;
|
|||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
use super::flags::Flags;
|
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::clippy::get_clippy_rules_in_order;
|
||||||
use crate::core::build_steps::llvm;
|
use crate::core::build_steps::llvm;
|
||||||
use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
|
use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
|
||||||
@ -427,3 +427,18 @@ fn jobs_precedence() {
|
|||||||
);
|
);
|
||||||
assert_eq!(config.jobs, Some(123));
|
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 {
|
pub fn parse_stage0_file() -> Stage0 {
|
||||||
let stage0_content = include_str!("../../../stage0");
|
let stage0_content = include_str!("../../stage0");
|
||||||
|
|
||||||
let mut stage0 = Stage0::default();
|
let mut stage0 = Stage0::default();
|
||||||
for line in stage0_content.lines() {
|
for line in stage0_content.lines() {
|
@ -176,9 +176,7 @@ else
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$NO_DOWNLOAD_CI_RUSTC" = "" ]; then
|
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"
|
||||||
#RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.download-rustc=if-unchanged"
|
|
||||||
true
|
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
@ -1011,9 +1011,7 @@ fn render_stability_since_raw_with_extra(
|
|||||||
// don't display const unstable if entirely unstable
|
// don't display const unstable if entirely unstable
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let unstable = if let Some(n) = issue
|
let unstable = if let Some(n) = issue {
|
||||||
&& let Some(feature) = feature
|
|
||||||
{
|
|
||||||
format!(
|
format!(
|
||||||
"<a \
|
"<a \
|
||||||
href=\"https://github.com/rust-lang/rust/issues/{n}\" \
|
href=\"https://github.com/rust-lang/rust/issues/{n}\" \
|
||||||
|
@ -7,7 +7,7 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
anyhow = "1.0.34"
|
anyhow = "1.0.34"
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../../build_helper" }
|
||||||
curl = "0.4.38"
|
curl = "0.4.38"
|
||||||
indexmap = { version = "2.0.0", features = ["serde"] }
|
indexmap = { version = "2.0.0", features = ["serde"] }
|
||||||
serde = { version = "1.0.125", features = ["derive"] }
|
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)
|
msrv.meets(const_stab_rust_version)
|
||||||
} else {
|
} else {
|
||||||
// Unstable const fn, check if the feature is enabled. We need both the regular stability
|
// Unstable const fn, check if the feature is enabled.
|
||||||
// feature and (if set) the const stability feature to const-call this function.
|
tcx.features().enabled(const_stab.feature) && msrv.current().is_none()
|
||||||
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()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,7 @@ unified-diff = "0.2.1"
|
|||||||
getopts = "0.2"
|
getopts = "0.2"
|
||||||
indexmap = "2.0.0"
|
indexmap = "2.0.0"
|
||||||
miropt-test-tools = { path = "../miropt-test-tools" }
|
miropt-test-tools = { path = "../miropt-test-tools" }
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../../build_helper" }
|
||||||
tracing = "0.1"
|
tracing = "0.1"
|
||||||
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
|
tracing-subscriber = { version = "0.3.3", default-features = false, features = ["fmt", "env-filter", "smallvec", "parking_lot", "ansi"] }
|
||||||
regex = "1.0"
|
regex = "1.0"
|
||||||
|
@ -35,6 +35,7 @@ const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
|
|||||||
"ignore-64bit",
|
"ignore-64bit",
|
||||||
"ignore-aarch64",
|
"ignore-aarch64",
|
||||||
"ignore-aarch64-unknown-linux-gnu",
|
"ignore-aarch64-unknown-linux-gnu",
|
||||||
|
"ignore-aix",
|
||||||
"ignore-android",
|
"ignore-android",
|
||||||
"ignore-apple",
|
"ignore-apple",
|
||||||
"ignore-arm",
|
"ignore-arm",
|
||||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../../build_helper" }
|
||||||
env_logger = "0.11"
|
env_logger = "0.11"
|
||||||
log = "0.4"
|
log = "0.4"
|
||||||
anyhow = { version = "1", features = ["backtrace"] }
|
anyhow = { version = "1", features = ["backtrace"] }
|
||||||
|
@ -10,7 +10,7 @@ similar = "2.5.0"
|
|||||||
wasmparser = { version = "0.216", default-features = false, features = ["std"] }
|
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
|
regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
|
||||||
gimli = "0.31.0"
|
gimli = "0.31.0"
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../../build_helper" }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ use crate::command::Command;
|
|||||||
use crate::env::env_var;
|
use crate::env::env_var;
|
||||||
use crate::path_helpers::cwd;
|
use crate::path_helpers::cwd;
|
||||||
use crate::util::set_host_rpath;
|
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
|
/// Construct a new `rustc` invocation. This will automatically set the library
|
||||||
/// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this.
|
/// search path as `-L cwd()`. Use [`bare_rustc`] to avoid this.
|
||||||
@ -346,7 +346,7 @@ impl Rustc {
|
|||||||
// endif
|
// endif
|
||||||
// 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
|
// 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
|
// 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
|
// 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
|
// 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
|
// link the parts of libstdc++ that we actually use, which doesn't include
|
||||||
// the dependency on the pthreads DLL.
|
// 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() {
|
} else if is_darwin() {
|
||||||
Some("-lc++")
|
self.cmd.arg("-lc++");
|
||||||
|
} else if is_aix() {
|
||||||
|
self.cmd.arg("-lc++");
|
||||||
|
self.cmd.arg("-lc++abi");
|
||||||
} else {
|
} else {
|
||||||
match &uname()[..] {
|
if !matches!(&uname()[..], "FreeBSD" | "SunOS" | "OpenBSD") {
|
||||||
"FreeBSD" | "SunOS" | "OpenBSD" => None,
|
self.cmd.arg("-lstdc++");
|
||||||
_ => Some("-lstdc++"),
|
};
|
||||||
}
|
|
||||||
};
|
};
|
||||||
if let Some(flag) = flag {
|
|
||||||
self.cmd.arg(flag);
|
|
||||||
}
|
|
||||||
self
|
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};
|
pub use run::{cmd, run, run_fail, run_with_args};
|
||||||
|
|
||||||
/// Helpers for checking target information.
|
/// 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.
|
/// Helpers for building names of output artifacts that are potentially target-specific.
|
||||||
pub use artifact_names::{
|
pub use artifact_names::{
|
||||||
|
@ -28,6 +28,12 @@ pub fn is_darwin() -> bool {
|
|||||||
target().contains("darwin")
|
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.
|
/// Get the target OS on Apple operating systems.
|
||||||
#[must_use]
|
#[must_use]
|
||||||
pub fn apple_os() -> &'static str {
|
pub fn apple_os() -> &'static str {
|
||||||
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../../build_helper" }
|
||||||
compiletest = { path = "../compiletest" }
|
compiletest = { path = "../compiletest" }
|
||||||
getopts = "0.2"
|
getopts = "0.2"
|
||||||
walkdir = "2"
|
walkdir = "2"
|
||||||
|
@ -5,4 +5,4 @@ edition = "2021"
|
|||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
glob = "0.3.0"
|
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
|
autobins = false
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
build_helper = { path = "../build_helper" }
|
build_helper = { path = "../../build_helper" }
|
||||||
cargo_metadata = "0.18"
|
cargo_metadata = "0.18"
|
||||||
regex = "1"
|
regex = "1"
|
||||||
miropt-test-tools = { path = "../miropt-test-tools" }
|
miropt-test-tools = { path = "../miropt-test-tools" }
|
||||||
|
@ -16,13 +16,13 @@ const fn const_main() {
|
|||||||
unsafe {
|
unsafe {
|
||||||
unstable_intrinsic::size_of_val(&x);
|
unstable_intrinsic::size_of_val(&x);
|
||||||
//~^ERROR: unstable library feature `unstable`
|
//~^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);
|
unstable_intrinsic::min_align_of_val(&x);
|
||||||
//~^ERROR: unstable library feature `unstable`
|
//~^ERROR: unstable library feature `unstable`
|
||||||
//~|ERROR: not yet stable as a const intrinsic
|
//~|ERROR: not yet stable as a const intrinsic
|
||||||
|
|
||||||
size_of_val(&x);
|
size_of_val(&x);
|
||||||
//~^ERROR: cannot be (indirectly) exposed to stable
|
//~^ERROR: cannot use `#[feature(local)]`
|
||||||
min_align_of_val(&x);
|
min_align_of_val(&x);
|
||||||
//~^ERROR: cannot use `#[feature(local)]`
|
//~^ERROR: cannot use `#[feature(local)]`
|
||||||
}
|
}
|
||||||
@ -59,6 +59,6 @@ mod fallback {
|
|||||||
#[rustc_intrinsic]
|
#[rustc_intrinsic]
|
||||||
const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
|
const unsafe fn copy<T>(src: *const T, _dst: *mut T, _count: usize) {
|
||||||
super::size_of_val(src);
|
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
|
= 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
|
= 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
|
--> $DIR/const-unstable-intrinsic.rs:17:9
|
||||||
|
|
|
|
||||||
LL | unstable_intrinsic::size_of_val(&x);
|
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
|
error: `min_align_of_val` is not yet stable as a const intrinsic
|
||||||
--> $DIR/const-unstable-intrinsic.rs:20:9
|
--> $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
|
= 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
|
--> $DIR/const-unstable-intrinsic.rs:24:9
|
||||||
|
|
|
|
||||||
LL | size_of_val(&x);
|
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)]`
|
error: const function that might be (indirectly) exposed to stable cannot use `#[feature(local)]`
|
||||||
--> $DIR/const-unstable-intrinsic.rs:26:9
|
--> $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)
|
= 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
|
--> $DIR/const-unstable-intrinsic.rs:61:9
|
||||||
|
|
|
|
||||||
LL | super::size_of_val(src);
|
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
|
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")]
|
#[rustc_const_stable(feature = "barfoo_const", since = "1.0.0")]
|
||||||
pub const fn barfoo_unstable() {}
|
pub const fn barfoo_unstable() {}
|
||||||
//~^ ERROR can only be applied to functions that are declared `#[stable]`
|
//~^ 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() {}
|
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`
|
error: aborting due to 8 previous errors
|
||||||
--> $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
|
|
||||||
|
|
||||||
|
@ -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
|
error: can't mark as unstable using an already stable feature
|
||||||
--> $DIR/unstable-attribute-rejects-already-stable-features.rs:6:1
|
--> $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")]
|
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
|
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]
|
[assign.adhoc_groups]
|
||||||
compiler-team = [
|
compiler = [
|
||||||
"@cjgillot",
|
|
||||||
"@compiler-errors",
|
|
||||||
"@petrochenkov",
|
|
||||||
"@davidtwco",
|
|
||||||
"@estebank",
|
|
||||||
"@lcnr",
|
|
||||||
"@oli-obk",
|
|
||||||
"@pnkfelix",
|
|
||||||
"@wesleywiser",
|
|
||||||
]
|
|
||||||
compiler-team-contributors = [
|
|
||||||
"@TaKO8Ki",
|
|
||||||
"@Nadrieril",
|
|
||||||
"@nnethercote",
|
|
||||||
"@fmease",
|
|
||||||
"@fee1-dead",
|
|
||||||
"@jieyouxu",
|
|
||||||
"@BoxyUwU",
|
"@BoxyUwU",
|
||||||
"@chenyukang",
|
"@chenyukang",
|
||||||
]
|
"@cjgillot",
|
||||||
compiler = [
|
"@compiler-errors",
|
||||||
"compiler-team",
|
"@davidtwco",
|
||||||
"compiler-team-contributors",
|
"@estebank",
|
||||||
|
"@fee1-dead",
|
||||||
|
"@fmease",
|
||||||
|
"@jieyouxu",
|
||||||
|
"@lcnr",
|
||||||
|
"@Nadrieril",
|
||||||
|
"@nnethercote",
|
||||||
|
"@oli-obk",
|
||||||
|
"@petrochenkov",
|
||||||
|
"@pnkfelix",
|
||||||
|
"@TaKO8Ki",
|
||||||
|
"@wesleywiser",
|
||||||
]
|
]
|
||||||
libs = [
|
libs = [
|
||||||
"@cuviper",
|
"@cuviper",
|
||||||
|
Loading…
Reference in New Issue
Block a user