about summary refs log tree commit diff
path: root/compiler/rustc_const_eval
diff options
context:
space:
mode:
authorDylan DPC <99973273+Dylan-DPC@users.noreply.github.com>2022-10-12 22:13:25 +0530
committerGitHub <noreply@github.com>2022-10-12 22:13:25 +0530
commitc763ebc72f45c0d086875f6acf88b48d7f39eb23 (patch)
tree9c1564eac5dd4372ffe3e995409060bc667f907f /compiler/rustc_const_eval
parent40deecef0370dec461279e10d5e8b2f4f57d4900 (diff)
parentbef8681a1837790f2745c1f6a7f8214af2fd7f5d (diff)
downloadrust-c763ebc72f45c0d086875f6acf88b48d7f39eb23.tar.gz
rust-c763ebc72f45c0d086875f6acf88b48d7f39eb23.zip
Rollup merge of #102830 - compiler-errors:constness-parity, r=fee1-dead
Unify `tcx.constness` query and param env constness checks

The checks that we do in the `constness` query seem inconsistent with the checks that we do to determine if an item's param-env is const, so I merged them into the `constness` query and call that from the `param_env` query.

I'm not sure if this totally makes sense -- is there a case where `tcx.param_env()` would return a const param-env for an item whose `tcx.constness()` is `Constness::NotConst`? Because if not, it seems a bit dangerous that these two differ.

Luckily, not many places actually use `tcx.constness()`, and the checks in `tcx.param_env()` seem stricter than the checks in `tcx.constness()` (at least for the types of items we type-check).

Also, due to the way that `tcx.param_env()` is implemented, it _never_ used to return a const param-env for a item coming from a different crate, which also seems dangerous (though also probably not weaponizable currently, because we seldom actually compute the param-env for a non-local item).
Diffstat (limited to 'compiler/rustc_const_eval')
-rw-r--r--compiler/rustc_const_eval/src/const_eval/fn_queries.rs72
1 files changed, 56 insertions, 16 deletions
diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
index f1674d04f8d..cdcebb61c2e 100644
--- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
+++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs
@@ -25,12 +25,10 @@ pub fn is_parent_const_impl_raw(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
 /// report whether said intrinsic has a `rustc_const_{un,}stable` attribute. Otherwise, return
 /// `Constness::NotConst`.
 fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
-    let def_id = def_id.expect_local();
-    let node = tcx.hir().get_by_def_id(def_id);
-
-    match node {
+    let hir_id = tcx.hir().local_def_id_to_hir_id(def_id.expect_local());
+    match tcx.hir().get(hir_id) {
         hir::Node::Ctor(_) => hir::Constness::Const,
-        hir::Node::Item(hir::Item { kind: hir::ItemKind::Impl(impl_), .. }) => impl_.constness,
+
         hir::Node::ForeignItem(hir::ForeignItem { kind: hir::ForeignItemKind::Fn(..), .. }) => {
             // Intrinsics use `rustc_const_{un,}stable` attributes to indicate constness. All other
             // foreign items cannot be evaluated at compile-time.
@@ -41,20 +39,62 @@ fn constness(tcx: TyCtxt<'_>, def_id: DefId) -> hir::Constness {
             };
             if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
         }
-        _ => {
-            if let Some(fn_kind) = node.fn_kind() {
-                if fn_kind.constness() == hir::Constness::Const {
-                    return hir::Constness::Const;
-                }
 
-                // If the function itself is not annotated with `const`, it may still be a `const fn`
-                // if it resides in a const trait impl.
-                let is_const = is_parent_const_impl_raw(tcx, def_id);
-                if is_const { hir::Constness::Const } else { hir::Constness::NotConst }
-            } else {
-                hir::Constness::NotConst
+        hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Fn(..), .. })
+            if tcx.is_const_default_method(def_id) =>
+        {
+            hir::Constness::Const
+        }
+
+        hir::Node::Item(hir::Item { kind: hir::ItemKind::Const(..), .. })
+        | hir::Node::Item(hir::Item { kind: hir::ItemKind::Static(..), .. })
+        | hir::Node::TraitItem(hir::TraitItem { kind: hir::TraitItemKind::Const(..), .. })
+        | hir::Node::AnonConst(_)
+        | hir::Node::ImplItem(hir::ImplItem { kind: hir::ImplItemKind::Const(..), .. })
+        | hir::Node::ImplItem(hir::ImplItem {
+            kind:
+                hir::ImplItemKind::Fn(
+                    hir::FnSig {
+                        header: hir::FnHeader { constness: hir::Constness::Const, .. },
+                        ..
+                    },
+                    ..,
+                ),
+            ..
+        }) => hir::Constness::Const,
+
+        hir::Node::ImplItem(hir::ImplItem {
+            kind: hir::ImplItemKind::Type(..) | hir::ImplItemKind::Fn(..),
+            ..
+        }) => {
+            let parent_hir_id = tcx.hir().get_parent_node(hir_id);
+            match tcx.hir().get(parent_hir_id) {
+                hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
+                    ..
+                }) => *constness,
+                _ => span_bug!(
+                    tcx.def_span(parent_hir_id.owner),
+                    "impl item's parent node is not an impl",
+                ),
             }
         }
+
+        hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..),
+            ..
+        })
+        | hir::Node::TraitItem(hir::TraitItem {
+            kind:
+                hir::TraitItemKind::Fn(hir::FnSig { header: hir::FnHeader { constness, .. }, .. }, ..),
+            ..
+        })
+        | hir::Node::Item(hir::Item {
+            kind: hir::ItemKind::Impl(hir::Impl { constness, .. }),
+            ..
+        }) => *constness,
+
+        _ => hir::Constness::NotConst,
     }
 }