rustc_const_eval/const_eval/
fn_queries.rs1use rustc_attr_ir::find_attr;
2use rustc_hir::def_id::{DefId, LocalDefId};
3use rustc_hir::{
4 Constness, ExprKind, ForeignItemKind, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind,
5 Node, TraitItem, TraitItemKind, VariantData,
6};
7use rustc_middle::query::Providers;
8use rustc_middle::ty::TyCtxt;
9
10fn constness(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Constness {
12 let node = tcx.hir_node_by_def_id(def_id);
13
14 match node {
15 Node::Ctor(VariantData::Tuple(..)) => Constness::Const { always: false },
16 Node::ForeignItem(item) if let ForeignItemKind::Fn(..) = item.kind => {
17 Constness::NotConst
19 }
20 Node::Expr(e) if let ExprKind::Closure(c) = e.kind => {
21 if let Constness::Const { .. } = c.constness && tcx.hir_body_const_context(tcx.local_parent(def_id)).is_none() {
22 tcx.dcx().span_err(tcx.def_span(def_id), "cannot use `const` closures outside of const contexts");
23 return Constness::NotConst;
24 }
25 c.constness
26 },
27 Node::Item(i) if let ItemKind::Impl(impl_) = i.kind => impl_.constness,
29 Node::Item(Item { kind: ItemKind::Fn { sig, .. }, .. }) => sig.header.constness,
30 Node::ImplItem(ImplItem {
31 impl_kind: ImplItemImplKind::Trait { .. },
32 kind: ImplItemKind::Fn(..),
33 ..
34 }) => tcx.impl_trait_header(tcx.local_parent(def_id)).constness,
35 Node::ImplItem(ImplItem {
36 impl_kind: ImplItemImplKind::Inherent { .. },
37 kind: ImplItemKind::Fn(sig, _),
38 ..
39 }) => {
40 match sig.header.constness {
41 Constness::Const { always } => Constness::Const { always },
42 Constness::NotConst => tcx.constness(tcx.local_parent(def_id)),
44 }
45 }
46 Node::TraitItem(ti @ TraitItem { kind: TraitItemKind::Fn(..), .. }) => {
47 if {
{
'done:
{
for i in
::rustc_attr_ir::HasAttrs::get_attrs(ti.hir_id(), &tcx) {
#[allow(unused_imports)]
use ::rustc_attr_ir::AttributeKind::*;
let i: &::rustc_attr_ir::Attribute = i;
match i {
::rustc_attr_ir::Attribute::Parsed(RustcNonConstTraitMethod)
=> {
break 'done Some(());
}
::rustc_attr_ir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}
}.is_some()find_attr!(tcx, ti.hir_id(), RustcNonConstTraitMethod) {
48 Constness::NotConst
49 } else {
50 tcx.trait_def(tcx.local_parent(def_id)).constness
51 }
52 }
53 _ => {
54 tcx.dcx().span_bug(
55 tcx.def_span(def_id),
56 ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("should not be requesting the constness of items that can\'t be const: {1:#?}: {0:?}",
tcx.def_kind(def_id), node))
})format!("should not be requesting the constness of items that can't be const: {node:#?}: {:?}", tcx.def_kind(def_id))
57 )
58 }
59 }
60}
61
62fn is_promotable_const_fn(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
63 tcx.is_const_fn(def_id)
64 && match tcx.lookup_const_stability(def_id) {
65 Some(stab) => {
66 if truecfg!(debug_assertions) && stab.promotable {
67 let sig = tcx.fn_sig(def_id);
68 if !sig.skip_binder().safety().is_safe() {
{
::core::panicking::panic_fmt(format_args!("don\'t mark const unsafe fns as promotable"));
}
};assert!(
69 sig.skip_binder().safety().is_safe(),
70 "don't mark const unsafe fns as promotable",
71 );
73 }
74 stab.promotable
75 }
76 None => false,
77 }
78}
79
80pub fn provide(providers: &mut Providers) {
81 *providers = Providers { constness, is_promotable_const_fn, ..*providers };
82}