]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
54a0048b | 11 | use hir::def_id::DefId; |
ea8adc8c XL |
12 | use ich::StableHashingContext; |
13 | use rustc_data_structures::stable_hasher::{StableHasher, StableHasherResult, | |
14 | HashStable}; | |
15 | use std::fmt::Debug; | |
16 | use std::hash::Hash; | |
17 | use std::mem; | |
b039eaaf | 18 | use syntax::ast; |
ea8adc8c | 19 | use ty::{self, Ty, TyCtxt}; |
1a4d82fc | 20 | |
ea8adc8c | 21 | use self::SimplifiedTypeGen::*; |
1a4d82fc | 22 | |
ea8adc8c XL |
23 | pub type SimplifiedType = SimplifiedTypeGen<DefId>; |
24 | ||
25 | /// See `simplify_type` | |
26 | /// | |
27 | /// Note that we keep this type generic over the type of identifier it uses | |
28 | /// because we sometimes need to use SimplifiedTypeGen values as stable sorting | |
29 | /// keys (in which case we use a DefPathHash as id-type) but in the general case | |
30 | /// the non-stable but fast to construct DefId-version is the better choice. | |
31 | #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] | |
32 | pub enum SimplifiedTypeGen<D> | |
33 | where D: Copy + Debug + Ord + Eq + Hash | |
34 | { | |
1a4d82fc JJ |
35 | BoolSimplifiedType, |
36 | CharSimplifiedType, | |
b039eaaf SL |
37 | IntSimplifiedType(ast::IntTy), |
38 | UintSimplifiedType(ast::UintTy), | |
39 | FloatSimplifiedType(ast::FloatTy), | |
ea8adc8c | 40 | AdtSimplifiedType(D), |
1a4d82fc | 41 | StrSimplifiedType, |
c30ab7b3 | 42 | ArraySimplifiedType, |
1a4d82fc | 43 | PtrSimplifiedType, |
5bcae85e | 44 | NeverSimplifiedType, |
c34b1796 | 45 | TupleSimplifiedType(usize), |
ea8adc8c XL |
46 | TraitSimplifiedType(D), |
47 | ClosureSimplifiedType(D), | |
48 | GeneratorSimplifiedType(D), | |
2c00a5a8 | 49 | GeneratorWitnessSimplifiedType(usize), |
ea8adc8c | 50 | AnonSimplifiedType(D), |
c34b1796 | 51 | FunctionSimplifiedType(usize), |
1a4d82fc | 52 | ParameterSimplifiedType, |
abe05a73 | 53 | ForeignSimplifiedType(DefId), |
1a4d82fc JJ |
54 | } |
55 | ||
56 | /// Tries to simplify a type by dropping type parameters, deref'ing away any reference types, etc. | |
57 | /// The idea is to get something simple that we can use to quickly decide if two types could unify | |
58 | /// during method lookup. | |
59 | /// | |
60 | /// If `can_simplify_params` is false, then we will fail to simplify type parameters entirely. This | |
61 | /// is useful when those type parameters would be instantiated with fresh type variables, since | |
62 | /// then we can't say much about whether two types would unify. Put another way, | |
63 | /// `can_simplify_params` should be true if type parameters appear free in `ty` and `false` if they | |
64 | /// are to be considered bound. | |
a7813a04 XL |
65 | pub fn simplify_type<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>, |
66 | ty: Ty, | |
67 | can_simplify_params: bool) | |
68 | -> Option<SimplifiedType> | |
1a4d82fc JJ |
69 | { |
70 | match ty.sty { | |
62682a34 SL |
71 | ty::TyBool => Some(BoolSimplifiedType), |
72 | ty::TyChar => Some(CharSimplifiedType), | |
73 | ty::TyInt(int_type) => Some(IntSimplifiedType(int_type)), | |
74 | ty::TyUint(uint_type) => Some(UintSimplifiedType(uint_type)), | |
75 | ty::TyFloat(float_type) => Some(FloatSimplifiedType(float_type)), | |
9e0c209e | 76 | ty::TyAdt(def, _) => Some(AdtSimplifiedType(def.did)), |
62682a34 | 77 | ty::TyStr => Some(StrSimplifiedType), |
c30ab7b3 | 78 | ty::TyArray(..) | ty::TySlice(_) => Some(ArraySimplifiedType), |
62682a34 | 79 | ty::TyRawPtr(_) => Some(PtrSimplifiedType), |
476ff2be SL |
80 | ty::TyDynamic(ref trait_info, ..) => { |
81 | trait_info.principal().map(|p| TraitSimplifiedType(p.def_id())) | |
1a4d82fc | 82 | } |
62682a34 | 83 | ty::TyRef(_, mt) => { |
1a4d82fc JJ |
84 | // since we introduce auto-refs during method lookup, we |
85 | // just treat &T and T as equivalent from the point of | |
86 | // view of possibly unifying | |
87 | simplify_type(tcx, mt.ty, can_simplify_params) | |
88 | } | |
041b39d2 | 89 | ty::TyFnDef(def_id, _) | |
62682a34 | 90 | ty::TyClosure(def_id, _) => { |
85aaf69f | 91 | Some(ClosureSimplifiedType(def_id)) |
1a4d82fc | 92 | } |
ea8adc8c XL |
93 | ty::TyGenerator(def_id, _, _) => { |
94 | Some(GeneratorSimplifiedType(def_id)) | |
95 | } | |
2c00a5a8 XL |
96 | ty::TyGeneratorWitness(ref tys) => { |
97 | Some(GeneratorWitnessSimplifiedType(tys.skip_binder().len())) | |
98 | } | |
5bcae85e | 99 | ty::TyNever => Some(NeverSimplifiedType), |
8bb4bdeb | 100 | ty::TyTuple(ref tys, _) => { |
1a4d82fc JJ |
101 | Some(TupleSimplifiedType(tys.len())) |
102 | } | |
041b39d2 | 103 | ty::TyFnPtr(ref f) => { |
8bb4bdeb | 104 | Some(FunctionSimplifiedType(f.skip_binder().inputs().len())) |
1a4d82fc | 105 | } |
e9174d1e | 106 | ty::TyProjection(_) | ty::TyParam(_) => { |
1a4d82fc | 107 | if can_simplify_params { |
e9174d1e SL |
108 | // In normalized types, projections don't unify with |
109 | // anything. when lazy normalization happens, this | |
110 | // will change. It would still be nice to have a way | |
111 | // to deal with known-not-to-unify-with-anything | |
112 | // projections (e.g. the likes of <__S as Encoder>::Error). | |
1a4d82fc JJ |
113 | Some(ParameterSimplifiedType) |
114 | } else { | |
115 | None | |
116 | } | |
117 | } | |
5bcae85e SL |
118 | ty::TyAnon(def_id, _) => { |
119 | Some(AnonSimplifiedType(def_id)) | |
120 | } | |
abe05a73 XL |
121 | ty::TyForeign(def_id) => { |
122 | Some(ForeignSimplifiedType(def_id)) | |
123 | } | |
62682a34 | 124 | ty::TyInfer(_) | ty::TyError => None, |
1a4d82fc JJ |
125 | } |
126 | } | |
ea8adc8c XL |
127 | |
128 | impl<D: Copy + Debug + Ord + Eq + Hash> SimplifiedTypeGen<D> { | |
129 | pub fn map_def<U, F>(self, map: F) -> SimplifiedTypeGen<U> | |
130 | where F: Fn(D) -> U, | |
131 | U: Copy + Debug + Ord + Eq + Hash, | |
132 | { | |
133 | match self { | |
134 | BoolSimplifiedType => BoolSimplifiedType, | |
135 | CharSimplifiedType => CharSimplifiedType, | |
136 | IntSimplifiedType(t) => IntSimplifiedType(t), | |
137 | UintSimplifiedType(t) => UintSimplifiedType(t), | |
138 | FloatSimplifiedType(t) => FloatSimplifiedType(t), | |
139 | AdtSimplifiedType(d) => AdtSimplifiedType(map(d)), | |
140 | StrSimplifiedType => StrSimplifiedType, | |
141 | ArraySimplifiedType => ArraySimplifiedType, | |
142 | PtrSimplifiedType => PtrSimplifiedType, | |
143 | NeverSimplifiedType => NeverSimplifiedType, | |
144 | TupleSimplifiedType(n) => TupleSimplifiedType(n), | |
145 | TraitSimplifiedType(d) => TraitSimplifiedType(map(d)), | |
146 | ClosureSimplifiedType(d) => ClosureSimplifiedType(map(d)), | |
147 | GeneratorSimplifiedType(d) => GeneratorSimplifiedType(map(d)), | |
2c00a5a8 | 148 | GeneratorWitnessSimplifiedType(n) => GeneratorWitnessSimplifiedType(n), |
ea8adc8c XL |
149 | AnonSimplifiedType(d) => AnonSimplifiedType(map(d)), |
150 | FunctionSimplifiedType(n) => FunctionSimplifiedType(n), | |
151 | ParameterSimplifiedType => ParameterSimplifiedType, | |
abe05a73 | 152 | ForeignSimplifiedType(d) => ForeignSimplifiedType(d), |
ea8adc8c XL |
153 | } |
154 | } | |
155 | } | |
156 | ||
157 | impl<'gcx, D> HashStable<StableHashingContext<'gcx>> for SimplifiedTypeGen<D> | |
158 | where D: Copy + Debug + Ord + Eq + Hash + | |
159 | HashStable<StableHashingContext<'gcx>>, | |
160 | { | |
161 | fn hash_stable<W: StableHasherResult>(&self, | |
162 | hcx: &mut StableHashingContext<'gcx>, | |
163 | hasher: &mut StableHasher<W>) { | |
164 | mem::discriminant(self).hash_stable(hcx, hasher); | |
165 | match *self { | |
166 | BoolSimplifiedType | | |
167 | CharSimplifiedType | | |
168 | StrSimplifiedType | | |
169 | ArraySimplifiedType | | |
170 | PtrSimplifiedType | | |
171 | NeverSimplifiedType | | |
172 | ParameterSimplifiedType => { | |
173 | // nothing to do | |
174 | } | |
175 | IntSimplifiedType(t) => t.hash_stable(hcx, hasher), | |
176 | UintSimplifiedType(t) => t.hash_stable(hcx, hasher), | |
177 | FloatSimplifiedType(t) => t.hash_stable(hcx, hasher), | |
178 | AdtSimplifiedType(d) => d.hash_stable(hcx, hasher), | |
179 | TupleSimplifiedType(n) => n.hash_stable(hcx, hasher), | |
180 | TraitSimplifiedType(d) => d.hash_stable(hcx, hasher), | |
181 | ClosureSimplifiedType(d) => d.hash_stable(hcx, hasher), | |
182 | GeneratorSimplifiedType(d) => d.hash_stable(hcx, hasher), | |
2c00a5a8 | 183 | GeneratorWitnessSimplifiedType(n) => n.hash_stable(hcx, hasher), |
ea8adc8c XL |
184 | AnonSimplifiedType(d) => d.hash_stable(hcx, hasher), |
185 | FunctionSimplifiedType(n) => n.hash_stable(hcx, hasher), | |
abe05a73 | 186 | ForeignSimplifiedType(d) => d.hash_stable(hcx, hasher), |
ea8adc8c XL |
187 | } |
188 | } | |
189 | } |