@@ -9,9 +9,9 @@ use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
9
9
use rustc_data_structures:: fx:: FxHashMap ;
10
10
use rustc_errors:: { Applicability , Diagnostic } ;
11
11
use rustc_feature:: GateIssue ;
12
- use rustc_hir as hir;
13
12
use rustc_hir:: def:: DefKind ;
14
13
use rustc_hir:: def_id:: { DefId , LocalDefId } ;
14
+ use rustc_hir:: { self as hir} ;
15
15
use rustc_hir:: { self , HirId } ;
16
16
use rustc_middle:: ty:: print:: with_no_trimmed_paths;
17
17
use rustc_session:: lint:: builtin:: { DEPRECATED , DEPRECATED_IN_FUTURE , SOFT_UNSTABLE } ;
@@ -306,6 +306,14 @@ fn suggestion_for_allocator_api(
306
306
None
307
307
}
308
308
309
+ /// An override option for eval_stability.
310
+ pub enum AllowUnstable {
311
+ /// Don't emit an unstable error for the item
312
+ Yes ,
313
+ /// Handle the item normally
314
+ No ,
315
+ }
316
+
309
317
impl < ' tcx > TyCtxt < ' tcx > {
310
318
/// Evaluates the stability of an item.
311
319
///
@@ -322,6 +330,28 @@ impl<'tcx> TyCtxt<'tcx> {
322
330
id : Option < HirId > ,
323
331
span : Span ,
324
332
method_span : Option < Span > ,
333
+ ) -> EvalResult {
334
+ self . eval_stability_override ( def_id, id, span, method_span, AllowUnstable :: No )
335
+ }
336
+
337
+ /// Evaluates the stability of an item.
338
+ ///
339
+ /// Returns `EvalResult::Allow` if the item is stable, or unstable but the corresponding
340
+ /// `#![feature]` has been provided. Returns `EvalResult::Deny` which describes the offending
341
+ /// unstable feature otherwise.
342
+ ///
343
+ /// If `id` is `Some(_)`, this function will also check if the item at `def_id` has been
344
+ /// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to
345
+ /// `id`.
346
+ ///
347
+ /// Pass `EvalOverride::AllowUnstable` to `eval_override` to force an unstable item to be allowed. Deprecation warnings will be emitted normally.
348
+ pub fn eval_stability_override (
349
+ self ,
350
+ def_id : DefId ,
351
+ id : Option < HirId > ,
352
+ span : Span ,
353
+ method_span : Option < Span > ,
354
+ eval_override : AllowUnstable ,
325
355
) -> EvalResult {
326
356
// Deprecated attributes apply in-crate and cross-crate.
327
357
if let Some ( id) = id {
@@ -419,6 +449,10 @@ impl<'tcx> TyCtxt<'tcx> {
419
449
}
420
450
}
421
451
452
+ if matches ! ( eval_override, AllowUnstable :: Yes ) {
453
+ return EvalResult :: Allow ;
454
+ }
455
+
422
456
let suggestion = suggestion_for_allocator_api ( self , def_id, span, feature) ;
423
457
EvalResult :: Deny { feature, reason, issue, suggestion, is_soft }
424
458
}
@@ -445,11 +479,38 @@ impl<'tcx> TyCtxt<'tcx> {
445
479
span : Span ,
446
480
method_span : Option < Span > ,
447
481
) {
448
- self . check_optional_stability ( def_id, id, span, method_span, |span, def_id| {
449
- // The API could be uncallable for other reasons, for example when a private module
450
- // was referenced.
451
- self . sess . delay_span_bug ( span, & format ! ( "encountered unmarked API: {:?}" , def_id) ) ;
452
- } )
482
+ self . check_stability_override ( def_id, id, span, method_span, AllowUnstable :: No )
483
+ }
484
+
485
+ /// Checks if an item is stable or error out.
486
+ ///
487
+ /// If the item defined by `def_id` is unstable and the corresponding `#![feature]` does not
488
+ /// exist, emits an error.
489
+ ///
490
+ /// This function will also check if the item is deprecated.
491
+ /// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted.
492
+ ///
493
+ /// Pass `EvalOverride::AllowUnstable` to `eval_override` to force an unstable item to be allowed. Deprecation warnings will be emitted normally.
494
+ pub fn check_stability_override (
495
+ self ,
496
+ def_id : DefId ,
497
+ id : Option < HirId > ,
498
+ span : Span ,
499
+ method_span : Option < Span > ,
500
+ eval_override : AllowUnstable ,
501
+ ) {
502
+ self . check_optional_stability (
503
+ def_id,
504
+ id,
505
+ span,
506
+ method_span,
507
+ eval_override,
508
+ |span, def_id| {
509
+ // The API could be uncallable for other reasons, for example when a private module
510
+ // was referenced.
511
+ self . sess . delay_span_bug ( span, & format ! ( "encountered unmarked API: {:?}" , def_id) ) ;
512
+ } ,
513
+ )
453
514
}
454
515
455
516
/// Like `check_stability`, except that we permit items to have custom behaviour for
@@ -462,14 +523,15 @@ impl<'tcx> TyCtxt<'tcx> {
462
523
id : Option < HirId > ,
463
524
span : Span ,
464
525
method_span : Option < Span > ,
526
+ eval_override : AllowUnstable ,
465
527
unmarked : impl FnOnce ( Span , DefId ) ,
466
528
) {
467
529
let soft_handler = |lint, span, msg : & _ | {
468
530
self . struct_span_lint_hir ( lint, id. unwrap_or ( hir:: CRATE_HIR_ID ) , span, |lint| {
469
531
lint. build ( msg) . emit ( ) ;
470
532
} )
471
533
} ;
472
- match self . eval_stability ( def_id, id, span, method_span) {
534
+ match self . eval_stability_override ( def_id, id, span, method_span, eval_override ) {
473
535
EvalResult :: Allow => { }
474
536
EvalResult :: Deny { feature, reason, issue, suggestion, is_soft } => report_unstable (
475
537
self . sess ,
0 commit comments