@@ -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,20 @@ fn suggestion_for_allocator_api(
306
306
None
307
307
}
308
308
309
+ /// An override option for eval_stability.
310
+ pub enum EvalOverride {
311
+ /// Don't emit an unstable error for the item
312
+ AllowUnstable ,
313
+ /// Handle the item normally
314
+ None ,
315
+ }
316
+
317
+ impl Default for EvalOverride {
318
+ fn default ( ) -> Self {
319
+ Self :: None
320
+ }
321
+ }
322
+
309
323
impl < ' tcx > TyCtxt < ' tcx > {
310
324
/// Evaluates the stability of an item.
311
325
///
@@ -322,6 +336,28 @@ impl<'tcx> TyCtxt<'tcx> {
322
336
id : Option < HirId > ,
323
337
span : Span ,
324
338
method_span : Option < Span > ,
339
+ ) -> EvalResult {
340
+ self . eval_stability_override ( def_id, id, span, method_span, Default :: default ( ) )
341
+ }
342
+
343
+ /// Evaluates the stability of an item.
344
+ ///
345
+ /// Returns `EvalResult::Allow` if the item is stable, or unstable but the corresponding
346
+ /// `#![feature]` has been provided. Returns `EvalResult::Deny` which describes the offending
347
+ /// unstable feature otherwise.
348
+ ///
349
+ /// If `id` is `Some(_)`, this function will also check if the item at `def_id` has been
350
+ /// deprecated. If the item is indeed deprecated, we will emit a deprecation lint attached to
351
+ /// `id`.
352
+ ///
353
+ /// Pass `EvalOverride::AllowUnstable` to `eval_override` to force an unstable item to be allowed. Deprecation warnings will be emitted normally.
354
+ pub fn eval_stability_override (
355
+ self ,
356
+ def_id : DefId ,
357
+ id : Option < HirId > ,
358
+ span : Span ,
359
+ method_span : Option < Span > ,
360
+ eval_override : EvalOverride ,
325
361
) -> EvalResult {
326
362
// Deprecated attributes apply in-crate and cross-crate.
327
363
if let Some ( id) = id {
@@ -419,6 +455,10 @@ impl<'tcx> TyCtxt<'tcx> {
419
455
}
420
456
}
421
457
458
+ if matches ! ( eval_override, EvalOverride :: AllowUnstable ) {
459
+ return EvalResult :: Allow ;
460
+ }
461
+
422
462
let suggestion = suggestion_for_allocator_api ( self , def_id, span, feature) ;
423
463
EvalResult :: Deny { feature, reason, issue, suggestion, is_soft }
424
464
}
@@ -445,11 +485,38 @@ impl<'tcx> TyCtxt<'tcx> {
445
485
span : Span ,
446
486
method_span : Option < Span > ,
447
487
) {
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
- } )
488
+ self . check_stability_override ( def_id, id, span, method_span, Default :: default ( ) )
489
+ }
490
+
491
+ /// Checks if an item is stable or error out.
492
+ ///
493
+ /// If the item defined by `def_id` is unstable and the corresponding `#![feature]` does not
494
+ /// exist, emits an error.
495
+ ///
496
+ /// This function will also check if the item is deprecated.
497
+ /// If so, and `id` is not `None`, a deprecated lint attached to `id` will be emitted.
498
+ ///
499
+ /// Pass `EvalOverride::AllowUnstable` to `eval_override` to force an unstable item to be allowed. Deprecation warnings will be emitted normally.
500
+ pub fn check_stability_override (
501
+ self ,
502
+ def_id : DefId ,
503
+ id : Option < HirId > ,
504
+ span : Span ,
505
+ method_span : Option < Span > ,
506
+ eval_override : EvalOverride ,
507
+ ) {
508
+ self . check_optional_stability (
509
+ def_id,
510
+ id,
511
+ span,
512
+ method_span,
513
+ eval_override,
514
+ |span, def_id| {
515
+ // The API could be uncallable for other reasons, for example when a private module
516
+ // was referenced.
517
+ self . sess . delay_span_bug ( span, & format ! ( "encountered unmarked API: {:?}" , def_id) ) ;
518
+ } ,
519
+ )
453
520
}
454
521
455
522
/// Like `check_stability`, except that we permit items to have custom behaviour for
@@ -462,14 +529,15 @@ impl<'tcx> TyCtxt<'tcx> {
462
529
id : Option < HirId > ,
463
530
span : Span ,
464
531
method_span : Option < Span > ,
532
+ eval_override : EvalOverride ,
465
533
unmarked : impl FnOnce ( Span , DefId ) ,
466
534
) {
467
535
let soft_handler = |lint, span, msg : & _ | {
468
536
self . struct_span_lint_hir ( lint, id. unwrap_or ( hir:: CRATE_HIR_ID ) , span, |lint| {
469
537
lint. build ( msg) . emit ( ) ;
470
538
} )
471
539
} ;
472
- match self . eval_stability ( def_id, id, span, method_span) {
540
+ match self . eval_stability_override ( def_id, id, span, method_span, eval_override ) {
473
541
EvalResult :: Allow => { }
474
542
EvalResult :: Deny { feature, reason, issue, suggestion, is_soft } => report_unstable (
475
543
self . sess ,
0 commit comments