]> git.proxmox.com Git - rustc.git/blame - src/librustc/ty/flags.rs
New upstream version 1.17.0+dfsg1
[rustc.git] / src / librustc / ty / flags.rs
CommitLineData
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 11use ty::subst::Substs;
54a0048b 12use ty::{self, Ty, TypeFlags, TypeFoldable};
e9174d1e 13
c30ab7b3 14#[derive(Debug)]
e9174d1e
SL
15pub 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
22impl 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}