From 3f661dab14bb5a6f1eed41efaf3cf41a8080df87 Mon Sep 17 00:00:00 2001 From: Dylan MacKenzie Date: Thu, 7 May 2020 10:22:35 -0700 Subject: [PATCH] Add `hir::ConstContext` --- src/librustc_hir/hir.rs | 47 ++++++++++++++++++++++++++++++ src/librustc_middle/hir/map/mod.rs | 20 +++++++++++++ 2 files changed, 67 insertions(+) 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; 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 { + 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,