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
+
1
6
use rustc_hir as hir;
2
7
use rustc_hir:: def_id:: DefId ;
3
8
use rustc_middle:: mir:: {
@@ -6,14 +11,15 @@ use rustc_middle::mir::{
6
11
} ;
7
12
use rustc_middle:: ty:: subst:: GenericArgKind ;
8
13
use rustc_middle:: ty:: { self , adjustment:: PointerCast , Ty , TyCtxt } ;
14
+ use rustc_semver:: RustcVersion ;
9
15
use rustc_span:: symbol:: sym;
10
16
use rustc_span:: Span ;
11
17
use rustc_target:: spec:: abi:: Abi :: RustIntrinsic ;
12
18
use std:: borrow:: Cow ;
13
19
14
20
type McfResult = Result < ( ) , ( Span , Cow < ' static , str > ) > ;
15
21
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 {
17
23
let def_id = body. source . def_id ( ) ;
18
24
let mut current = def_id;
19
25
loop {
@@ -70,7 +76,7 @@ pub fn is_min_const_fn(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>) -> McfResult {
70
76
) ?;
71
77
72
78
for bb in body. basic_blocks ( ) {
73
- check_terminator ( tcx, body, bb. terminator ( ) ) ?;
79
+ check_terminator ( tcx, body, bb. terminator ( ) , msrv ) ?;
74
80
for stmt in & bb. statements {
75
81
check_statement ( tcx, body, def_id, stmt) ?;
76
82
}
@@ -268,7 +274,12 @@ fn check_place(tcx: TyCtxt<'tcx>, place: Place<'tcx>, span: Span, body: &Body<'t
268
274
Ok ( ( ) )
269
275
}
270
276
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 {
272
283
let span = terminator. source_info . span ;
273
284
match & terminator. kind {
274
285
TerminatorKind :: FalseEdge { .. }
@@ -305,7 +316,7 @@ fn check_terminator(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Termin
305
316
} => {
306
317
let fn_ty = func. ty ( body, tcx) ;
307
318
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 ) {
309
320
return Err ( (
310
321
span,
311
322
format ! (
@@ -350,3 +361,24 @@ fn check_terminator(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, terminator: &Termin
350
361
TerminatorKind :: InlineAsm { .. } => Err ( ( span, "cannot use inline assembly in const fn" . into ( ) ) ) ,
351
362
}
352
363
}
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