@@ -30,6 +30,14 @@ pub enum StabilityLevel {
3030 Stable ,
3131}
3232
33+ #[ derive( Copy , Clone ) ]
34+ pub enum UnstableKind {
35+ /// Enforcing regular stability of an item
36+ Regular ,
37+ /// Enforcing const stability of an item
38+ Const ( Span ) ,
39+ }
40+
3341/// An entry in the `depr_map`.
3442#[ derive( Copy , Clone , HashStable , Debug , Encodable , Decodable ) ]
3543pub struct DeprecationEntry {
@@ -108,10 +116,16 @@ pub fn report_unstable(
108116 is_soft : bool ,
109117 span : Span ,
110118 soft_handler : impl FnOnce ( & ' static Lint , Span , String ) ,
119+ kind : UnstableKind ,
111120) {
121+ let qual = match kind {
122+ UnstableKind :: Regular => "" ,
123+ UnstableKind :: Const ( _) => " const" ,
124+ } ;
125+
112126 let msg = match reason {
113- Some ( r) => format ! ( "use of unstable library feature `{feature}`: {r}" ) ,
114- None => format ! ( "use of unstable library feature `{feature}`" ) ,
127+ Some ( r) => format ! ( "use of unstable{qual} library feature `{feature}`: {r}" ) ,
128+ None => format ! ( "use of unstable{qual} library feature `{feature}`" ) ,
115129 } ;
116130
117131 if is_soft {
@@ -121,6 +135,9 @@ pub fn report_unstable(
121135 if let Some ( ( inner_types, msg, sugg, applicability) ) = suggestion {
122136 err. span_suggestion ( inner_types, msg, sugg, applicability) ;
123137 }
138+ if let UnstableKind :: Const ( kw) = kind {
139+ err. span_label ( kw, "trait is not stable as const yet" ) ;
140+ }
124141 err. emit ( ) ;
125142 }
126143}
@@ -587,13 +604,81 @@ impl<'tcx> TyCtxt<'tcx> {
587604 is_soft,
588605 span,
589606 soft_handler,
607+ UnstableKind :: Regular ,
590608 ) ,
591609 EvalResult :: Unmarked => unmarked ( span, def_id) ,
592610 }
593611
594612 is_allowed
595613 }
596614
615+ /// This function is analogous to `check_optional_stability` but with the logic in
616+ /// `eval_stability_allow_unstable` inlined, and which operating on const stability
617+ /// instead of regular stability.
618+ ///
619+ /// This enforces *syntactical* const stability of const traits. In other words,
620+ /// it enforces the ability to name `~const`/`const` traits in trait bounds in various
621+ /// syntax positions in HIR (including in the trait of an impl header).
622+ pub fn check_const_stability ( self , def_id : DefId , span : Span , const_kw_span : Span ) {
623+ let is_staged_api = self . lookup_stability ( def_id. krate . as_def_id ( ) ) . is_some ( ) ;
624+ if !is_staged_api {
625+ return ;
626+ }
627+
628+ // Only the cross-crate scenario matters when checking unstable APIs
629+ let cross_crate = !def_id. is_local ( ) ;
630+ if !cross_crate {
631+ return ;
632+ }
633+
634+ let stability = self . lookup_const_stability ( def_id) ;
635+ debug ! (
636+ "stability: \
637+ inspecting def_id={:?} span={:?} of stability={:?}",
638+ def_id, span, stability
639+ ) ;
640+
641+ match stability {
642+ Some ( ConstStability {
643+ level : attr:: StabilityLevel :: Unstable { reason, issue, is_soft, implied_by, .. } ,
644+ feature,
645+ ..
646+ } ) => {
647+ assert ! ( !is_soft) ;
648+
649+ if span. allows_unstable ( feature) {
650+ debug ! ( "body stability: skipping span={:?} since it is internal" , span) ;
651+ return ;
652+ }
653+ if self . features ( ) . enabled ( feature) {
654+ return ;
655+ }
656+
657+ // If this item was previously part of a now-stabilized feature which is still
658+ // enabled (i.e. the user hasn't removed the attribute for the stabilized feature
659+ // yet) then allow use of this item.
660+ if let Some ( implied_by) = implied_by
661+ && self . features ( ) . enabled ( implied_by)
662+ {
663+ return ;
664+ }
665+
666+ report_unstable (
667+ self . sess ,
668+ feature,
669+ reason. to_opt_reason ( ) ,
670+ issue,
671+ None ,
672+ false ,
673+ span,
674+ |_, _, _| { } ,
675+ UnstableKind :: Const ( const_kw_span) ,
676+ ) ;
677+ }
678+ Some ( _) | None => { }
679+ }
680+ }
681+
597682 pub fn lookup_deprecation ( self , id : DefId ) -> Option < Deprecation > {
598683 self . lookup_deprecation_entry ( id) . map ( |depr| depr. attr )
599684 }
0 commit comments