]>
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 | ||
54a0048b SL |
11 | use ty::subst; |
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); | |
80 | if p.space == subst::SelfSpace { | |
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 | ||
105 | &ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) => { | |
106 | self.add_substs(substs); | |
107 | } | |
108 | ||
109 | &ty::TyProjection(ref data) => { | |
110 | self.add_flags(TypeFlags::HAS_PROJECTION); | |
111 | self.add_projection_ty(data); | |
112 | } | |
113 | ||
5bcae85e SL |
114 | &ty::TyAnon(_, substs) => { |
115 | self.add_flags(TypeFlags::HAS_PROJECTION); | |
116 | self.add_substs(substs); | |
117 | } | |
118 | ||
e9174d1e SL |
119 | &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { |
120 | let mut computation = FlagComputation::new(); | |
121 | computation.add_substs(principal.0.substs); | |
122 | for projection_bound in &bounds.projection_bounds { | |
123 | let mut proj_computation = FlagComputation::new(); | |
124 | proj_computation.add_projection_predicate(&projection_bound.0); | |
125 | self.add_bound_computation(&proj_computation); | |
126 | } | |
127 | self.add_bound_computation(&computation); | |
128 | ||
129 | self.add_bounds(bounds); | |
130 | } | |
131 | ||
132 | &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { | |
133 | self.add_ty(tt) | |
134 | } | |
135 | ||
136 | &ty::TyRawPtr(ref m) => { | |
137 | self.add_ty(m.ty); | |
138 | } | |
139 | ||
140 | &ty::TyRef(r, ref m) => { | |
141 | self.add_region(*r); | |
142 | self.add_ty(m.ty); | |
143 | } | |
144 | ||
145 | &ty::TyTuple(ref ts) => { | |
146 | self.add_tys(&ts[..]); | |
147 | } | |
148 | ||
54a0048b SL |
149 | &ty::TyFnDef(_, substs, ref f) => { |
150 | self.add_substs(substs); | |
151 | self.add_fn_sig(&f.sig); | |
152 | } | |
153 | ||
154 | &ty::TyFnPtr(ref f) => { | |
e9174d1e SL |
155 | self.add_fn_sig(&f.sig); |
156 | } | |
157 | } | |
158 | } | |
159 | ||
160 | fn add_ty(&mut self, ty: Ty) { | |
161 | self.add_flags(ty.flags.get()); | |
162 | self.add_depth(ty.region_depth); | |
163 | } | |
164 | ||
165 | fn add_tys(&mut self, tys: &[Ty]) { | |
166 | for &ty in tys { | |
167 | self.add_ty(ty); | |
168 | } | |
169 | } | |
170 | ||
171 | fn add_fn_sig(&mut self, fn_sig: &ty::PolyFnSig) { | |
172 | let mut computation = FlagComputation::new(); | |
173 | ||
174 | computation.add_tys(&fn_sig.0.inputs); | |
5bcae85e | 175 | computation.add_ty(fn_sig.0.output); |
e9174d1e SL |
176 | |
177 | self.add_bound_computation(&computation); | |
178 | } | |
179 | ||
180 | fn add_region(&mut self, r: ty::Region) { | |
181 | match r { | |
3157f602 XL |
182 | ty::ReVar(..) => { |
183 | self.add_flags(TypeFlags::HAS_RE_INFER); | |
184 | self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX); | |
185 | } | |
a7813a04 XL |
186 | ty::ReSkolemized(..) => { |
187 | self.add_flags(TypeFlags::HAS_RE_INFER); | |
3157f602 | 188 | self.add_flags(TypeFlags::HAS_RE_SKOL); |
a7813a04 XL |
189 | self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX); |
190 | } | |
e9174d1e SL |
191 | ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); } |
192 | ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); } | |
3157f602 | 193 | ty::ReStatic | ty::ReErased => {} |
e9174d1e SL |
194 | _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); } |
195 | } | |
196 | ||
197 | if !r.is_global() { | |
198 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
199 | } | |
200 | } | |
201 | ||
202 | fn add_projection_predicate(&mut self, projection_predicate: &ty::ProjectionPredicate) { | |
203 | self.add_projection_ty(&projection_predicate.projection_ty); | |
204 | self.add_ty(projection_predicate.ty); | |
205 | } | |
206 | ||
207 | fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) { | |
208 | self.add_substs(projection_ty.trait_ref.substs); | |
209 | } | |
210 | ||
211 | fn add_substs(&mut self, substs: &subst::Substs) { | |
212 | self.add_tys(substs.types.as_slice()); | |
54a0048b SL |
213 | for &r in &substs.regions { |
214 | self.add_region(r); | |
e9174d1e SL |
215 | } |
216 | } | |
217 | ||
218 | fn add_bounds(&mut self, bounds: &ty::ExistentialBounds) { | |
219 | self.add_region(bounds.region_bound); | |
220 | } | |
221 | } |