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.
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.
11 use mir::interpret::ConstValue;
12 use ty::subst::Substs;
13 use ty::{self, Ty, TypeFlags, TypeFoldable};
16 pub struct FlagComputation {
19 // see `TyS::outer_exclusive_binder` for details
20 pub outer_exclusive_binder: ty::DebruijnIndex,
23 impl FlagComputation {
24 fn new() -> FlagComputation {
26 flags: TypeFlags::empty(),
27 outer_exclusive_binder: ty::INNERMOST,
31 pub fn for_sty(st: &ty::TypeVariants) -> FlagComputation {
32 let mut result = FlagComputation::new();
37 fn add_flags(&mut self, flags: TypeFlags) {
38 self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
41 /// indicates that `self` refers to something at binding level `binder`
42 fn add_binder(&mut self, binder: ty::DebruijnIndex) {
43 let exclusive_binder = binder.shifted_in(1);
44 self.add_exclusive_binder(exclusive_binder);
47 /// indicates that `self` refers to something *inside* binding
48 /// level `binder` -- not bound by `binder`, but bound by the next
49 /// binder internal to it
50 fn add_exclusive_binder(&mut self, exclusive_binder: ty::DebruijnIndex) {
51 self.outer_exclusive_binder = self.outer_exclusive_binder.max(exclusive_binder);
54 /// Adds the flags/depth from a set of types that appear within the current type, but within a
56 fn add_bound_computation(&mut self, computation: &FlagComputation) {
57 self.add_flags(computation.flags);
59 // The types that contributed to `computation` occurred within
60 // a region binder, so subtract one from the region depth
61 // within when adding the depth to `self`.
62 let outer_exclusive_binder = computation.outer_exclusive_binder;
63 if outer_exclusive_binder > ty::INNERMOST {
64 self.add_exclusive_binder(outer_exclusive_binder.shifted_out(1));
66 // otherwise, this binder captures nothing
70 fn add_sty(&mut self, st: &ty::TypeVariants) {
79 &ty::TyForeign(..) => {
82 // You might think that we could just return TyError for
83 // any type containing TyError as a component, and get
84 // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with
85 // the exception of function types that return bot).
86 // But doing so caused sporadic memory corruption, and
87 // neither I (tjc) nor nmatsakis could figure out why,
88 // so we're doing it this way.
90 self.add_flags(TypeFlags::HAS_TY_ERR)
93 &ty::TyParam(ref p) => {
94 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
96 self.add_flags(TypeFlags::HAS_SELF);
98 self.add_flags(TypeFlags::HAS_PARAMS);
102 &ty::TyGenerator(_, ref substs, _) => {
103 self.add_flags(TypeFlags::HAS_TY_CLOSURE);
104 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
105 self.add_substs(&substs.substs);
108 &ty::TyGeneratorWitness(ref ts) => {
109 let mut computation = FlagComputation::new();
110 computation.add_tys(&ts.skip_binder()[..]);
111 self.add_bound_computation(&computation);
114 &ty::TyClosure(_, ref substs) => {
115 self.add_flags(TypeFlags::HAS_TY_CLOSURE);
116 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES);
117 self.add_substs(&substs.substs);
120 &ty::TyInfer(infer) => {
121 self.add_flags(TypeFlags::HAS_FREE_LOCAL_NAMES); // it might, right?
122 self.add_flags(TypeFlags::HAS_TY_INFER);
126 ty::FreshFloatTy(_) |
127 ty::CanonicalTy(_) => {
128 self.add_flags(TypeFlags::HAS_CANONICAL_VARS);
134 self.add_flags(TypeFlags::KEEP_IN_LOCAL_TCX)
139 &ty::TyAdt(_, substs) => {
140 self.add_substs(substs);
143 &ty::TyProjection(ref data) => {
144 // currently we can't normalize projections that
145 // include bound regions, so track those separately.
146 if !data.has_escaping_regions() {
147 self.add_flags(TypeFlags::HAS_NORMALIZABLE_PROJECTION);
149 self.add_flags(TypeFlags::HAS_PROJECTION);
150 self.add_projection_ty(data);
153 &ty::TyAnon(_, substs) => {
154 self.add_flags(TypeFlags::HAS_PROJECTION);
155 self.add_substs(substs);
158 &ty::TyDynamic(ref obj, r) => {
159 let mut computation = FlagComputation::new();
160 for predicate in obj.skip_binder().iter() {
162 ty::ExistentialPredicate::Trait(tr) => computation.add_substs(tr.substs),
163 ty::ExistentialPredicate::Projection(p) => {
164 let mut proj_computation = FlagComputation::new();
165 proj_computation.add_existential_projection(&p);
166 self.add_bound_computation(&proj_computation);
168 ty::ExistentialPredicate::AutoTrait(_) => {}
171 self.add_bound_computation(&computation);
175 &ty::TyArray(tt, len) => {
180 &ty::TySlice(tt) => {
184 &ty::TyRawPtr(ref m) => {
188 &ty::TyRef(r, ty, _) => {
193 &ty::TyTuple(ref ts) => {
194 self.add_tys(&ts[..]);
197 &ty::TyFnDef(_, substs) => {
198 self.add_substs(substs);
207 fn add_ty(&mut self, ty: Ty) {
208 self.add_flags(ty.flags);
209 self.add_exclusive_binder(ty.outer_exclusive_binder);
212 fn add_tys(&mut self, tys: &[Ty]) {
218 fn add_fn_sig(&mut self, fn_sig: ty::PolyFnSig) {
219 let mut computation = FlagComputation::new();
221 computation.add_tys(fn_sig.skip_binder().inputs());
222 computation.add_ty(fn_sig.skip_binder().output());
224 self.add_bound_computation(&computation);
227 fn add_region(&mut self, r: ty::Region) {
228 self.add_flags(r.type_flags());
229 if let ty::ReLateBound(debruijn, _) = *r {
230 self.add_binder(debruijn);
234 fn add_const(&mut self, constant: &ty::Const) {
235 self.add_ty(constant.ty);
236 if let ConstValue::Unevaluated(_, substs) = constant.val {
237 self.add_flags(TypeFlags::HAS_PROJECTION);
238 self.add_substs(substs);
242 fn add_existential_projection(&mut self, projection: &ty::ExistentialProjection) {
243 self.add_substs(projection.substs);
244 self.add_ty(projection.ty);
247 fn add_projection_ty(&mut self, projection_ty: &ty::ProjectionTy) {
248 self.add_substs(projection_ty.substs);
251 fn add_substs(&mut self, substs: &Substs) {
252 for ty in substs.types() {
256 for r in substs.regions() {