rustc_const_eval/const_eval/
fn_queries.rs1use rustc_hir as hir;
2use rustc_hir::def::DefKind;
3use rustc_hir::def_id::{DefId, LocalDefId};
4use rustc_middle::query::Providers;
5use rustc_middle::ty::TyCtxt;
6
7fn parent_impl_or_trait_constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
8 let parent_id = tcx.local_parent(def_id);
9 match tcx.def_kind(parent_id) {
10 DefKind::Impl { of_trait: true } => tcx.impl_trait_header(parent_id).constness,
11 DefKind::Impl { of_trait: false } => tcx.constness(parent_id),
12 DefKind::Trait => {
13 if tcx.is_const_trait(parent_id.into()) {
14 hir::Constness::Const
15 } else {
16 hir::Constness::NotConst
17 }
18 }
19 _ => hir::Constness::NotConst,
20 }
21}
22
23fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::Constness {
25 let node = tcx.hir_node_by_def_id(def_id);
26
27 match node {
28 hir::Node::Ctor(hir::VariantData::Tuple(..)) => hir::Constness::Const,
29 hir::Node::ForeignItem(item) if let hir::ForeignItemKind::Fn(..) = item.kind => {
30 hir::Constness::NotConst
32 }
33 hir::Node::Expr(e) if let hir::ExprKind::Closure(c) = e.kind => c.constness,
34 hir::Node::Item(i) if let hir::ItemKind::Impl(impl_) = i.kind => impl_.constness,
35 _ => {
36 if let Some(fn_kind) = node.fn_kind() {
37 if fn_kind.constness() == hir::Constness::Const {
38 return hir::Constness::Const;
39 }
40
41 parent_impl_or_trait_constness(tcx, def_id)
44 } else {
45 tcx.dcx().span_bug(
46 tcx.def_span(def_id),
47 format!("should not be requesting the constness of items that can't be const: {node:#?}: {:?}", tcx.def_kind(def_id))
48 )
49 }
50 }
51 }
52}
53
54fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
55 tcx.is_const_fn(def_id)
56 && match tcx.lookup_const_stability(def_id) {
57 Some(stab) => {
58 if cfg!(debug_assertions) && stab.promotable {
59 let sig = tcx.fn_sig(def_id);
60 assert!(
61 sig.skip_binder().safety().is_safe(),
62 "don't mark const unsafe fns as promotable",
63 );
65 }
66 stab.promotable
67 }
68 None => false,
69 }
70}
71
72pub fn provide(providers: &mut Providers) {
73 *providers = Providers { constness, is_promotable_const_fn, ..*providers };
74}