]>
git.proxmox.com Git - rustc.git/blob - src/librustc/ty/inhabitedness/def_id_forest.rs
2 use smallvec
::SmallVec
;
3 use rustc
::hir
::CRATE_HIR_ID
;
4 use crate::ty
::context
::TyCtxt
;
5 use crate::ty
::{DefId, DefIdTree}
;
7 /// Represents a forest of `DefId`s closed under the ancestor relation. That is,
8 /// if a `DefId` representing a module is contained in the forest then all
9 /// `DefId`s defined in that module or submodules are also implicitly contained
12 /// This is used to represent a set of modules in which a type is visibly
15 pub struct DefIdForest
{
16 /// The minimal set of `DefId`s required to represent the whole set.
17 /// If A and B are DefIds in the `DefIdForest`, and A is a descendant
18 /// of B, then only B will be in `root_ids`.
19 /// We use a `SmallVec` here because (for its use for caching inhabitedness)
20 /// its rare that this will contain even two IDs.
21 root_ids
: SmallVec
<[DefId
; 1]>,
24 impl<'tcx
> DefIdForest
{
25 /// Creates an empty forest.
26 pub fn empty() -> DefIdForest
{
28 root_ids
: SmallVec
::new(),
32 /// Creates a forest consisting of a single tree representing the entire
35 pub fn full(tcx
: TyCtxt
<'tcx
>) -> DefIdForest
{
36 let crate_id
= tcx
.hir().local_def_id(CRATE_HIR_ID
);
37 DefIdForest
::from_id(crate_id
)
40 /// Creates a forest containing a `DefId` and all its descendants.
41 pub fn from_id(id
: DefId
) -> DefIdForest
{
42 let mut root_ids
= SmallVec
::new();
49 /// Tests whether the forest is empty.
50 pub fn is_empty(&self) -> bool
{
51 self.root_ids
.is_empty()
54 /// Tests whether the forest contains a given DefId.
55 pub fn contains(&self, tcx
: TyCtxt
<'tcx
>, id
: DefId
) -> bool
{
56 self.root_ids
.iter().any(|root_id
| tcx
.is_descendant_of(id
, *root_id
))
59 /// Calculate the intersection of a collection of forests.
60 pub fn intersection
<I
>(tcx
: TyCtxt
<'tcx
>, iter
: I
) -> DefIdForest
62 I
: IntoIterator
<Item
= DefIdForest
>,
64 let mut iter
= iter
.into_iter();
65 let mut ret
= if let Some(first
) = iter
.next() {
68 return DefIdForest
::full(tcx
);
71 let mut next_ret
= SmallVec
::new();
72 let mut old_ret
: SmallVec
<[DefId
; 1]> = SmallVec
::new();
73 for next_forest
in iter
{
74 // No need to continue if the intersection is already empty.
79 for id
in ret
.root_ids
.drain(..) {
80 if next_forest
.contains(tcx
, id
) {
86 ret
.root_ids
.extend(old_ret
.drain(..));
88 next_ret
.extend(next_forest
.root_ids
.into_iter().filter(|&id
| ret
.contains(tcx
, id
)));
90 mem
::swap(&mut next_ret
, &mut ret
.root_ids
);
96 /// Calculate the union of a collection of forests.
97 pub fn union<I
>(tcx
: TyCtxt
<'tcx
>, iter
: I
) -> DefIdForest
99 I
: IntoIterator
<Item
= DefIdForest
>,
101 let mut ret
= DefIdForest
::empty();
102 let mut next_ret
= SmallVec
::new();
103 for next_forest
in iter
{
104 next_ret
.extend(ret
.root_ids
.drain(..).filter(|&id
| !next_forest
.contains(tcx
, id
)));
106 for id
in next_forest
.root_ids
{
107 if !next_ret
.contains(&id
) {
112 mem
::swap(&mut next_ret
, &mut ret
.root_ids
);