]>
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 | 13 | |
c30ab7b3 | 14 | #[derive(Debug)] |
e9174d1e SL |
15 | pub struct FlagComputation { |
16 | pub flags: TypeFlags, | |
17 | ||
18 | // maximum depth of any bound region that we have seen thus far | |
19 | pub depth: u32, | |
20 | } | |
21 | ||
22 | impl FlagComputation { | |
23 | fn new() -> FlagComputation { | |
24 | FlagComputation { flags: TypeFlags::empty(), depth: 0 } | |
25 | } | |
26 | ||
27 | pub fn for_sty(st: &ty::TypeVariants) -> FlagComputation { | |
28 | let mut result = FlagComputation::new(); | |
29 | result.add_sty(st); | |
30 | result | |
31 | } | |
32 | ||
33 | fn add_flags(&mut self, flags: TypeFlags) { | |
34 | self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS); | |
35 | } | |
36 | ||
37 | fn add_depth(&mut self, depth: u32) { | |
38 | if depth > self.depth { | |
39 | self.depth = depth; | |
40 | } | |
41 | } | |
42 | ||
43 | /// Adds the flags/depth from a set of types that appear within the current type, but within a | |
44 | /// region binder. | |
45 | fn add_bound_computation(&mut self, computation: &FlagComputation) { | |
46 | self.add_flags(computation.flags); | |
47 | ||
48 | // The types that contributed to `computation` occurred within | |
49 | // a region binder, so subtract one from the region depth | |
50 | // within when adding the depth to `self`. | |
51 | let depth = computation.depth; | |
52 | if depth > 0 { | |
53 | self.add_depth(depth - 1); | |
54 | } | |
55 | } | |
56 | ||
57 | fn add_sty(&mut self, st: &ty::TypeVariants) { | |
58 | match st { | |
59 | &ty::TyBool | | |
60 | &ty::TyChar | | |
61 | &ty::TyInt(_) | | |
62 | &ty::TyFloat(_) | | |
63 | &ty::TyUint(_) | | |
5bcae85e | 64 | &ty::TyNever | |
e9174d1e SL |
65 | &ty::TyStr => { |
66 | } | |
67 | ||
68 | // You might think that we could just return TyError for | |
69 | // any type containing TyError as a component, and get | |
70 | // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with | |
71 | // the exception of function types that return bot). | |
72 | // But doing so caused sporadic memory corruption, and | |
73 | // neither I (tjc) nor nmatsakis could figure out why, | |
74 | // so we're doing it this way. | |
75 | &ty::TyError => { | |
76 | self.add_flags(TypeFlags::HAS_TY_ERR) | |
77 | } | |
78 | ||
79 | &ty::TyParam(ref p) => { | |
80 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
9e0c209e | 81 | if p.is_self() { |
e9174d1e SL |
82 | self.add_flags(TypeFlags::HAS_SELF); |
83 | } else { | |
84 | self.add_flags(TypeFlags::HAS_PARAMS); | |
85 | } | |
86 | } | |
87 | ||
88 | &ty::TyClosure(_, ref substs) => { | |
89 | self.add_flags(TypeFlags::HAS_TY_CLOSURE); | |
90 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
476ff2be | 91 | self.add_substs(&substs.substs); |
e9174d1e SL |
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 | ||
476ff2be | 124 | &ty::TyDynamic(ref obj, r) => { |
e9174d1e | 125 | let mut computation = FlagComputation::new(); |
476ff2be SL |
126 | for predicate in obj.skip_binder().iter() { |
127 | match *predicate { | |
128 | ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs), | |
129 | ty::ExistentialPredicate::Projection(p) => { | |
130 | let mut proj_computation = FlagComputation::new(); | |
131 | proj_computation.add_existential_projection(&p); | |
132 | self.add_bound_computation(&proj_computation); | |
133 | } | |
134 | ty::ExistentialPredicate::AutoTrait(_) => {} | |
135 | } | |
e9174d1e SL |
136 | } |
137 | self.add_bound_computation(&computation); | |
476ff2be | 138 | self.add_region(r); |
e9174d1e SL |
139 | } |
140 | ||
32a655c1 | 141 | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { |
e9174d1e SL |
142 | self.add_ty(tt) |
143 | } | |
144 | ||
145 | &ty::TyRawPtr(ref m) => { | |
146 | self.add_ty(m.ty); | |
147 | } | |
148 | ||
149 | &ty::TyRef(r, ref m) => { | |
9e0c209e | 150 | self.add_region(r); |
e9174d1e SL |
151 | self.add_ty(m.ty); |
152 | } | |
153 | ||
8bb4bdeb | 154 | &ty::TyTuple(ref ts, _) => { |
e9174d1e SL |
155 | self.add_tys(&ts[..]); |
156 | } | |
157 | ||
8bb4bdeb | 158 | &ty::TyFnDef(_, substs, f) => { |
54a0048b | 159 | self.add_substs(substs); |
8bb4bdeb | 160 | self.add_fn_sig(f); |
54a0048b SL |
161 | } |
162 | ||
8bb4bdeb XL |
163 | &ty::TyFnPtr(f) => { |
164 | self.add_fn_sig(f); | |
e9174d1e SL |
165 | } |
166 | } | |
167 | } | |
168 | ||
169 | fn add_ty(&mut self, ty: Ty) { | |
170 | self.add_flags(ty.flags.get()); | |
171 | self.add_depth(ty.region_depth); | |
172 | } | |
173 | ||
174 | fn add_tys(&mut self, tys: &[Ty]) { | |
175 | for &ty in tys { | |
176 | self.add_ty(ty); | |
177 | } | |
178 | } | |
179 | ||
8bb4bdeb | 180 | fn add_fn_sig(&mut self, fn_sig: ty::PolyFnSig) { |
e9174d1e SL |
181 | let mut computation = FlagComputation::new(); |
182 | ||
476ff2be SL |
183 | computation.add_tys(fn_sig.skip_binder().inputs()); |
184 | computation.add_ty(fn_sig.skip_binder().output()); | |
e9174d1e SL |
185 | |
186 | self.add_bound_computation(&computation); | |
187 | } | |
188 | ||
9e0c209e | 189 | fn add_region(&mut self, r: &ty::Region) { |
c30ab7b3 SL |
190 | self.add_flags(r.type_flags()); |
191 | if let ty::ReLateBound(debruijn, _) = *r { | |
192 | self.add_depth(debruijn.depth); | |
e9174d1e SL |
193 | } |
194 | } | |
195 | ||
9e0c209e SL |
196 | fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) { |
197 | self.add_substs(projection.trait_ref.substs); | |
198 | self.add_ty(projection.ty); | |
e9174d1e SL |
199 | } |
200 | ||
201 | fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) { | |
202 | self.add_substs(projection_ty.trait_ref.substs); | |
203 | } | |
204 | ||
9e0c209e SL |
205 | fn add_substs(&mut self, substs: &Substs) { |
206 | for ty in substs.types() { | |
207 | self.add_ty(ty); | |
e9174d1e | 208 | } |
e9174d1e | 209 | |
9e0c209e SL |
210 | for r in substs.regions() { |
211 | self.add_region(r); | |
212 | } | |
e9174d1e SL |
213 | } |
214 | } |