@@ -9,9 +9,9 @@ use rustc_attr::{self as attr, ConstStability, Deprecation, Stability};
99use rustc_data_structures:: fx:: FxHashMap ;
1010use rustc_errors:: { Applicability , Diagnostic } ;
1111use rustc_feature:: GateIssue ;
12- use rustc_hir as hir;
1312use rustc_hir:: def:: DefKind ;
1413use rustc_hir:: def_id:: { DefId , LocalDefId } ;
14+ use rustc_hir:: { self as hir} ;
1515use rustc_hir:: { self , HirId } ;
1616use rustc_middle:: ty:: print:: with_no_trimmed_paths;
1717use rustc_session:: lint:: builtin:: { DEPRECATED , DEPRECATED_IN_FUTURE , SOFT_UNSTABLE } ;
@@ -306,6 +306,14 @@ fn suggestion_for_allocator_api(
306306 None
307307}
308308
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+
309317impl < ' tcx > TyCtxt < ' tcx > {
310318 /// Evaluates the stability of an item.
311319 ///
@@ -322,6 +330,28 @@ impl<'tcx> TyCtxt<'tcx> {
322330 id : Option < HirId > ,
323331 span : Span ,
324332 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 ,
325355 ) -> EvalResult {
326356 // Deprecated attributes apply in-crate and cross-crate.
327357 if let Some ( id) = id {
@@ -419,6 +449,10 @@ impl<'tcx> TyCtxt<'tcx> {
419449 }
420450 }
421451
452+ if matches ! ( eval_override, AllowUnstable :: Yes ) {
453+ return EvalResult :: Allow ;
454+ }
455+
422456 let suggestion = suggestion_for_allocator_api ( self , def_id, span, feature) ;
423457 EvalResult :: Deny { feature, reason, issue, suggestion, is_soft }
424458 }
@@ -445,11 +479,38 @@ impl<'tcx> TyCtxt<'tcx> {
445479 span : Span ,
446480 method_span : Option < Span > ,
447481 ) {
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+ )
453514 }
454515
455516 /// Like `check_stability`, except that we permit items to have custom behaviour for
@@ -462,14 +523,15 @@ impl<'tcx> TyCtxt<'tcx> {
462523 id : Option < HirId > ,
463524 span : Span ,
464525 method_span : Option < Span > ,
526+ eval_override : AllowUnstable ,
465527 unmarked : impl FnOnce ( Span , DefId ) ,
466528 ) {
467529 let soft_handler = |lint, span, msg : & _ | {
468530 self . struct_span_lint_hir ( lint, id. unwrap_or ( hir:: CRATE_HIR_ID ) , span, |lint| {
469531 lint. build ( msg) . emit ( ) ;
470532 } )
471533 } ;
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 ) {
473535 EvalResult :: Allow => { }
474536 EvalResult :: Deny { feature, reason, issue, suggestion, is_soft } => report_unstable (
475537 self . sess ,
0 commit comments