]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2012-2015 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 | ||
9e0c209e | 11 | use ty::subst::Substs; |
54a0048b | 12 | use ty::{self, Ty, TypeFlags, TypeFoldable}; |
e9174d1e SL |
13 | |
14 | pub struct FlagComputation { | |
15 | pub flags: TypeFlags, | |
16 | ||
17 | // maximum depth of any bound region that we have seen thus far | |
18 | pub depth: u32, | |
19 | } | |
20 | ||
21 | impl FlagComputation { | |
22 | fn new() -> FlagComputation { | |
23 | FlagComputation { flags: TypeFlags::empty(), depth: 0 } | |
24 | } | |
25 | ||
26 | pub fn for_sty(st: &ty::TypeVariants) -> FlagComputation { | |
27 | let mut result = FlagComputation::new(); | |
28 | result.add_sty(st); | |
29 | result | |
30 | } | |
31 | ||
32 | fn add_flags(&mut self, flags: TypeFlags) { | |
33 | self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS); | |
34 | } | |
35 | ||
36 | fn add_depth(&mut self, depth: u32) { | |
37 | if depth > self.depth { | |
38 | self.depth = depth; | |
39 | } | |
40 | } | |
41 | ||
42 | /// Adds the flags/depth from a set of types that appear within the current type, but within a | |
43 | /// region binder. | |
44 | fn add_bound_computation(&mut self, computation: &FlagComputation) { | |
45 | self.add_flags(computation.flags); | |
46 | ||
47 | // The types that contributed to `computation` occurred within | |
48 | // a region binder, so subtract one from the region depth | |
49 | // within when adding the depth to `self`. | |
50 | let depth = computation.depth; | |
51 | if depth > 0 { | |
52 | self.add_depth(depth - 1); | |
53 | } | |
54 | } | |
55 | ||
56 | fn add_sty(&mut self, st: &ty::TypeVariants) { | |
57 | match st { | |
58 | &ty::TyBool | | |
59 | &ty::TyChar | | |
60 | &ty::TyInt(_) | | |
61 | &ty::TyFloat(_) | | |
62 | &ty::TyUint(_) | | |
5bcae85e | 63 | &ty::TyNever | |
e9174d1e SL |
64 | &ty::TyStr => { |
65 | } | |
66 | ||
67 | // You might think that we could just return TyError for | |
68 | // any type containing TyError as a component, and get | |
69 | // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with | |
70 | // the exception of function types that return bot). | |
71 | // But doing so caused sporadic memory corruption, and | |
72 | // neither I (tjc) nor nmatsakis could figure out why, | |
73 | // so we're doing it this way. | |
74 | &ty::TyError => { | |
75 | self.add_flags(TypeFlags::HAS_TY_ERR) | |
76 | } | |
77 | ||
78 | &ty::TyParam(ref p) => { | |
79 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
9e0c209e | 80 | if p.is_self() { |
e9174d1e SL |
81 | self.add_flags(TypeFlags::HAS_SELF); |
82 | } else { | |
83 | self.add_flags(TypeFlags::HAS_PARAMS); | |
84 | } | |
85 | } | |
86 | ||
87 | &ty::TyClosure(_, ref substs) => { | |
88 | self.add_flags(TypeFlags::HAS_TY_CLOSURE); | |
89 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
90 | self.add_substs(&substs.func_substs); | |
91 | self.add_tys(&substs.upvar_tys); | |
92 | } | |
93 | ||
a7813a04 | 94 | &ty::TyInfer(infer) => { |
e9174d1e | 95 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right? |
a7813a04 XL |
96 | self.add_flags(TypeFlags::HAS_TY_INFER); |
97 | match infer { | |
98 | ty::FreshTy(_) | | |
99 | ty::FreshIntTy(_) | | |
100 | ty::FreshFloatTy(_) => {} | |
101 | _ => self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX) | |
102 | } | |
e9174d1e SL |
103 | } |
104 | ||
9e0c209e | 105 | &ty::TyAdt(_, substs) => { |
e9174d1e SL |
106 | self.add_substs(substs); |
107 | } | |
108 | ||
109 | &ty::TyProjection(ref data) => { | |
1bb2cb6e SL |
110 | // currently we can't normalize projections that |
111 | // include bound regions, so track those separately. | |
112 | if !data.has_escaping_regions() { | |
113 | self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION); | |
114 | } | |
e9174d1e SL |
115 | self.add_flags(TypeFlags::HAS_PROJECTION); |
116 | self.add_projection_ty(data); | |
117 | } | |
118 | ||
5bcae85e SL |
119 | &ty::TyAnon(_, substs) => { |
120 | self.add_flags(TypeFlags::HAS_PROJECTION); | |
121 | self.add_substs(substs); | |
122 | } | |
123 | ||
9e0c209e | 124 | &ty::TyTrait(ref obj) => { |
e9174d1e | 125 | let mut computation = FlagComputation::new(); |
9e0c209e SL |
126 | computation.add_substs(obj.principal.skip_binder().substs); |
127 | for projection_bound in &obj.projection_bounds { | |
e9174d1e | 128 | let mut proj_computation = FlagComputation::new(); |
9e0c209e | 129 | proj_computation.add_existential_projection(&projection_bound.0); |
e9174d1e SL |
130 | self.add_bound_computation(&proj_computation); |
131 | } | |
132 | self.add_bound_computation(&computation); | |
9e0c209e | 133 | self.add_region(obj.region_bound); |
e9174d1e SL |
134 | } |
135 | ||
136 | &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { | |
137 | self.add_ty(tt) | |
138 | } | |
139 | ||
140 | &ty::TyRawPtr(ref m) => { | |
141 | self.add_ty(m.ty); | |
142 | } | |
143 | ||
144 | &ty::TyRef(r, ref m) => { | |
9e0c209e | 145 | self.add_region(r); |
e9174d1e SL |
146 | self.add_ty(m.ty); |
147 | } | |
148 | ||
149 | &ty::TyTuple(ref ts) => { | |
150 | self.add_tys(&ts[..]); | |
151 | } | |
152 | ||
54a0048b SL |
153 | &ty::TyFnDef(_, substs, ref f) => { |
154 | self.add_substs(substs); | |
155 | self.add_fn_sig(&f.sig); | |
156 | } | |
157 | ||
158 | &ty::TyFnPtr(ref f) => { | |
e9174d1e SL |
159 | self.add_fn_sig(&f.sig); |
160 | } | |
161 | } | |
162 | } | |
163 | ||
164 | fn add_ty(&mut self, ty: Ty) { | |
165 | self.add_flags(ty.flags.get()); | |
166 | self.add_depth(ty.region_depth); | |
167 | } | |
168 | ||
169 | fn add_tys(&mut self, tys: &[Ty]) { | |
170 | for &ty in tys { | |
171 | self.add_ty(ty); | |
172 | } | |
173 | } | |
174 | ||
175 | fn add_fn_sig(&mut self, fn_sig: &ty::PolyFnSig) { | |
176 | let mut computation = FlagComputation::new(); | |
177 | ||
178 | computation.add_tys(&fn_sig.0.inputs); | |
5bcae85e | 179 | computation.add_ty(fn_sig.0.output); |
e9174d1e SL |
180 | |
181 | self.add_bound_computation(&computation); | |
182 | } | |
183 | ||
9e0c209e SL |
184 | fn add_region(&mut self, r: &ty::Region) { |
185 | match *r { | |
3157f602 XL |
186 | ty::ReVar(..) => { |
187 | self.add_flags(TypeFlags::HAS_RE_INFER); | |
188 | self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX); | |
189 | } | |
a7813a04 XL |
190 | ty::ReSkolemized(..) => { |
191 | self.add_flags(TypeFlags::HAS_RE_INFER); | |
3157f602 | 192 | self.add_flags(TypeFlags::HAS_RE_SKOL); |
a7813a04 XL |
193 | self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX); |
194 | } | |
e9174d1e SL |
195 | ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); } |
196 | ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); } | |
3157f602 | 197 | ty::ReStatic | ty::ReErased => {} |
e9174d1e SL |
198 | _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); } |
199 | } | |
200 | ||
201 | if !r.is_global() { | |
202 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
203 | } | |
204 | } | |
205 | ||
9e0c209e SL |
206 | fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) { |
207 | self.add_substs(projection.trait_ref.substs); | |
208 | self.add_ty(projection.ty); | |
e9174d1e SL |
209 | } |
210 | ||
211 | fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) { | |
212 | self.add_substs(projection_ty.trait_ref.substs); | |
213 | } | |
214 | ||
9e0c209e SL |
215 | fn add_substs(&mut self, substs: &Substs) { |
216 | for ty in substs.types() { | |
217 | self.add_ty(ty); | |
e9174d1e | 218 | } |
e9174d1e | 219 | |
9e0c209e SL |
220 | for r in substs.regions() { |
221 | self.add_region(r); | |
222 | } | |
e9174d1e SL |
223 | } |
224 | } |