Add hir::ConstContext

This commit is contained in:
Dylan MacKenzie 2020-05-07 10:22:35 -07:00
parent 6318d24ad8
commit 3f661dab14
2 changed files with 67 additions and 0 deletions

View File

@ -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>;

View File

@ -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,