about summary refs log tree commit diff
diff options
context:
space:
mode:
authorDylan MacKenzie <ecstaticmorse@gmail.com>2020-05-07 10:22:35 -0700
committerDylan MacKenzie <ecstaticmorse@gmail.com>2020-05-07 11:28:55 -0700
commit3f661dab14bb5a6f1eed41efaf3cf41a8080df87 (patch)
tree3009e82473c45062b0e2cbf59c3bdc835f7273bf
parent6318d24ad8440fa30428b405be1174478e9536e3 (diff)
downloadrust-3f661dab14bb5a6f1eed41efaf3cf41a8080df87.tar.gz
rust-3f661dab14bb5a6f1eed41efaf3cf41a8080df87.zip
Add `hir::ConstContext`
-rw-r--r--src/librustc_hir/hir.rs47
-rw-r--r--src/librustc_middle/hir/map/mod.rs20
2 files changed, 67 insertions, 0 deletions
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 258428d77da..03b8fdf1aa3 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -1291,6 +1291,53 @@ impl BodyOwnerKind {
     }
 }
 
+/// The kind of an item that requires const-checking.
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+pub enum ConstContext {
+    /// A `const fn`.
+    ConstFn,
+
+    /// A `static` or `static mut`.
+    Static(Mutability),
+
+    /// A `const`, associated `const`, or other const context.
+    ///
+    /// Other contexts include:
+    /// - Array length expressions
+    /// - Enum discriminants
+    /// - Const generics
+    ///
+    /// For the most part, other contexts are treated just like a regular `const`, so they are
+    /// lumped into the same category.
+    Const,
+}
+
+impl ConstContext {
+    /// A description of this const context that can appear between backticks in an error message.
+    ///
+    /// E.g. `const` or `static mut`.
+    pub fn keyword_name(self) -> &'static str {
+        match self {
+            Self::Const => "const",
+            Self::Static(Mutability::Not) => "static",
+            Self::Static(Mutability::Mut) => "static mut",
+            Self::ConstFn => "const fn",
+        }
+    }
+}
+
+/// A colloquial, trivially pluralizable description of this const context for use in error
+/// messages.
+impl fmt::Display for ConstContext {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match *self {
+            Self::Const => write!(f, "constant"),
+            Self::Static(_) => write!(f, "static"),
+            Self::ConstFn => write!(f, "constant function"),
+        }
+    }
+}
+
 /// A literal.
 pub type Lit = Spanned<LitKind>;
 
diff --git a/src/librustc_middle/hir/map/mod.rs b/src/librustc_middle/hir/map/mod.rs
index 1c71fc57bea..235d1d80192 100644
--- a/src/librustc_middle/hir/map/mod.rs
+++ b/src/librustc_middle/hir/map/mod.rs
@@ -408,6 +408,9 @@ impl<'hir> Map<'hir> {
         })
     }
 
+    /// Returns the `BodyOwnerKind` of this `LocalDefId`.
+    ///
+    /// Panics if `LocalDefId` does not have an associated body.
     pub fn body_owner_kind(&self, id: HirId) -> BodyOwnerKind {
         match self.get(id) {
             Node::Item(&Item { kind: ItemKind::Const(..), .. })
@@ -424,6 +427,23 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    /// Returns the `ConstContext` of the body associated with this `LocalDefId`.
+    ///
+    /// Panics if `LocalDefId` does not have an associated body.
+    pub fn body_const_context(&self, did: LocalDefId) -> Option<ConstContext> {
+        let hir_id = self.local_def_id_to_hir_id(did);
+        let ccx = match self.body_owner_kind(hir_id) {
+            BodyOwnerKind::Const => ConstContext::Const,
+            BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
+
+            BodyOwnerKind::Fn if self.tcx.is_constructor(did.to_def_id()) => return None,
+            BodyOwnerKind::Fn if self.tcx.is_const_fn_raw(did.to_def_id()) => ConstContext::ConstFn,
+            BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
+        };
+
+        Some(ccx)
+    }
+
     pub fn ty_param_owner(&self, id: HirId) -> HirId {
         match self.get(id) {
             Node::Item(&Item { kind: ItemKind::Trait(..) | ItemKind::TraitAlias(..), .. }) => id,