1+ // This code used to be a part of `rustc` but moved to Clippy as a result of
2+ // https://github.com/rust-lang/rust/issues/76618. Because of that, it contains unused code and some
3+ // of terminologies might not be relevant in the context of Clippy. Note that its behavior might
4+ // differ from the time of `rustc` even if the name stays the same.
5+
16use rustc_hir as hir;
27use rustc_hir:: def_id:: DefId ;
38use rustc_middle:: mir:: {
@@ -6,14 +11,15 @@ use rustc_middle::mir::{
611} ;
712use rustc_middle:: ty:: subst:: GenericArgKind ;
813use rustc_middle:: ty:: { self , adjustment:: PointerCast , Ty , TyCtxt } ;
14+ use rustc_semver:: RustcVersion ;
915use rustc_span:: symbol:: sym;
1016use rustc_span:: Span ;
1117use rustc_target:: spec:: abi:: Abi :: RustIntrinsic ;
1218use std:: borrow:: Cow ;
1319
1420type McfResult = Result < ( ) , ( Span , Cow < ' static , str > ) > ;
1521
16- pub fn is_min_const_fn ( tcx : TyCtxt < ' tcx > , body : & ' a Body < ' tcx > ) -> McfResult {
22+ pub fn is_min_const_fn ( tcx : TyCtxt < ' tcx > , body : & ' a Body < ' tcx > , msrv : Option < & RustcVersion > ) -> McfResult {
1723 let def_id = body. source . def_id ( ) ;
1824 let mut current = def_id;
1925 loop {
@@ -70,7 +76,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>) -> McfResult {
7076 ) ?;
7177
7278 for bb in body. basic_blocks ( ) {
73- check_terminator ( tcx, body, bb. terminator ( ) ) ?;
79+ check_terminator ( tcx, body, bb. terminator ( ) , msrv ) ?;
7480 for stmt in & bb. statements {
7581 check_statement ( tcx, body, def_id, stmt) ?;
7682 }
@@ -268,7 +274,12 @@ fn check_place(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'t
268274 Ok ( ( ) )
269275}
270276
271- fn check_terminator ( tcx : TyCtxt < ' tcx > , body : & ' a Body < ' tcx > , terminator : & Terminator < ' tcx > ) -> McfResult {
277+ fn check_terminator (
278+ tcx : TyCtxt < ' tcx > ,
279+ body : & ' a Body < ' tcx > ,
280+ terminator : & Terminator < ' tcx > ,
281+ msrv : Option < & RustcVersion > ,
282+ ) -> McfResult {
272283 let span = terminator. source_info . span ;
273284 match & terminator. kind {
274285 TerminatorKind :: FalseEdge { .. }
@@ -305,7 +316,7 @@ fn check_terminator(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Termin
305316 } => {
306317 let fn_ty = func. ty ( body, tcx) ;
307318 if let ty:: FnDef ( fn_def_id, _) = * fn_ty. kind ( ) {
308- if !rustc_mir :: const_eval :: is_min_const_fn ( tcx, fn_def_id) {
319+ if !is_const_fn ( tcx, fn_def_id, msrv ) {
309320 return Err ( (
310321 span,
311322 format ! (
@@ -350,3 +361,24 @@ fn check_terminator(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Termin
350361 TerminatorKind :: InlineAsm { .. } => Err ( ( span, "cannot use inline assembly in const fn" . into ( ) ) ) ,
351362 }
352363}
364+
365+ fn is_const_fn ( tcx : TyCtxt < ' _ > , def_id : DefId , msrv : Option < & RustcVersion > ) -> bool {
366+ rustc_mir:: const_eval:: is_const_fn ( tcx, def_id)
367+ && if let Some ( const_stab) = tcx. lookup_const_stability ( def_id) {
368+ if let rustc_attr:: StabilityLevel :: Stable { since } = const_stab. level {
369+ // Checking MSRV is manually necessary because `rustc` has no such concept. This entire
370+ // function could be removed if `rustc` provided a MSRV-aware version of `is_const_fn`.
371+ // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262.
372+ crate :: meets_msrv (
373+ msrv,
374+ & RustcVersion :: parse ( & since. as_str ( ) )
375+ . expect ( "`rustc_attr::StabilityLevel::Stable::since` is ill-formatted" ) ,
376+ )
377+ } else {
378+ // `rustc_mir::const_eval::is_const_fn` should return false for unstably const functions.
379+ unreachable ! ( ) ;
380+ }
381+ } else {
382+ true
383+ }
384+ }
0 commit comments