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 ty
::subst
::Substs
;
12 use ty
::{self, Ty, TypeFlags, TypeFoldable}
;
14 pub struct FlagComputation
{
17 // maximum depth of any bound region that we have seen thus far
21 impl FlagComputation
{
22 fn new() -> FlagComputation
{
23 FlagComputation { flags: TypeFlags::empty(), depth: 0 }
26 pub fn for_sty(st
: &ty
::TypeVariants
) -> FlagComputation
{
27 let mut result
= FlagComputation
::new();
32 fn add_flags(&mut self, flags
: TypeFlags
) {
33 self.flags
= self.flags
| (flags
& TypeFlags
::NOMINAL_FLAGS
);
36 fn add_depth(&mut self, depth
: u32) {
37 if depth
> self.depth
{
42 /// Adds the flags/depth from a set of types that appear within the current type, but within a
44 fn add_bound_computation(&mut self, computation
: &FlagComputation
) {
45 self.add_flags(computation
.flags
);
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
;
52 self.add_depth(depth
- 1);
56 fn add_sty(&mut self, st
: &ty
::TypeVariants
) {
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.
75 self.add_flags(TypeFlags
::HAS_TY_ERR
)
78 &ty
::TyParam(ref p
) => {
79 self.add_flags(TypeFlags
::HAS_LOCAL_NAMES
);
81 self.add_flags(TypeFlags
::HAS_SELF
);
83 self.add_flags(TypeFlags
::HAS_PARAMS
);
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
);
94 &ty
::TyInfer(infer
) => {
95 self.add_flags(TypeFlags
::HAS_LOCAL_NAMES
); // it might, right?
96 self.add_flags(TypeFlags
::HAS_TY_INFER
);
100 ty
::FreshFloatTy(_
) => {}
101 _
=> self.add_flags(TypeFlags
::KEEP_IN_LOCAL_TCX
)
105 &ty
::TyAdt(_
, substs
) => {
106 self.add_substs(substs
);
109 &ty
::TyProjection(ref data
) => {
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
);
115 self.add_flags(TypeFlags
::HAS_PROJECTION
);
116 self.add_projection_ty(data
);
119 &ty
::TyAnon(_
, substs
) => {
120 self.add_flags(TypeFlags
::HAS_PROJECTION
);
121 self.add_substs(substs
);
124 &ty
::TyTrait(ref obj
) => {
125 let mut computation
= FlagComputation
::new();
126 computation
.add_substs(obj
.principal
.skip_binder().substs
);
127 for projection_bound
in &obj
.projection_bounds
{
128 let mut proj_computation
= FlagComputation
::new();
129 proj_computation
.add_existential_projection(&projection_bound
.0);
130 self.add_bound_computation(&proj_computation
);
132 self.add_bound_computation(&computation
);
133 self.add_region(obj
.region_bound
);
136 &ty
::TyBox(tt
) | &ty
::TyArray(tt
, _
) | &ty
::TySlice(tt
) => {
140 &ty
::TyRawPtr(ref m
) => {
144 &ty
::TyRef(r
, ref m
) => {
149 &ty
::TyTuple(ref ts
) => {
150 self.add_tys(&ts
[..]);
153 &ty
::TyFnDef(_
, substs
, ref f
) => {
154 self.add_substs(substs
);
155 self.add_fn_sig(&f
.sig
);
158 &ty
::TyFnPtr(ref f
) => {
159 self.add_fn_sig(&f
.sig
);
164 fn add_ty(&mut self, ty
: Ty
) {
165 self.add_flags(ty
.flags
.get());
166 self.add_depth(ty
.region_depth
);
169 fn add_tys(&mut self, tys
: &[Ty
]) {
175 fn add_fn_sig(&mut self, fn_sig
: &ty
::PolyFnSig
) {
176 let mut computation
= FlagComputation
::new();
178 computation
.add_tys(&fn_sig
.0.inputs
);
179 computation
.add_ty(fn_sig
.0.output
);
181 self.add_bound_computation(&computation
);
184 fn add_region(&mut self, r
: &ty
::Region
) {
187 self.add_flags(TypeFlags
::HAS_RE_INFER
);
188 self.add_flags(TypeFlags
::KEEP_IN_LOCAL_TCX
);
190 ty
::ReSkolemized(..) => {
191 self.add_flags(TypeFlags
::HAS_RE_INFER
);
192 self.add_flags(TypeFlags
::HAS_RE_SKOL
);
193 self.add_flags(TypeFlags
::KEEP_IN_LOCAL_TCX
);
195 ty
::ReLateBound(debruijn
, _
) => { self.add_depth(debruijn.depth); }
196 ty
::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); }
197 ty
::ReStatic
| ty
::ReErased
=> {}
198 _
=> { self.add_flags(TypeFlags::HAS_FREE_REGIONS); }
202 self.add_flags(TypeFlags
::HAS_LOCAL_NAMES
);
206 fn add_existential_projection(&mut self, projection
: &ty
::ExistentialProjection
) {
207 self.add_substs(projection
.trait_ref
.substs
);
208 self.add_ty(projection
.ty
);
211 fn add_projection_ty(&mut self, projection_ty
: &ty
::ProjectionTy
) {
212 self.add_substs(projection_ty
.trait_ref
.substs
);
215 fn add_substs(&mut self, substs
: &Substs
) {
216 for ty
in substs
.types() {
220 for r
in substs
.regions() {