]>
Commit | Line | Data |
---|---|---|
353b0b11 | 1 | use rustc_attr as attr; |
dfeec247 | 2 | use rustc_hir as hir; |
5e7ed085 | 3 | use rustc_hir::def::DefKind; |
5099ac24 | 4 | use rustc_hir::def_id::{DefId, LocalDefId}; |
49aad941 | 5 | use rustc_middle::query::Providers; |
353b0b11 | 6 | use rustc_middle::ty::TyCtxt; |
dfeec247 | 7 | use 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. | |
11 | pub 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 | 25 | pub 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 | 35 | fn 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 | 69 | fn 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 | 88 | pub fn provide(providers: &mut Providers) { |
923072b8 | 89 | *providers = Providers { constness, is_promotable_const_fn, ..*providers }; |
dfeec247 | 90 | } |