]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_const_eval/src/const_eval/fn_queries.rs
New upstream version 1.71.1+dfsg1
[rustc.git] / compiler / rustc_const_eval / src / const_eval / fn_queries.rs
CommitLineData
353b0b11 1use rustc_attr as attr;
dfeec247 2use rustc_hir as hir;
5e7ed085 3use rustc_hir::def::DefKind;
5099ac24 4use rustc_hir::def_id::{DefId, LocalDefId};
49aad941 5use rustc_middle::query::Providers;
353b0b11 6use rustc_middle::ty::TyCtxt;
dfeec247 7use rustc_span::symbol::Symbol;
dfeec247 8
353b0b11
FG
9/// Whether the `def_id` is an unstable const fn and what feature gate(s) are necessary to enable
10/// it.
11pub fn is_unstable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> Option<(Symbol, Option<Symbol>)> {
dfeec247
XL
12 if tcx.is_const_fn_raw(def_id) {
13 let const_stab = tcx.lookup_const_stability(def_id)?;
353b0b11
FG
14 match const_stab.level {
15 attr::StabilityLevel::Unstable { implied_by, .. } => {
16 Some((const_stab.feature, implied_by))
17 }
18 attr::StabilityLevel::Stable { .. } => None,
19 }
dfeec247
XL
20 } else {
21 None
22 }
23}
24
5099ac24 25pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
04454e1e 26 let parent_id = tcx.local_parent(def_id);
9ffffee4
FG
27 matches!(tcx.def_kind(parent_id), DefKind::Impl { .. })
28 && tcx.constness(parent_id) == hir::Constness::Const
74b04a01 29}
dfeec247 30
923072b8
FG
31/// Checks whether an item is considered to be `const`. If it is a constructor, it is const. If
32/// it is a trait impl/function, return if it has a `const` modifier. If it is an intrinsic,
33/// report whether said intrinsic has a `rustc_const_{un,}stable` attribute. Otherwise, return
34/// `Constness::NotConst`.
353b0b11 35fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
5099ac24 36 let node = tcx.hir().get_by_def_id(def_id);
74b04a01 37
5e7ed085
FG
38 match node {
39 hir::Node::Ctor(_) => hir::Constness::Const,
40 hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
41 hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
42 // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
43 // foreign items cannot be evaluated at compile-time.
923072b8 44 let is_const = if tcx.is_intrinsic(def_id) {
5e7ed085
FG
45 tcx.lookup_const_stability(def_id).is_some()
46 } else {
47 false
48 };
49 if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
dfeec247 50 }
9c376795 51 hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
5e7ed085
FG
52 _ => {
53 if let Some(fn_kind) = node.fn_kind() {
54 if fn_kind.constness() == hir::Constness::Const {
55 return hir::Constness::Const;
56 }
dfeec247 57
5e7ed085
FG
58 // If the function itself is not annotated with `const`, it may still be a `const fn`
59 // if it resides in a const trait impl.
60 let is_const = is_parent_const_impl_raw(tcx, def_id);
61 if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
62 } else {
63 hir::Constness::NotConst
64 }
65 }
74b04a01
XL
66 }
67}
dfeec247 68
74b04a01 69fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
c295e0f8 70 tcx.is_const_fn(def_id)
74b04a01
XL
71 && match tcx.lookup_const_stability(def_id) {
72 Some(stab) => {
73 if cfg!(debug_assertions) && stab.promotable {
74 let sig = tcx.fn_sig(def_id);
75 assert_eq!(
9ffffee4 76 sig.skip_binder().unsafety(),
74b04a01
XL
77 hir::Unsafety::Normal,
78 "don't mark const unsafe fns as promotable",
79 // https://github.com/rust-lang/rust/pull/53851#issuecomment-418760682
80 );
dfeec247 81 }
74b04a01 82 stab.promotable
dfeec247 83 }
74b04a01
XL
84 None => false,
85 }
86}
dfeec247 87
f035d41b 88pub fn provide(providers: &mut Providers) {
923072b8 89 *providers = Providers { constness, is_promotable_const_fn, ..*providers };
dfeec247 90}