1- use crate :: hir:: map:: blocks:: FnLikeNode ;
2- use crate :: ty:: query:: Providers ;
3- use crate :: ty:: TyCtxt ;
1+ use rustc :: hir:: map:: blocks:: FnLikeNode ;
2+ use rustc :: ty:: query:: Providers ;
3+ use rustc :: ty:: TyCtxt ;
44use rustc_hir as hir;
55use rustc_hir:: def_id:: DefId ;
66use rustc_span:: symbol:: Symbol ;
77use rustc_target:: spec:: abi:: Abi ;
88use syntax:: attr;
99
10- impl < ' tcx > TyCtxt < ' tcx > {
11- /// Whether the `def_id` counts as const fn in your current crate, considering all active
12- /// feature gates
13- pub fn is_const_fn ( self , def_id : DefId ) -> bool {
14- self . is_const_fn_raw ( def_id)
15- && match self . is_unstable_const_fn ( def_id) {
16- Some ( feature_name) => {
17- // has a `rustc_const_unstable` attribute, check whether the user enabled the
18- // corresponding feature gate.
19- self . features ( )
20- . declared_lib_features
21- . iter ( )
22- . any ( |& ( sym, _) | sym == feature_name)
23- }
24- // functions without const stability are either stable user written
25- // const fn or the user is using feature gates and we thus don't
26- // care what they do
27- None => true ,
10+ /// Whether the `def_id` counts as const fn in your current crate, considering all active
11+ /// feature gates
12+ pub fn is_const_fn ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
13+ tcx. is_const_fn_raw ( def_id)
14+ && match is_unstable_const_fn ( tcx, def_id) {
15+ Some ( feature_name) => {
16+ // has a `rustc_const_unstable` attribute, check whether the user enabled the
17+ // corresponding feature gate.
18+ tcx. features ( ) . declared_lib_features . iter ( ) . any ( |& ( sym, _) | sym == feature_name)
2819 }
29- }
30-
31- /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
32- pub fn is_unstable_const_fn ( self , def_id : DefId ) -> Option < Symbol > {
33- if self . is_const_fn_raw ( def_id) {
34- let const_stab = self . lookup_const_stability ( def_id) ?;
35- if const_stab. level . is_unstable ( ) { Some ( const_stab. feature ) } else { None }
36- } else {
37- None
20+ // functions without const stability are either stable user written
21+ // const fn or the user is using feature gates and we thus don't
22+ // care what they do
23+ None => true ,
3824 }
25+ }
26+
27+ /// Whether the `def_id` is an unstable const fn and what feature gate is necessary to enable it
28+ pub fn is_unstable_const_fn ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> Option < Symbol > {
29+ if tcx. is_const_fn_raw ( def_id) {
30+ let const_stab = tcx. lookup_const_stability ( def_id) ?;
31+ if const_stab. level . is_unstable ( ) { Some ( const_stab. feature ) } else { None }
32+ } else {
33+ None
3934 }
35+ }
4036
41- /// Returns `true` if this function must conform to `min_const_fn`
42- pub fn is_min_const_fn ( self , def_id : DefId ) -> bool {
43- // Bail out if the signature doesn't contain `const`
44- if !self . is_const_fn_raw ( def_id) {
45- return false ;
46- }
37+ /// Returns `true` if this function must conform to `min_const_fn`
38+ pub fn is_min_const_fn ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
39+ // Bail out if the signature doesn't contain `const`
40+ if !tcx . is_const_fn_raw ( def_id) {
41+ return false ;
42+ }
4743
48- if self . features ( ) . staged_api {
49- // In order for a libstd function to be considered min_const_fn
50- // it needs to be stable and have no `rustc_const_unstable` attribute.
51- match self . lookup_const_stability ( def_id) {
52- // `rustc_const_unstable` functions don't need to conform.
53- Some ( & attr:: ConstStability { ref level, .. } ) if level. is_unstable ( ) => false ,
54- None => {
55- if let Some ( stab) = self . lookup_stability ( def_id) {
56- if stab. level . is_stable ( ) {
57- self . sess . span_err (
58- self . def_span ( def_id) ,
59- "stable const functions must have either `rustc_const_stable` or \
60- `rustc_const_unstable` attribute",
61- ) ;
62- // While we errored above, because we don't know if we need to conform, we
63- // err on the "safe" side and require min_const_fn.
64- true
65- } else {
66- // Unstable functions need not conform to min_const_fn.
67- false
68- }
69- } else {
70- // Internal functions are forced to conform to min_const_fn.
71- // Annotate the internal function with a const stability attribute if
72- // you need to use unstable features.
73- // Note: this is an arbitrary choice that does not affect stability or const
74- // safety or anything, it just changes whether we need to annotate some
75- // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
44+ if tcx. features ( ) . staged_api {
45+ // In order for a libstd function to be considered min_const_fn
46+ // it needs to be stable and have no `rustc_const_unstable` attribute.
47+ match tcx. lookup_const_stability ( def_id) {
48+ // `rustc_const_unstable` functions don't need to conform.
49+ Some ( & attr:: ConstStability { ref level, .. } ) if level. is_unstable ( ) => false ,
50+ None => {
51+ if let Some ( stab) = tcx. lookup_stability ( def_id) {
52+ if stab. level . is_stable ( ) {
53+ tcx. sess . span_err (
54+ tcx. def_span ( def_id) ,
55+ "stable const functions must have either `rustc_const_stable` or \
56+ `rustc_const_unstable` attribute",
57+ ) ;
58+ // While we errored above, because we don't know if we need to conform, we
59+ // err on the "safe" side and require min_const_fn.
7660 true
61+ } else {
62+ // Unstable functions need not conform to min_const_fn.
63+ false
7764 }
65+ } else {
66+ // Internal functions are forced to conform to min_const_fn.
67+ // Annotate the internal function with a const stability attribute if
68+ // you need to use unstable features.
69+ // Note: this is an arbitrary choice that does not affect stability or const
70+ // safety or anything, it just changes whether we need to annotate some
71+ // internal functions with `rustc_const_stable` or with `rustc_const_unstable`
72+ true
7873 }
79- // Everything else needs to conform, because it would be callable from
80- // other `min_const_fn` functions.
81- _ => true ,
8274 }
83- } else {
84- // users enabling the `const_fn` feature gate can do what they want
85- ! self . features ( ) . const_fn
75+ // Everything else needs to conform, because it would be callable from
76+ // other `min_const_fn` functions.
77+ _ => true ,
8678 }
79+ } else {
80+ // users enabling the `const_fn` feature gate can do what they want
81+ !tcx. features ( ) . const_fn
8782 }
8883}
8984
@@ -121,7 +116,7 @@ pub fn provide(providers: &mut Providers<'_>) {
121116 }
122117
123118 fn is_promotable_const_fn ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
124- tcx . is_const_fn ( def_id)
119+ is_const_fn ( tcx , def_id)
125120 && match tcx. lookup_const_stability ( def_id) {
126121 Some ( stab) => {
127122 if cfg ! ( debug_assertions) && stab. promotable {
@@ -140,7 +135,7 @@ pub fn provide(providers: &mut Providers<'_>) {
140135 }
141136
142137 fn const_fn_is_allowed_fn_ptr ( tcx : TyCtxt < ' _ > , def_id : DefId ) -> bool {
143- tcx . is_const_fn ( def_id)
138+ is_const_fn ( tcx , def_id)
144139 && tcx
145140 . lookup_const_stability ( def_id)
146141 . map ( |stab| stab. allow_const_fn_ptr )
0 commit comments