@@ -5,7 +5,7 @@ pub use self::StabilityLevel::*;
5
5
6
6
use crate :: ty:: { self , DefIdTree , TyCtxt } ;
7
7
use rustc_ast:: NodeId ;
8
- use rustc_attr:: { self as attr, ConstStability , Deprecation , Stability } ;
8
+ use rustc_attr:: { self as attr, ConstStability , DefaultBodyStability , Deprecation , Stability } ;
9
9
use rustc_data_structures:: fx:: FxHashMap ;
10
10
use rustc_errors:: { Applicability , Diagnostic } ;
11
11
use rustc_feature:: GateIssue ;
@@ -61,6 +61,7 @@ pub struct Index {
61
61
/// are filled by the annotator.
62
62
pub stab_map : FxHashMap < LocalDefId , Stability > ,
63
63
pub const_stab_map : FxHashMap < LocalDefId , ConstStability > ,
64
+ pub default_body_stab_map : FxHashMap < LocalDefId , DefaultBodyStability > ,
64
65
pub depr_map : FxHashMap < LocalDefId , DeprecationEntry > ,
65
66
/// Mapping from feature name to feature name based on the `implied_by` field of `#[unstable]`
66
67
/// attributes. If a `#[unstable(feature = "implier", implied_by = "impliee")]` attribute
@@ -86,6 +87,10 @@ impl Index {
86
87
self . const_stab_map . get ( & def_id) . copied ( )
87
88
}
88
89
90
+ pub fn local_default_body_stability ( & self , def_id : LocalDefId ) -> Option < DefaultBodyStability > {
91
+ self . default_body_stab_map . get ( & def_id) . copied ( )
92
+ }
93
+
89
94
pub fn local_deprecation_entry ( & self , def_id : LocalDefId ) -> Option < DeprecationEntry > {
90
95
self . depr_map . get ( & def_id) . cloned ( )
91
96
}
@@ -416,19 +421,19 @@ impl<'tcx> TyCtxt<'tcx> {
416
421
return EvalResult :: Allow ;
417
422
}
418
423
424
+ // Only the cross-crate scenario matters when checking unstable APIs
425
+ let cross_crate = !def_id. is_local ( ) ;
426
+ if !cross_crate {
427
+ return EvalResult :: Allow ;
428
+ }
429
+
419
430
let stability = self . lookup_stability ( def_id) ;
420
431
debug ! (
421
432
"stability: \
422
433
inspecting def_id={:?} span={:?} of stability={:?}",
423
434
def_id, span, stability
424
435
) ;
425
436
426
- // Only the cross-crate scenario matters when checking unstable APIs
427
- let cross_crate = !def_id. is_local ( ) ;
428
- if !cross_crate {
429
- return EvalResult :: Allow ;
430
- }
431
-
432
437
// Issue #38412: private items lack stability markers.
433
438
if skip_stability_check_due_to_privacy ( self , def_id) {
434
439
return EvalResult :: Allow ;
@@ -492,6 +497,62 @@ impl<'tcx> TyCtxt<'tcx> {
492
497
}
493
498
}
494
499
500
+ /// Evaluates the default-impl stability of an item.
501
+ ///
502
+ /// Returns `EvalResult::Allow` if the item's default implementation is stable, or unstable but the corresponding
503
+ /// `#![feature]` has been provided. Returns `EvalResult::Deny` which describes the offending
504
+ /// unstable feature otherwise.
505
+ pub fn eval_default_body_stability ( self , def_id : DefId , span : Span ) -> EvalResult {
506
+ let is_staged_api = self . lookup_stability ( def_id. krate . as_def_id ( ) ) . is_some ( ) ;
507
+ if !is_staged_api {
508
+ return EvalResult :: Allow ;
509
+ }
510
+
511
+ // Only the cross-crate scenario matters when checking unstable APIs
512
+ let cross_crate = !def_id. is_local ( ) ;
513
+ if !cross_crate {
514
+ return EvalResult :: Allow ;
515
+ }
516
+
517
+ let stability = self . lookup_default_body_stability ( def_id) ;
518
+ debug ! (
519
+ "body stability: inspecting def_id={def_id:?} span={span:?} of stability={stability:?}"
520
+ ) ;
521
+
522
+ // Issue #38412: private items lack stability markers.
523
+ if skip_stability_check_due_to_privacy ( self , def_id) {
524
+ return EvalResult :: Allow ;
525
+ }
526
+
527
+ match stability {
528
+ Some ( DefaultBodyStability {
529
+ level : attr:: Unstable { reason, issue, is_soft, .. } ,
530
+ feature,
531
+ } ) => {
532
+ if span. allows_unstable ( feature) {
533
+ debug ! ( "body stability: skipping span={:?} since it is internal" , span) ;
534
+ return EvalResult :: Allow ;
535
+ }
536
+ if self . features ( ) . active ( feature) {
537
+ return EvalResult :: Allow ;
538
+ }
539
+
540
+ EvalResult :: Deny {
541
+ feature,
542
+ reason : reason. to_opt_reason ( ) ,
543
+ issue,
544
+ suggestion : None ,
545
+ is_soft,
546
+ }
547
+ }
548
+ Some ( _) => {
549
+ // Stable APIs are always ok to call
550
+ EvalResult :: Allow
551
+ }
552
+ None => EvalResult :: Unmarked ,
553
+ }
554
+ }
555
+
495
556
/// Checks if an item is stable or error out.
496
557
///
497
558
/// If the item defined by `def_id` is unstable and the corresponding `#![feature]` does not
0 commit comments