1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
use rustc_hir::def::DefKind;
use rustc_middle::ty::*;

/// Just like `TyCtxt::predicates_of`, but in the case of a trait or impl item or closures,
/// also includes the predicates defined on the parents. Also this returns the special
/// `Self` clause separately.
pub fn predicates_of_or_above<'tcx>(
    tcx: TyCtxt<'tcx>,
    did: rustc_span::def_id::DefId,
) -> (
    Vec<PolyTraitPredicate<'tcx>>,
    Option<PolyTraitPredicate<'tcx>>,
) {
    use DefKind::*;
    let def_kind = tcx.def_kind(did);

    let (mut predicates, mut self_pred) = match def_kind {
        // These inherit some predicates from their parent.
        AssocTy | AssocFn | AssocConst | Closure => {
            let parent = tcx.parent(did);
            predicates_of_or_above(tcx, parent)
        }
        _ => (vec![], None),
    };

    match def_kind {
        // Don't list the predicates of traits, we already list the `Self` clause from
        // which we can resolve anything needed.
        Trait => {}
        AssocConst
        | AssocFn
        | AssocTy
        | Const
        | Enum
        | Fn
        | ForeignTy
        | Impl { .. }
        | OpaqueTy
        | Static { .. }
        | Struct
        | TraitAlias
        | TyAlias
        | Union => {
            // Only these kinds may reasonably have predicates; we have to filter
            // otherwise calling `predicates_defined_on` may ICE.
            predicates.extend(
                tcx.predicates_defined_on(did)
                    .predicates
                    .iter()
                    .filter_map(|(clause, _span)| clause.as_trait_clause()),
            );
        }
        _ => {}
    }

    // Add some extra predicates that aren't in `predicates_defined_on`.
    match def_kind {
        OpaqueTy => {
            // An opaque type (e.g. `impl Trait`) provides predicates by itself: we need to
            // account for them.
            // TODO: is this still useful? The test that used to require this doesn't anymore.
            predicates.extend(
                tcx.explicit_item_bounds(did)
                    .skip_binder() // Skips an `EarlyBinder`, likely for GATs
                    .iter()
                    .filter_map(|(clause, _span)| clause.as_trait_clause()),
            )
        }
        Trait => {
            // Add the special `Self: Trait` clause.
            // Copied from the code of `tcx.predicates_of()`.
            let self_clause: Clause<'_> = TraitRef::identity(tcx, did).upcast(tcx);
            self_pred = Some(self_clause.as_trait_clause().unwrap());
        }
        _ => {}
    }

    (predicates, self_pred)
}

/// Erase all regions. Largely copied from `tcx.erase_regions`.
pub fn erase_all_regions<'tcx, T>(tcx: TyCtxt<'tcx>, value: T) -> T
where
    T: TypeFoldable<TyCtxt<'tcx>>,
{
    use rustc_middle::ty;
    struct RegionEraserVisitor<'tcx> {
        tcx: TyCtxt<'tcx>,
    }

    impl<'tcx> TypeFolder<TyCtxt<'tcx>> for RegionEraserVisitor<'tcx> {
        fn cx(&self) -> TyCtxt<'tcx> {
            self.tcx
        }

        fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
            ty.super_fold_with(self)
        }

        fn fold_binder<T>(&mut self, t: ty::Binder<'tcx, T>) -> ty::Binder<'tcx, T>
        where
            T: TypeFoldable<TyCtxt<'tcx>>,
        {
            // Empty the binder
            Binder::dummy(t.skip_binder().fold_with(self))
        }

        fn fold_region(&mut self, _r: ty::Region<'tcx>) -> ty::Region<'tcx> {
            // We erase bound regions despite it being possibly incorrect. `for<'a> fn(&'a
            // ())` and `fn(&'free ())` are different types: they may implement different
            // traits and have a different `TypeId`. It's unclear whether this can cause us
            // to select the wrong trait reference.
            self.tcx.lifetimes.re_erased
        }
    }
    value.fold_with(&mut RegionEraserVisitor { tcx })
}

// Lifetimes are irrelevant when resolving instances.
pub fn erase_and_norm<'tcx, T>(tcx: TyCtxt<'tcx>, param_env: ParamEnv<'tcx>, x: T) -> T
where
    T: TypeFoldable<TyCtxt<'tcx>> + Copy,
{
    erase_all_regions(
        tcx,
        tcx.try_normalize_erasing_regions(param_env, x).unwrap_or(x),
    )
}