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.
12 use middle
::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
) {
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.
74 self.add_flags(TypeFlags
::HAS_TY_ERR
)
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
);
82 self.add_flags(TypeFlags
::HAS_PARAMS
);
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
);
94 self.add_flags(TypeFlags
::HAS_LOCAL_NAMES
); // it might, right?
95 self.add_flags(TypeFlags
::HAS_TY_INFER
)
98 &ty
::TyEnum(_
, substs
) | &ty
::TyStruct(_
, substs
) => {
99 self.add_substs(substs
);
102 &ty
::TyProjection(ref data
) => {
103 self.add_flags(TypeFlags
::HAS_PROJECTION
);
104 self.add_projection_ty(data
);
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
);
115 self.add_bound_computation(&computation
);
117 self.add_bounds(bounds
);
120 &ty
::TyBox(tt
) | &ty
::TyArray(tt
, _
) | &ty
::TySlice(tt
) => {
124 &ty
::TyRawPtr(ref m
) => {
128 &ty
::TyRef(r
, ref m
) => {
133 &ty
::TyTuple(ref ts
) => {
134 self.add_tys(&ts
[..]);
137 &ty
::TyBareFn(_
, ref f
) => {
138 self.add_fn_sig(&f
.sig
);
143 fn add_ty(&mut self, ty
: Ty
) {
144 self.add_flags(ty
.flags
.get());
145 self.add_depth(ty
.region_depth
);
148 fn add_tys(&mut self, tys
: &[Ty
]) {
154 fn add_fn_sig(&mut self, fn_sig
: &ty
::PolyFnSig
) {
155 let mut computation
= FlagComputation
::new();
157 computation
.add_tys(&fn_sig
.0.inputs
);
159 if let ty
::FnConverging(output
) = fn_sig
.0.output
{
160 computation
.add_ty(output
);
163 self.add_bound_computation(&computation
);
166 fn add_region(&mut self, r
: ty
::Region
) {
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); }
173 _
=> { self.add_flags(TypeFlags::HAS_FREE_REGIONS); }
177 self.add_flags(TypeFlags
::HAS_LOCAL_NAMES
);
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
);
186 fn add_projection_ty(&mut self, projection_ty
: &ty
::ProjectionTy
) {
187 self.add_substs(projection_ty
.trait_ref
.substs
);
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
) => {
202 fn add_bounds(&mut self, bounds
: &ty
::ExistentialBounds
) {
203 self.add_region(bounds
.region_bound
);