Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit b9af36e

Browse files
committed
Clarify/fix const-unstable semantics in the presence of multiple unstable features
1 parent d9915da commit b9af36e

File tree

8 files changed

+50
-49
lines changed

8 files changed

+50
-49
lines changed

‎compiler/rustc_attr/src/builtin.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ impl Stability {
9696
}
9797

9898
/// Represents the `#[rustc_const_unstable]` and `#[rustc_const_stable]` attributes.
99+
/// For details see [the dev guide](https://rustc-dev-guide.rust-lang.org/stability.html#rustc_const_unstable).
99100
#[derive(Encodable, Decodable, Clone, Debug, PartialEq, Eq, Hash)]
100101
#[derive(HashStable_Generic)]
101102
pub struct ConstStability {
@@ -115,8 +116,8 @@ impl ConstStability {
115116
self.level.is_const_stable()
116117
}
117118

118-
pub fn is_implicit(&self) -> bool {
119-
self.level.is_implicit()
119+
pub fn is_implicit_unstable(&self) -> bool {
120+
self.level.is_implicit_unstable()
120121
}
121122

122123
pub fn unstable_features(&self) -> impl Iterator<Item = Symbol> + use<'_> {
@@ -154,7 +155,6 @@ pub enum StabilityLevel {
154155
}
155156

156157
/// The available const-stability levels for const functions.
157-
/// For details see [#131349](https://github.com/rust-lang/rust/pull/131349).
158158
#[derive(Encodable, Decodable, PartialEq, Clone, Debug, Eq, Hash)]
159159
#[derive(HashStable_Generic)]
160160
pub enum ConstStabilityLevel {
@@ -169,7 +169,7 @@ pub enum ConstStabilityLevel {
169169
},
170170
/// For functions with no explicit const-stability attribute that require checking recursive
171171
/// const stability. This is either an unmarked const fn or a `const_stable_indirect` intrinsic.
172-
Implicit,
172+
ImplicitUnstable,
173173
}
174174

175175
/// Rust release in which a feature is stabilized.
@@ -224,15 +224,15 @@ impl StabilityLevel {
224224

225225
impl ConstStabilityLevel {
226226
pub fn is_const_unstable(&self) -> bool {
227-
matches!(self, ConstStabilityLevel::Unstable { .. })
227+
matches!(self, ConstStabilityLevel::Unstable { .. } | ConstStabilityLevel::ImplicitUnstable)
228228
}
229229

230230
pub fn is_const_stable(&self) -> bool {
231231
matches!(self, ConstStabilityLevel::Stable { .. })
232232
}
233233

234-
pub fn is_implicit(&self) -> bool {
235-
matches!(self, ConstStabilityLevel::Implicit)
234+
pub fn is_implicit_unstable(&self) -> bool {
235+
matches!(self, ConstStabilityLevel::ImplicitUnstable)
236236
}
237237

238238
pub fn unstable_features(&self) -> impl Iterator<Item = Symbol> + use<'_> {
@@ -428,10 +428,10 @@ pub fn find_const_stability(
428428
// record this, and so that's what we do for all `const fn` in a staged_api crate.
429429
if is_const_fn || const_stable_indirect.is_some() {
430430
stab_spans = ConstStabilitySpans(smallvec![(
431-
ConstStabilityLevel::Implicit,
431+
ConstStabilityLevel::ImplicitUnstable,
432432
const_stable_indirect.unwrap_or(DUMMY_SP)
433433
)]);
434-
ConstStabilityLevel::Implicit
434+
ConstStabilityLevel::ImplicitUnstable
435435
} else {
436436
return None;
437437
}

‎compiler/rustc_const_eval/src/check_consts/check.rs

Lines changed: 21 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use rustc_span::{Span, Symbol, sym};
2323
use rustc_trait_selection::traits::{
2424
Obligation, ObligationCause, ObligationCauseCode, ObligationCtxt,
2525
};
26-
use smallvec::SmallVec;
2726
use tracing::{debug, instrument, trace};
2827

2928
use super::ops::{self, NonConstOp, Status};
@@ -761,7 +760,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
761760
// Non-const intrinsic.
762761
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
763762
}
764-
Some(ConstStability { level: ConstStabilityLevel::Implicit, .. }) => {
763+
Some(ConstStability {
764+
level: ConstStabilityLevel::ImplicitUnstable,
765+
..
766+
}) => {
765767
// Intrinsic does not need a separate feature gate (we rely on the
766768
// regular stability checker). However, we have to worry about recursive
767769
// const stability.
@@ -815,7 +817,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
815817
Some(ConstStability { level: ConstStabilityLevel::Stable { .. }, .. }) => {
816818
// All good.
817819
}
818-
None | Some(ConstStability { level: ConstStabilityLevel::Implicit, .. }) => {
820+
None
821+
| Some(ConstStability {
822+
level: ConstStabilityLevel::ImplicitUnstable, ..
823+
}) => {
819824
// This doesn't need a separate const-stability check -- const-stability equals
820825
// regular stability, and regular stability is checked separately.
821826
// However, we *do* have to worry about *recursive* const stability.
@@ -838,43 +843,33 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
838843

839844
// We only honor `span.allows_unstable` aka `#[allow_internal_unstable]` if
840845
// the callee is safe to expose, to avoid bypassing recursive stability.
841-
let is_allowed_unstable = |u: &rustc_attr::Unstability| {
842-
callee_safe_to_expose_on_stable
843-
&& (self.span.allows_unstable(u.feature)
844-
|| u.implied_by.is_some_and(|f| self.span.allows_unstable(f)))
845-
};
846-
let mut needs_check =
847-
unstables.iter().filter(|u| !is_allowed_unstable(u)).peekable();
848-
if needs_check.peek().is_none() {
846+
if callee_safe_to_expose_on_stable
847+
&& unstables.iter().all(|u| {
848+
self.span.allows_unstable(u.feature)
849+
|| u.implied_by.is_some_and(|f| self.span.allows_unstable(f))
850+
})
851+
{
849852
return;
850853
}
851854

852855
// We can't use `check_op` to check whether the feature is enabled because
853856
// the logic is a bit different than elsewhere: local functions don't need
854857
// the feature gate, and there might be an "implied" gate that also suffices
855858
// to allow this.
856-
let is_feature_enabled = |u:&rustc_attr::Unstability| {
857-
callee.is_local()
858-
|| tcx.features().enabled(u.feature)
859-
|| u.implied_by.is_some_and(|f| tcx.features().enabled(f))
860-
};
859+
let features_enabled = callee.is_local()
860+
|| unstables.iter().all(|u| {
861+
tcx.features().enabled(u.feature)
862+
|| u.implied_by.is_some_and(|f| tcx.features().enabled(f))
863+
});
861864
// We do *not* honor this if we are in the "danger zone": we have to enforce
862865
// recursive const-stability and the callee is not safe-to-expose. In that
863866
// case we need `check_op` to do the check.
864867
let danger_zone = !callee_safe_to_expose_on_stable
865868
&& self.enforce_recursive_const_stability();
866-
let missing_features: SmallVec<[_; 1]> = if danger_zone {
867-
needs_check.map(|u| u.into()).collect()
868-
} else {
869-
needs_check
870-
.filter(|u| !is_feature_enabled(u))
871-
.map(|u| u.into())
872-
.collect()
873-
};
874-
if !missing_features.is_empty() {
869+
if danger_zone || !features_enabled {
875870
self.check_op(ops::FnCallUnstable {
876871
def_id: callee,
877-
features: missing_features,
872+
features: unstables.iter().map(|u| u.into()).collect(),
878873
reason: *reason,
879874
safe_to_expose_on_stable: callee_safe_to_expose_on_stable,
880875
});

‎compiler/rustc_const_eval/src/check_consts/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ pub fn is_safe_to_expose_on_stable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> b
116116
Some(stab) => {
117117
// We consider things safe-to-expose if they are stable, if they don't have any explicit
118118
// const stability attribute, or if they are marked as `const_stable_indirect`.
119-
stab.is_const_stable() || stab.is_implicit() || stab.const_stable_indirect
119+
stab.is_const_stable() || stab.is_implicit_unstable() || stab.const_stable_indirect
120120
}
121121
}
122122
}

‎compiler/rustc_const_eval/src/check_consts/ops.rs

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -325,15 +325,19 @@ impl<'tcx> NonConstOp<'tcx> for FnCallUnstable {
325325
}
326326

327327
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
328+
// Only report the features that aren't already enabled.
329+
let missing_features = Vec::from_iter(
330+
self.features.iter().filter(|d| !ccx.tcx.features().enabled(d.feature)).copied(),
331+
);
328332
ccx.dcx().create_err(errors::UnstableConstFn {
329333
span,
330334
def_path: ccx.tcx.def_path_str(self.def_id),
331-
features: stability::unstable_message(&self.features, self.reason.to_opt_reason())
335+
features: stability::unstable_message(&missing_features, self.reason.to_opt_reason())
332336
.hide_features_on_nightly(&ccx.tcx.sess),
333-
issues: stability::unstable_issues(&self.features),
337+
issues: stability::unstable_issues(&missing_features),
334338
nightly_subdiags: stability::unstable_nightly_subdiags(
335339
&ccx.tcx.sess,
336-
&self.features,
340+
&missing_features,
337341
None,
338342
),
339343
})
@@ -377,15 +381,19 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
377381
}
378382

379383
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
384+
// Only report the features that aren't already enabled.
385+
let missing_features = Vec::from_iter(
386+
self.features.iter().filter(|d| !ccx.tcx.features().enabled(d.feature)).copied(),
387+
);
380388
ccx.dcx().create_err(errors::UnstableIntrinsic {
381389
span,
382390
name: self.name,
383-
features: stability::unstable_message(&self.features, self.reason.to_opt_reason())
391+
features: stability::unstable_message(&missing_features, self.reason.to_opt_reason())
384392
.hide_features_on_nightly(&ccx.tcx.sess),
385-
issues: stability::unstable_issues(&self.features),
393+
issues: stability::unstable_issues(&missing_features),
386394
nightly_subdiags: stability::unstable_nightly_subdiags(
387395
&ccx.tcx.sess,
388-
&self.features,
396+
&missing_features,
389397
None,
390398
),
391399
})

‎compiler/rustc_middle/src/middle/stability.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -362,7 +362,7 @@ pub enum EvalResult {
362362
}
363363

364364
/// An instance of a disabled feature required for an unstable item
365-
#[derive(Debug)]
365+
#[derive(Clone,Copy,Debug)]
366366
pub struct EvalDenial {
367367
pub feature: Symbol,
368368
pub issue: Option<NonZero<u32>>,

‎compiler/rustc_passes/src/stability.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
600600
let is_stable =
601601
self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
602602
let missing_const_stability_attribute =
603-
self.tcx.lookup_const_stability(def_id).is_none_or(|s| s.is_implicit());
603+
self.tcx.lookup_const_stability(def_id).is_none_or(|s| s.is_implicit_unstable());
604604

605605
if is_const && is_stable && missing_const_stability_attribute {
606606
let descr = self.tcx.def_descr(def_id.to_def_id());

‎src/librustdoc/html/format.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1700,14 +1700,12 @@ pub(crate) fn print_constness_with_space(
17001700
| (_, None)
17011701
// ...or when const unstable, but overall unstable too...
17021702
| (None, Some(ConstStability { level: ConstStabilityLevel::Unstable { .. }, .. }))
1703-
// ...or when a const stability level was not explicitly provided, and overall unstable
1704-
| (None, Some(ConstStability { level: ConstStabilityLevel::Implicit, .. })) => {
1703+
| (None, Some(ConstStability { level: ConstStabilityLevel::ImplicitUnstable, .. })) => {
17051704
"const "
17061705
}
17071706
// const unstable (and overall stable)...
17081707
(Some(_), Some(ConstStability { level: ConstStabilityLevel::Unstable { .. }, .. }))
1709-
// ...or without an explicit const stability level (and overall stable)
1710-
| (Some(_), Some(ConstStability { level: ConstStabilityLevel::Implicit, .. })) => "",
1708+
| (Some(_), Some(ConstStability { level: ConstStabilityLevel::ImplicitUnstable, .. })) => "",
17111709
},
17121710
// not const
17131711
hir::Constness::NotConst => "",

‎src/librustdoc/html/render/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1041,7 +1041,7 @@ fn render_stability_since_raw_with_extra(
10411041
Some((String::from("const unstable"), format!("const: {unstable}")))
10421042
}
10431043
}
1044-
Some(ConstStability { level: ConstStabilityLevel::Implicit, .. }) => {
1044+
Some(ConstStability { level: ConstStabilityLevel::ImplicitUnstable, .. }) => {
10451045
// No explicit const-stability annotation was provided. Treat it as const-unstable.
10461046
if stable_version.is_none() {
10471047
None

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /