]>
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 | ||
11 | use middle::subst; | |
9cc50fc6 | 12 | use middle::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(_) | | |
63 | &ty::TyStr => { | |
64 | } | |
65 | ||
66 | // You might think that we could just return TyError for | |
67 | // any type containing TyError as a component, and get | |
68 | // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with | |
69 | // the exception of function types that return bot). | |
70 | // But doing so caused sporadic memory corruption, and | |
71 | // neither I (tjc) nor nmatsakis could figure out why, | |
72 | // so we're doing it this way. | |
73 | &ty::TyError => { | |
74 | self.add_flags(TypeFlags::HAS_TY_ERR) | |
75 | } | |
76 | ||
77 | &ty::TyParam(ref p) => { | |
78 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
79 | if p.space == subst::SelfSpace { | |
80 | self.add_flags(TypeFlags::HAS_SELF); | |
81 | } else { | |
82 | self.add_flags(TypeFlags::HAS_PARAMS); | |
83 | } | |
84 | } | |
85 | ||
86 | &ty::TyClosure(_, ref substs) => { | |
87 | self.add_flags(TypeFlags::HAS_TY_CLOSURE); | |
88 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
89 | self.add_substs(&substs.func_substs); | |
90 | self.add_tys(&substs.upvar_tys); | |
91 | } | |
92 | ||
93 | &ty::TyInfer(_) => { | |
94 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right? | |
95 | self.add_flags(TypeFlags::HAS_TY_INFER) | |
96 | } | |
97 | ||
98 | &ty::TyEnum(_, substs) | &ty::TyStruct(_, substs) => { | |
99 | self.add_substs(substs); | |
100 | } | |
101 | ||
102 | &ty::TyProjection(ref data) => { | |
103 | self.add_flags(TypeFlags::HAS_PROJECTION); | |
104 | self.add_projection_ty(data); | |
105 | } | |
106 | ||
107 | &ty::TyTrait(box ty::TraitTy { ref principal, ref bounds }) => { | |
108 | let mut computation = FlagComputation::new(); | |
109 | computation.add_substs(principal.0.substs); | |
110 | for projection_bound in &bounds.projection_bounds { | |
111 | let mut proj_computation = FlagComputation::new(); | |
112 | proj_computation.add_projection_predicate(&projection_bound.0); | |
113 | self.add_bound_computation(&proj_computation); | |
114 | } | |
115 | self.add_bound_computation(&computation); | |
116 | ||
117 | self.add_bounds(bounds); | |
118 | } | |
119 | ||
120 | &ty::TyBox(tt) | &ty::TyArray(tt, _) | &ty::TySlice(tt) => { | |
121 | self.add_ty(tt) | |
122 | } | |
123 | ||
124 | &ty::TyRawPtr(ref m) => { | |
125 | self.add_ty(m.ty); | |
126 | } | |
127 | ||
128 | &ty::TyRef(r, ref m) => { | |
129 | self.add_region(*r); | |
130 | self.add_ty(m.ty); | |
131 | } | |
132 | ||
133 | &ty::TyTuple(ref ts) => { | |
134 | self.add_tys(&ts[..]); | |
135 | } | |
136 | ||
137 | &ty::TyBareFn(_, ref f) => { | |
138 | self.add_fn_sig(&f.sig); | |
139 | } | |
140 | } | |
141 | } | |
142 | ||
143 | fn add_ty(&mut self, ty: Ty) { | |
144 | self.add_flags(ty.flags.get()); | |
145 | self.add_depth(ty.region_depth); | |
146 | } | |
147 | ||
148 | fn add_tys(&mut self, tys: &[Ty]) { | |
149 | for &ty in tys { | |
150 | self.add_ty(ty); | |
151 | } | |
152 | } | |
153 | ||
154 | fn add_fn_sig(&mut self, fn_sig: &ty::PolyFnSig) { | |
155 | let mut computation = FlagComputation::new(); | |
156 | ||
157 | computation.add_tys(&fn_sig.0.inputs); | |
158 | ||
159 | if let ty::FnConverging(output) = fn_sig.0.output { | |
160 | computation.add_ty(output); | |
161 | } | |
162 | ||
163 | self.add_bound_computation(&computation); | |
164 | } | |
165 | ||
166 | fn add_region(&mut self, r: ty::Region) { | |
167 | match r { | |
168 | ty::ReVar(..) | | |
169 | ty::ReSkolemized(..) => { self.add_flags(TypeFlags::HAS_RE_INFER); } | |
170 | ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); } | |
171 | ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); } | |
172 | ty::ReStatic => {} | |
173 | _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); } | |
174 | } | |
175 | ||
176 | if !r.is_global() { | |
177 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
178 | } | |
179 | } | |
180 | ||
181 | fn add_projection_predicate(&mut self, projection_predicate: &ty::ProjectionPredicate) { | |
182 | self.add_projection_ty(&projection_predicate.projection_ty); | |
183 | self.add_ty(projection_predicate.ty); | |
184 | } | |
185 | ||
186 | fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) { | |
187 | self.add_substs(projection_ty.trait_ref.substs); | |
188 | } | |
189 | ||
190 | fn add_substs(&mut self, substs: &subst::Substs) { | |
191 | self.add_tys(substs.types.as_slice()); | |
192 | match substs.regions { | |
193 | subst::ErasedRegions => {} | |
194 | subst::NonerasedRegions(ref regions) => { | |
195 | for &r in regions { | |
196 | self.add_region(r); | |
197 | } | |
198 | } | |
199 | } | |
200 | } | |
201 | ||
202 | fn add_bounds(&mut self, bounds: &ty::ExistentialBounds) { | |
203 | self.add_region(bounds.region_bound); | |
204 | } | |
205 | } |