1
Fork 0

Use a slice in DefIdForest.

This commit is contained in:
Camille GILLOT 2022-02-01 18:27:49 +01:00
parent 6c2ee885e6
commit f72f15ca28
3 changed files with 22 additions and 25 deletions

View file

@ -1515,8 +1515,7 @@ rustc_queries! {
/// check whether the forest is empty. /// check whether the forest is empty.
query type_uninhabited_from( query type_uninhabited_from(
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>> key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>
) -> ty::inhabitedness::DefIdForest { ) -> ty::inhabitedness::DefIdForest<'tcx> {
storage(ArenaCacheSelector<'tcx>)
desc { "computing the inhabitedness of `{:?}`", key } desc { "computing the inhabitedness of `{:?}`", key }
remap_env_constness remap_env_constness
} }

View file

@ -3,7 +3,6 @@ use crate::ty::{DefId, DefIdTree};
use rustc_span::def_id::CRATE_DEF_ID; use rustc_span::def_id::CRATE_DEF_ID;
use smallvec::SmallVec; use smallvec::SmallVec;
use std::mem; use std::mem;
use std::sync::Arc;
use DefIdForest::*; use DefIdForest::*;
@ -18,14 +17,13 @@ use DefIdForest::*;
/// We store the minimal set of `DefId`s required to represent the whole set. If A and B are /// We store the minimal set of `DefId`s required to represent the whole set. If A and B are
/// `DefId`s in the `DefIdForest`, and A is a parent of B, then only A will be stored. When this is /// `DefId`s in the `DefIdForest`, and A is a parent of B, then only A will be stored. When this is
/// used with `type_uninhabited_from`, there will very rarely be more than one `DefId` stored. /// used with `type_uninhabited_from`, there will very rarely be more than one `DefId` stored.
#[derive(Clone, HashStable, Debug)] #[derive(Copy, Clone, HashStable, Debug)]
pub enum DefIdForest { pub enum DefIdForest<'a> {
Empty, Empty,
Single(DefId), Single(DefId),
/// This variant is very rare. /// This variant is very rare.
/// Invariant: >1 elements /// Invariant: >1 elements
/// We use `Arc` because this is used in the output of a query. Multiple(&'a [DefId]),
Multiple(Arc<[DefId]>),
} }
/// Tests whether a slice of roots contains a given DefId. /// Tests whether a slice of roots contains a given DefId.
@ -34,21 +32,21 @@ fn slice_contains<'tcx>(tcx: TyCtxt<'tcx>, slice: &[DefId], id: DefId) -> bool {
slice.iter().any(|root_id| tcx.is_descendant_of(id, *root_id)) slice.iter().any(|root_id| tcx.is_descendant_of(id, *root_id))
} }
impl<'tcx> DefIdForest { impl<'tcx> DefIdForest<'tcx> {
/// Creates an empty forest. /// Creates an empty forest.
pub fn empty() -> DefIdForest { pub fn empty() -> DefIdForest<'tcx> {
DefIdForest::Empty DefIdForest::Empty
} }
/// Creates a forest consisting of a single tree representing the entire /// Creates a forest consisting of a single tree representing the entire
/// crate. /// crate.
#[inline] #[inline]
pub fn full() -> DefIdForest { pub fn full() -> DefIdForest<'tcx> {
DefIdForest::from_id(CRATE_DEF_ID.to_def_id()) DefIdForest::from_id(CRATE_DEF_ID.to_def_id())
} }
/// Creates a forest containing a `DefId` and all its descendants. /// Creates a forest containing a `DefId` and all its descendants.
pub fn from_id(id: DefId) -> DefIdForest { pub fn from_id(id: DefId) -> DefIdForest<'tcx> {
DefIdForest::Single(id) DefIdForest::Single(id)
} }
@ -61,11 +59,11 @@ impl<'tcx> DefIdForest {
} }
// Only allocates in the rare `Multiple` case. // Only allocates in the rare `Multiple` case.
fn from_slice(root_ids: &[DefId]) -> DefIdForest { fn from_vec(tcx: TyCtxt<'tcx>, root_ids: SmallVec<[DefId; 1]>) -> DefIdForest<'tcx> {
match root_ids { match &root_ids[..] {
[] => Empty, [] => Empty,
[id] => Single(*id), [id] => Single(*id),
_ => DefIdForest::Multiple(root_ids.into()), _ => DefIdForest::Multiple(tcx.arena.alloc_from_iter(root_ids)),
} }
} }
@ -88,9 +86,9 @@ impl<'tcx> DefIdForest {
} }
/// Calculate the intersection of a collection of forests. /// Calculate the intersection of a collection of forests.
pub fn intersection<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest pub fn intersection<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest<'tcx>
where where
I: IntoIterator<Item = DefIdForest>, I: IntoIterator<Item = DefIdForest<'tcx>>,
{ {
let mut iter = iter.into_iter(); let mut iter = iter.into_iter();
let mut ret: SmallVec<[_; 1]> = if let Some(first) = iter.next() { let mut ret: SmallVec<[_; 1]> = if let Some(first) = iter.next() {
@ -114,13 +112,13 @@ impl<'tcx> DefIdForest {
mem::swap(&mut next_ret, &mut ret); mem::swap(&mut next_ret, &mut ret);
next_ret.clear(); next_ret.clear();
} }
DefIdForest::from_slice(&ret) DefIdForest::from_vec(tcx, ret)
} }
/// Calculate the union of a collection of forests. /// Calculate the union of a collection of forests.
pub fn union<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest pub fn union<I>(tcx: TyCtxt<'tcx>, iter: I) -> DefIdForest<'tcx>
where where
I: IntoIterator<Item = DefIdForest>, I: IntoIterator<Item = DefIdForest<'tcx>>,
{ {
let mut ret: SmallVec<[_; 1]> = SmallVec::new(); let mut ret: SmallVec<[_; 1]> = SmallVec::new();
let mut next_ret: SmallVec<[_; 1]> = SmallVec::new(); let mut next_ret: SmallVec<[_; 1]> = SmallVec::new();
@ -142,6 +140,6 @@ impl<'tcx> DefIdForest {
mem::swap(&mut next_ret, &mut ret); mem::swap(&mut next_ret, &mut ret);
next_ret.clear(); next_ret.clear();
} }
DefIdForest::from_slice(&ret) DefIdForest::from_vec(tcx, ret)
} }
} }

View file

@ -112,7 +112,7 @@ impl<'tcx> AdtDef {
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> DefIdForest { ) -> DefIdForest<'tcx> {
// Non-exhaustive ADTs from other crates are always considered inhabited. // Non-exhaustive ADTs from other crates are always considered inhabited.
if self.is_variant_list_non_exhaustive() && !self.did.is_local() { if self.is_variant_list_non_exhaustive() && !self.did.is_local() {
DefIdForest::empty() DefIdForest::empty()
@ -135,7 +135,7 @@ impl<'tcx> VariantDef {
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
adt_kind: AdtKind, adt_kind: AdtKind,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> DefIdForest { ) -> DefIdForest<'tcx> {
let is_enum = match adt_kind { let is_enum = match adt_kind {
// For now, `union`s are never considered uninhabited. // For now, `union`s are never considered uninhabited.
// The precise semantics of inhabitedness with respect to unions is currently undecided. // The precise semantics of inhabitedness with respect to unions is currently undecided.
@ -163,7 +163,7 @@ impl<'tcx> FieldDef {
substs: SubstsRef<'tcx>, substs: SubstsRef<'tcx>,
is_enum: bool, is_enum: bool,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> DefIdForest { ) -> DefIdForest<'tcx> {
let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env); let data_uninhabitedness = move || self.ty(tcx, substs).uninhabited_from(tcx, param_env);
// FIXME(canndrew): Currently enum fields are (incorrectly) stored with // FIXME(canndrew): Currently enum fields are (incorrectly) stored with
// `Visibility::Invisible` so we need to override `self.vis` if we're // `Visibility::Invisible` so we need to override `self.vis` if we're
@ -190,7 +190,7 @@ impl<'tcx> TyS<'tcx> {
&'tcx self, &'tcx self,
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
param_env: ty::ParamEnv<'tcx>, param_env: ty::ParamEnv<'tcx>,
) -> DefIdForest { ) -> DefIdForest<'tcx> {
tcx.type_uninhabited_from(param_env.and(self)).clone() tcx.type_uninhabited_from(param_env.and(self)).clone()
} }
} }
@ -199,7 +199,7 @@ impl<'tcx> TyS<'tcx> {
pub(crate) fn type_uninhabited_from<'tcx>( pub(crate) fn type_uninhabited_from<'tcx>(
tcx: TyCtxt<'tcx>, tcx: TyCtxt<'tcx>,
key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>, key: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
) -> DefIdForest { ) -> DefIdForest<'tcx> {
let ty = key.value; let ty = key.value;
let param_env = key.param_env; let param_env = key.param_env;
match *ty.kind() { match *ty.kind() {