Enforce syntactical stability of const traits in HIR
This commit is contained in:
parent
8c39ce5b4f
commit
2743df848b
21 changed files with 279 additions and 38 deletions
|
@ -30,6 +30,14 @@ pub enum StabilityLevel {
|
|||
Stable,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone)]
|
||||
pub enum UnstableKind {
|
||||
/// Enforcing regular stability of an item
|
||||
Regular,
|
||||
/// Enforcing const stability of an item
|
||||
Const(Span),
|
||||
}
|
||||
|
||||
/// An entry in the `depr_map`.
|
||||
#[derive(Copy, Clone, HashStable, Debug, Encodable, Decodable)]
|
||||
pub struct DeprecationEntry {
|
||||
|
@ -108,10 +116,16 @@ pub fn report_unstable(
|
|||
is_soft: bool,
|
||||
span: Span,
|
||||
soft_handler: impl FnOnce(&'static Lint, Span, String),
|
||||
kind: UnstableKind,
|
||||
) {
|
||||
let qual = match kind {
|
||||
UnstableKind::Regular => "",
|
||||
UnstableKind::Const(_) => " const",
|
||||
};
|
||||
|
||||
let msg = match reason {
|
||||
Some(r) => format!("use of unstable library feature `{feature}`: {r}"),
|
||||
None => format!("use of unstable library feature `{feature}`"),
|
||||
Some(r) => format!("use of unstable{qual} library feature `{feature}`: {r}"),
|
||||
None => format!("use of unstable{qual} library feature `{feature}`"),
|
||||
};
|
||||
|
||||
if is_soft {
|
||||
|
@ -121,6 +135,9 @@ pub fn report_unstable(
|
|||
if let Some((inner_types, msg, sugg, applicability)) = suggestion {
|
||||
err.span_suggestion(inner_types, msg, sugg, applicability);
|
||||
}
|
||||
if let UnstableKind::Const(kw) = kind {
|
||||
err.span_label(kw, "trait is not stable as const yet");
|
||||
}
|
||||
err.emit();
|
||||
}
|
||||
}
|
||||
|
@ -587,6 +604,7 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
is_soft,
|
||||
span,
|
||||
soft_handler,
|
||||
UnstableKind::Regular,
|
||||
),
|
||||
EvalResult::Unmarked => unmarked(span, def_id),
|
||||
}
|
||||
|
@ -594,6 +612,73 @@ impl<'tcx> TyCtxt<'tcx> {
|
|||
is_allowed
|
||||
}
|
||||
|
||||
/// This function is analogous to `check_optional_stability` but with the logic in
|
||||
/// `eval_stability_allow_unstable` inlined, and which operating on const stability
|
||||
/// instead of regular stability.
|
||||
///
|
||||
/// This enforces *syntactical* const stability of const traits. In other words,
|
||||
/// it enforces the ability to name `~const`/`const` traits in trait bounds in various
|
||||
/// syntax positions in HIR (including in the trait of an impl header).
|
||||
pub fn check_const_stability(self, def_id: DefId, span: Span, const_kw_span: Span) {
|
||||
let is_staged_api = self.lookup_stability(def_id.krate.as_def_id()).is_some();
|
||||
if !is_staged_api {
|
||||
return;
|
||||
}
|
||||
|
||||
// Only the cross-crate scenario matters when checking unstable APIs
|
||||
let cross_crate = !def_id.is_local();
|
||||
if !cross_crate {
|
||||
return;
|
||||
}
|
||||
|
||||
let stability = self.lookup_const_stability(def_id);
|
||||
debug!(
|
||||
"stability: \
|
||||
inspecting def_id={:?} span={:?} of stability={:?}",
|
||||
def_id, span, stability
|
||||
);
|
||||
|
||||
match stability {
|
||||
Some(ConstStability {
|
||||
level: attr::StabilityLevel::Unstable { reason, issue, is_soft, implied_by, .. },
|
||||
feature,
|
||||
..
|
||||
}) => {
|
||||
assert!(!is_soft);
|
||||
|
||||
if span.allows_unstable(feature) {
|
||||
debug!("body stability: skipping span={:?} since it is internal", span);
|
||||
return;
|
||||
}
|
||||
if self.features().enabled(feature) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If this item was previously part of a now-stabilized feature which is still
|
||||
// enabled (i.e. the user hasn't removed the attribute for the stabilized feature
|
||||
// yet) then allow use of this item.
|
||||
if let Some(implied_by) = implied_by
|
||||
&& self.features().enabled(implied_by)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
report_unstable(
|
||||
self.sess,
|
||||
feature,
|
||||
reason.to_opt_reason(),
|
||||
issue,
|
||||
None,
|
||||
false,
|
||||
span,
|
||||
|_, _, _| {},
|
||||
UnstableKind::Const(const_kw_span),
|
||||
);
|
||||
}
|
||||
Some(_) | None => {}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lookup_deprecation(self, id: DefId) -> Option<Deprecation> {
|
||||
self.lookup_deprecation_entry(id).map(|depr| depr.attr)
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue