1 use crate::ty
::context
::TyCtxt
;
2 use crate::ty
::{DefId, DefIdTree}
;
3 use rustc_hir
::CRATE_HIR_ID
;
4 use smallvec
::SmallVec
;
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 /// it's 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
{
27 DefIdForest { root_ids: SmallVec::new() }
30 /// Creates a forest consisting of a single tree representing the entire
33 pub fn full(tcx
: TyCtxt
<'tcx
>) -> DefIdForest
{
34 let crate_id
= tcx
.hir().local_def_id(CRATE_HIR_ID
);
35 DefIdForest
::from_id(crate_id
.to_def_id())
38 /// Creates a forest containing a `DefId` and all its descendants.
39 pub fn from_id(id
: DefId
) -> DefIdForest
{
40 let mut root_ids
= SmallVec
::new();
42 DefIdForest { root_ids }
45 /// Tests whether the forest is empty.
46 pub fn is_empty(&self) -> bool
{
47 self.root_ids
.is_empty()
50 /// Tests whether the forest contains a given DefId.
51 pub fn contains(&self, tcx
: TyCtxt
<'tcx
>, id
: DefId
) -> bool
{
52 self.root_ids
.iter().any(|root_id
| tcx
.is_descendant_of(id
, *root_id
))
55 /// Calculate the intersection of a collection of forests.
56 pub fn intersection
<I
>(tcx
: TyCtxt
<'tcx
>, iter
: I
) -> DefIdForest
58 I
: IntoIterator
<Item
= DefIdForest
>,
60 let mut iter
= iter
.into_iter();
61 let mut ret
= if let Some(first
) = iter
.next() {
64 return DefIdForest
::full(tcx
);
67 let mut next_ret
= SmallVec
::new();
68 let mut old_ret
: SmallVec
<[DefId
; 1]> = SmallVec
::new();
69 for next_forest
in iter
{
70 // No need to continue if the intersection is already empty.
75 for id
in ret
.root_ids
.drain(..) {
76 if next_forest
.contains(tcx
, id
) {
82 ret
.root_ids
.extend(old_ret
.drain(..));
84 next_ret
.extend(next_forest
.root_ids
.into_iter().filter(|&id
| ret
.contains(tcx
, id
)));
86 mem
::swap(&mut next_ret
, &mut ret
.root_ids
);
92 /// Calculate the union of a collection of forests.
93 pub fn union<I
>(tcx
: TyCtxt
<'tcx
>, iter
: I
) -> DefIdForest
95 I
: IntoIterator
<Item
= DefIdForest
>,
97 let mut ret
= DefIdForest
::empty();
98 let mut next_ret
= SmallVec
::new();
99 for next_forest
in iter
{
100 next_ret
.extend(ret
.root_ids
.drain(..).filter(|&id
| !next_forest
.contains(tcx
, id
)));
102 for id
in next_forest
.root_ids
{
103 if !next_ret
.contains(&id
) {
108 mem
::swap(&mut next_ret
, &mut ret
.root_ids
);