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 bc6c3b0

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

File tree

8 files changed

+47
-49
lines changed

8 files changed

+47
-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<'_> {
@@ -429,10 +429,10 @@ pub fn find_const_stability(
429429
// record this, and so that's what we do for all `const fn` in a staged_api crate.
430430
if is_const_fn || const_stable_indirect.is_some() {
431431
stab_spans = ConstStabilitySpans(smallvec![(
432-
ConstStabilityLevel::Implicit,
432+
ConstStabilityLevel::ImplicitUnstable,
433433
const_stable_indirect.unwrap_or(DUMMY_SP)
434434
)]);
435-
ConstStabilityLevel::Implicit
435+
ConstStabilityLevel::ImplicitUnstable
436436
} else {
437437
return None;
438438
}

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

Lines changed: 18 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ use rustc_mir_dataflow::storage::always_storage_live_locals;
2323
use rustc_span::{DUMMY_SP, Span, Symbol, sym};
2424
use rustc_trait_selection::error_reporting::InferCtxtErrorExt;
2525
use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt};
26-
use smallvec::SmallVec;
2726
use tracing::{debug, instrument, trace};
2827

2928
use super::ops::{self, NonConstOp, Status};
@@ -720,7 +719,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
720719
self.check_op(ops::IntrinsicNonConst { name: intrinsic.name });
721720
}
722721
Some(ConstStability {
723-
level: ConstStabilityLevel::Implicit,
722+
level: ConstStabilityLevel::ImplicitUnstable,
724723
const_stable_indirect,
725724
..
726725
}) => {
@@ -776,7 +775,10 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
776775
Some(ConstStability { level: ConstStabilityLevel::Stable { .. }, .. }) => {
777776
// All good.
778777
}
779-
None | Some(ConstStability { level: ConstStabilityLevel::Implicit, .. }) => {
778+
None
779+
| Some(ConstStability {
780+
level: ConstStabilityLevel::ImplicitUnstable, ..
781+
}) => {
780782
// This doesn't need a separate const-stability check -- const-stability equals
781783
// regular stability, and regular stability is checked separately.
782784
// However, we *do* have to worry about *recursive* const stability.
@@ -799,43 +801,33 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
799801

800802
// We only honor `span.allows_unstable` aka `#[allow_internal_unstable]` if
801803
// the callee is safe to expose, to avoid bypassing recursive stability.
802-
let is_allowed_unstable = |u: &rustc_attr::Unstability| {
803-
callee_safe_to_expose_on_stable
804-
&& (self.span.allows_unstable(u.feature)
805-
|| u.implied_by.is_some_and(|f| self.span.allows_unstable(f)))
806-
};
807-
let mut needs_check =
808-
unstables.iter().filter(|u| !is_allowed_unstable(u)).peekable();
809-
if needs_check.peek().is_none() {
804+
if callee_safe_to_expose_on_stable
805+
&& unstables.iter().all(|u| {
806+
self.span.allows_unstable(u.feature)
807+
|| u.implied_by.is_some_and(|f| self.span.allows_unstable(f))
808+
})
809+
{
810810
return;
811811
}
812812

813813
// We can't use `check_op` to check whether the feature is enabled because
814814
// the logic is a bit different than elsewhere: local functions don't need
815815
// the feature gate, and there might be an "implied" gate that also suffices
816816
// to allow this.
817-
let is_feature_enabled = |u:&rustc_attr::Unstability| {
818-
callee.is_local()
819-
|| tcx.features().enabled(u.feature)
820-
|| u.implied_by.is_some_and(|f| tcx.features().enabled(f))
821-
};
817+
let features_enabled = callee.is_local()
818+
|| unstables.iter().all(|u| {
819+
tcx.features().enabled(u.feature)
820+
|| u.implied_by.is_some_and(|f| tcx.features().enabled(f))
821+
});
822822
// We do *not* honor this if we are in the "danger zone": we have to enforce
823823
// recursive const-stability and the callee is not safe-to-expose. In that
824824
// case we need `check_op` to do the check.
825825
let danger_zone = !callee_safe_to_expose_on_stable
826826
&& self.enforce_recursive_const_stability();
827-
let missing_features: SmallVec<[_; 1]> = if danger_zone {
828-
needs_check.map(|u| u.into()).collect()
829-
} else {
830-
needs_check
831-
.filter(|u| !is_feature_enabled(u))
832-
.map(|u| u.into())
833-
.collect()
834-
};
835-
if !missing_features.is_empty() {
827+
if danger_zone || !features_enabled {
836828
self.check_op(ops::FnCallUnstable {
837829
def_id: callee,
838-
features: missing_features,
830+
features: unstables.iter().map(|u| u.into()).collect(),
839831
reason: *reason,
840832
safe_to_expose_on_stable: callee_safe_to_expose_on_stable,
841833
});

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

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

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

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

328328
fn build_error(&self, ccx: &ConstCx<'_, 'tcx>, span: Span) -> Diag<'tcx> {
329+
// Only report the features that aren't already enabled.
330+
let missing_features = Vec::from_iter(
331+
self.features.iter().filter(|d| !ccx.tcx.features().enabled(d.feature)).copied(),
332+
);
329333
ccx.dcx().create_err(errors::UnstableConstFn {
330334
span,
331335
def_path: ccx.tcx.def_path_str(self.def_id),
332-
features: stability::unstable_message(&self.features, self.reason.to_opt_reason())
336+
features: stability::unstable_message(&missing_features, self.reason.to_opt_reason())
333337
.hide_features_on_nightly(&ccx.tcx.sess),
334-
issues: stability::unstable_issues(&self.features),
338+
issues: stability::unstable_issues(&missing_features),
335339
nightly_subdiags: stability::unstable_nightly_subdiags(
336340
&ccx.tcx.sess,
337-
&self.features,
341+
&missing_features,
338342
None,
339343
),
340344
})
@@ -378,15 +382,19 @@ impl<'tcx> NonConstOp<'tcx> for IntrinsicUnstable {
378382
}
379383

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

‎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
@@ -616,7 +616,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> {
616616
let is_stable =
617617
self.tcx.lookup_stability(def_id).is_some_and(|stability| stability.level.is_stable());
618618
let missing_const_stability_attribute =
619-
self.tcx.lookup_const_stability(def_id).is_none_or(|s| s.is_implicit());
619+
self.tcx.lookup_const_stability(def_id).is_none_or(|s| s.is_implicit_unstable());
620620

621621
if is_const && is_stable && missing_const_stability_attribute {
622622
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
@@ -1701,14 +1701,12 @@ pub(crate) fn print_constness_with_space(
17011701
| (_, None)
17021702
// ...or when const unstable, but overall unstable too...
17031703
| (None, Some(ConstStability { level: ConstStabilityLevel::Unstable { .. }, .. }))
1704-
// ...or when a const stability level was not explicitly provided, and overall unstable
1705-
| (None, Some(ConstStability { level: ConstStabilityLevel::Implicit, .. })) => {
1704+
| (None, Some(ConstStability { level: ConstStabilityLevel::ImplicitUnstable, .. })) => {
17061705
"const "
17071706
}
17081707
// const unstable (and overall stable)...
17091708
(Some(_), Some(ConstStability { level: ConstStabilityLevel::Unstable { .. }, .. }))
1710-
// ...or without an explicit const stability level (and overall stable)
1711-
| (Some(_), Some(ConstStability { level: ConstStabilityLevel::Implicit, .. })) => "",
1709+
| (Some(_), Some(ConstStability { level: ConstStabilityLevel::ImplicitUnstable, .. })) => "",
17121710
},
17131711
// not const
17141712
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 によって変換されたページ (->オリジナル) /