]>
Commit | Line | Data |
---|---|---|
1a4d82fc | 1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
223e47cc LB |
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 | ||
1a4d82fc JJ |
11 | #![allow(non_camel_case_types)] |
12 | ||
13 | pub use self::terr_vstore_kind::*; | |
14 | pub use self::type_err::*; | |
1a4d82fc JJ |
15 | pub use self::InferTy::*; |
16 | pub use self::InferRegion::*; | |
17 | pub use self::ImplOrTraitItemId::*; | |
85aaf69f | 18 | pub use self::ClosureKind::*; |
1a4d82fc JJ |
19 | pub use self::Variance::*; |
20 | pub use self::AutoAdjustment::*; | |
21 | pub use self::Representability::*; | |
1a4d82fc | 22 | pub use self::AutoRef::*; |
1a4d82fc JJ |
23 | pub use self::DtorKind::*; |
24 | pub use self::ExplicitSelfCategory::*; | |
25 | pub use self::FnOutput::*; | |
26 | pub use self::Region::*; | |
27 | pub use self::ImplOrTraitItemContainer::*; | |
28 | pub use self::BorrowKind::*; | |
29 | pub use self::ImplOrTraitItem::*; | |
30 | pub use self::BoundRegion::*; | |
62682a34 | 31 | pub use self::TypeVariants::*; |
1a4d82fc | 32 | pub use self::IntVarValue::*; |
1a4d82fc JJ |
33 | pub use self::MethodOrigin::*; |
34 | pub use self::CopyImplementationError::*; | |
35 | ||
62682a34 SL |
36 | pub use self::BuiltinBound::Send as BoundSend; |
37 | pub use self::BuiltinBound::Sized as BoundSized; | |
38 | pub use self::BuiltinBound::Copy as BoundCopy; | |
39 | pub use self::BuiltinBound::Sync as BoundSync; | |
40 | ||
41 | use ast_map::{self, LinkedPath}; | |
1a4d82fc JJ |
42 | use back::svh::Svh; |
43 | use session::Session; | |
44 | use lint; | |
223e47cc | 45 | use metadata::csearch; |
1a4d82fc | 46 | use middle; |
62682a34 | 47 | use middle::cast; |
85aaf69f | 48 | use middle::check_const; |
62682a34 | 49 | use middle::const_eval::{self, ConstVal}; |
1a4d82fc JJ |
50 | use middle::def::{self, DefMap, ExportMap}; |
51 | use middle::dependency_format; | |
d9579d0f | 52 | use middle::fast_reject; |
bd371182 | 53 | use middle::free_region::FreeRegionMap; |
62682a34 | 54 | use middle::infer::error_reporting::note_and_explain_region; |
c34b1796 | 55 | use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; |
1a4d82fc JJ |
56 | use middle::mem_categorization as mc; |
57 | use middle::region; | |
58 | use middle::resolve_lifetime; | |
59 | use middle::infer; | |
c34b1796 | 60 | use middle::pat_util; |
bd371182 | 61 | use middle::region::RegionMaps; |
1a4d82fc | 62 | use middle::stability; |
c34b1796 | 63 | use middle::subst::{self, ParamSpace, Subst, Substs, VecPerParamSpace}; |
1a4d82fc | 64 | use middle::traits; |
223e47cc | 65 | use middle::ty; |
1a4d82fc | 66 | use middle::ty_fold::{self, TypeFoldable, TypeFolder}; |
c34b1796 | 67 | use middle::ty_walk::{self, TypeWalker}; |
1a4d82fc JJ |
68 | use util::common::{memoized, ErrorReported}; |
69 | use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet}; | |
c34b1796 | 70 | use util::nodemap::FnvHashMap; |
9346a6ac | 71 | use util::num::ToPrimitive; |
1a4d82fc JJ |
72 | |
73 | use arena::TypedArena; | |
85aaf69f | 74 | use std::borrow::{Borrow, Cow}; |
c34b1796 | 75 | use std::cell::{Cell, RefCell, Ref}; |
85aaf69f SL |
76 | use std::cmp; |
77 | use std::fmt; | |
78 | use std::hash::{Hash, SipHasher, Hasher}; | |
1a4d82fc | 79 | use std::mem; |
970d7e83 | 80 | use std::ops; |
1a4d82fc | 81 | use std::rc::Rc; |
c34b1796 | 82 | use std::vec::IntoIter; |
62682a34 | 83 | use collections::enum_set::{self, EnumSet, CLike}; |
1a4d82fc JJ |
84 | use std::collections::{HashMap, HashSet}; |
85 | use syntax::abi; | |
d9579d0f | 86 | use syntax::ast::{CrateNum, DefId, ItemImpl, ItemTrait, LOCAL_CRATE}; |
1a4d82fc | 87 | use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId}; |
85aaf69f | 88 | use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility}; |
62682a34 | 89 | use syntax::ast_util::{self, is_local, local_def}; |
c34b1796 | 90 | use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt}; |
1a4d82fc JJ |
91 | use syntax::codemap::Span; |
92 | use syntax::parse::token::{self, InternedString, special_idents}; | |
c34b1796 AL |
93 | use syntax::print::pprust; |
94 | use syntax::ptr::P; | |
95 | use syntax::ast; | |
1a4d82fc JJ |
96 | |
97 | pub type Disr = u64; | |
98 | ||
99 | pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0; | |
223e47cc LB |
100 | |
101 | // Data types | |
102 | ||
1a4d82fc JJ |
103 | /// The complete set of all analyses described in this module. This is |
104 | /// produced by the driver and fed to trans and later passes. | |
62682a34 | 105 | pub struct CrateAnalysis { |
1a4d82fc JJ |
106 | pub export_map: ExportMap, |
107 | pub exported_items: middle::privacy::ExportedItems, | |
108 | pub public_items: middle::privacy::PublicItems, | |
1a4d82fc JJ |
109 | pub reachable: NodeSet, |
110 | pub name: String, | |
111 | pub glob_map: Option<GlobMap>, | |
112 | } | |
113 | ||
114 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
115 | pub struct field<'tcx> { | |
116 | pub name: ast::Name, | |
117 | pub mt: mt<'tcx> | |
118 | } | |
119 | ||
85aaf69f | 120 | #[derive(Clone, Copy, Debug)] |
1a4d82fc JJ |
121 | pub enum ImplOrTraitItemContainer { |
122 | TraitContainer(ast::DefId), | |
123 | ImplContainer(ast::DefId), | |
124 | } | |
125 | ||
126 | impl ImplOrTraitItemContainer { | |
127 | pub fn id(&self) -> ast::DefId { | |
128 | match *self { | |
129 | TraitContainer(id) => id, | |
130 | ImplContainer(id) => id, | |
131 | } | |
132 | } | |
133 | } | |
134 | ||
62682a34 | 135 | #[derive(Clone)] |
1a4d82fc | 136 | pub enum ImplOrTraitItem<'tcx> { |
d9579d0f | 137 | ConstTraitItem(Rc<AssociatedConst<'tcx>>), |
1a4d82fc | 138 | MethodTraitItem(Rc<Method<'tcx>>), |
62682a34 | 139 | TypeTraitItem(Rc<AssociatedType<'tcx>>), |
1a4d82fc JJ |
140 | } |
141 | ||
142 | impl<'tcx> ImplOrTraitItem<'tcx> { | |
143 | fn id(&self) -> ImplOrTraitItemId { | |
144 | match *self { | |
d9579d0f AL |
145 | ConstTraitItem(ref associated_const) => { |
146 | ConstTraitItemId(associated_const.def_id) | |
147 | } | |
1a4d82fc JJ |
148 | MethodTraitItem(ref method) => MethodTraitItemId(method.def_id), |
149 | TypeTraitItem(ref associated_type) => { | |
150 | TypeTraitItemId(associated_type.def_id) | |
151 | } | |
152 | } | |
153 | } | |
154 | ||
155 | pub fn def_id(&self) -> ast::DefId { | |
156 | match *self { | |
d9579d0f | 157 | ConstTraitItem(ref associated_const) => associated_const.def_id, |
1a4d82fc JJ |
158 | MethodTraitItem(ref method) => method.def_id, |
159 | TypeTraitItem(ref associated_type) => associated_type.def_id, | |
160 | } | |
161 | } | |
162 | ||
163 | pub fn name(&self) -> ast::Name { | |
164 | match *self { | |
d9579d0f | 165 | ConstTraitItem(ref associated_const) => associated_const.name, |
1a4d82fc JJ |
166 | MethodTraitItem(ref method) => method.name, |
167 | TypeTraitItem(ref associated_type) => associated_type.name, | |
168 | } | |
169 | } | |
170 | ||
d9579d0f AL |
171 | pub fn vis(&self) -> ast::Visibility { |
172 | match *self { | |
173 | ConstTraitItem(ref associated_const) => associated_const.vis, | |
174 | MethodTraitItem(ref method) => method.vis, | |
175 | TypeTraitItem(ref associated_type) => associated_type.vis, | |
176 | } | |
177 | } | |
178 | ||
1a4d82fc JJ |
179 | pub fn container(&self) -> ImplOrTraitItemContainer { |
180 | match *self { | |
d9579d0f | 181 | ConstTraitItem(ref associated_const) => associated_const.container, |
1a4d82fc JJ |
182 | MethodTraitItem(ref method) => method.container, |
183 | TypeTraitItem(ref associated_type) => associated_type.container, | |
184 | } | |
185 | } | |
186 | ||
187 | pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> { | |
188 | match *self { | |
189 | MethodTraitItem(ref m) => Some((*m).clone()), | |
d9579d0f | 190 | _ => None, |
1a4d82fc JJ |
191 | } |
192 | } | |
193 | } | |
194 | ||
85aaf69f | 195 | #[derive(Clone, Copy, Debug)] |
1a4d82fc | 196 | pub enum ImplOrTraitItemId { |
d9579d0f | 197 | ConstTraitItemId(ast::DefId), |
1a4d82fc JJ |
198 | MethodTraitItemId(ast::DefId), |
199 | TypeTraitItemId(ast::DefId), | |
200 | } | |
201 | ||
202 | impl ImplOrTraitItemId { | |
203 | pub fn def_id(&self) -> ast::DefId { | |
204 | match *self { | |
d9579d0f | 205 | ConstTraitItemId(def_id) => def_id, |
1a4d82fc JJ |
206 | MethodTraitItemId(def_id) => def_id, |
207 | TypeTraitItemId(def_id) => def_id, | |
970d7e83 | 208 | } |
1a4d82fc JJ |
209 | } |
210 | } | |
211 | ||
85aaf69f | 212 | #[derive(Clone, Debug)] |
1a4d82fc JJ |
213 | pub struct Method<'tcx> { |
214 | pub name: ast::Name, | |
85aaf69f SL |
215 | pub generics: Generics<'tcx>, |
216 | pub predicates: GenericPredicates<'tcx>, | |
1a4d82fc JJ |
217 | pub fty: BareFnTy<'tcx>, |
218 | pub explicit_self: ExplicitSelfCategory, | |
219 | pub vis: ast::Visibility, | |
220 | pub def_id: ast::DefId, | |
221 | pub container: ImplOrTraitItemContainer, | |
970d7e83 | 222 | |
1a4d82fc JJ |
223 | // If this method is provided, we need to know where it came from |
224 | pub provided_source: Option<ast::DefId> | |
225 | } | |
226 | ||
227 | impl<'tcx> Method<'tcx> { | |
228 | pub fn new(name: ast::Name, | |
229 | generics: ty::Generics<'tcx>, | |
85aaf69f | 230 | predicates: GenericPredicates<'tcx>, |
1a4d82fc JJ |
231 | fty: BareFnTy<'tcx>, |
232 | explicit_self: ExplicitSelfCategory, | |
233 | vis: ast::Visibility, | |
234 | def_id: ast::DefId, | |
235 | container: ImplOrTraitItemContainer, | |
236 | provided_source: Option<ast::DefId>) | |
237 | -> Method<'tcx> { | |
970d7e83 | 238 | Method { |
1a4d82fc | 239 | name: name, |
970d7e83 | 240 | generics: generics, |
85aaf69f | 241 | predicates: predicates, |
970d7e83 LB |
242 | fty: fty, |
243 | explicit_self: explicit_self, | |
244 | vis: vis, | |
1a4d82fc JJ |
245 | def_id: def_id, |
246 | container: container, | |
247 | provided_source: provided_source | |
970d7e83 LB |
248 | } |
249 | } | |
970d7e83 | 250 | |
1a4d82fc JJ |
251 | pub fn container_id(&self) -> ast::DefId { |
252 | match self.container { | |
253 | TraitContainer(id) => id, | |
254 | ImplContainer(id) => id, | |
255 | } | |
256 | } | |
223e47cc LB |
257 | } |
258 | ||
d9579d0f AL |
259 | #[derive(Clone, Copy, Debug)] |
260 | pub struct AssociatedConst<'tcx> { | |
261 | pub name: ast::Name, | |
262 | pub ty: Ty<'tcx>, | |
263 | pub vis: ast::Visibility, | |
264 | pub def_id: ast::DefId, | |
265 | pub container: ImplOrTraitItemContainer, | |
266 | pub default: Option<ast::DefId>, | |
267 | } | |
268 | ||
85aaf69f | 269 | #[derive(Clone, Copy, Debug)] |
62682a34 | 270 | pub struct AssociatedType<'tcx> { |
1a4d82fc | 271 | pub name: ast::Name, |
62682a34 | 272 | pub ty: Option<Ty<'tcx>>, |
1a4d82fc JJ |
273 | pub vis: ast::Visibility, |
274 | pub def_id: ast::DefId, | |
275 | pub container: ImplOrTraitItemContainer, | |
223e47cc LB |
276 | } |
277 | ||
85aaf69f | 278 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
279 | pub struct mt<'tcx> { |
280 | pub ty: Ty<'tcx>, | |
281 | pub mutbl: ast::Mutability, | |
223e47cc LB |
282 | } |
283 | ||
85aaf69f | 284 | #[derive(Clone, Copy, Debug)] |
223e47cc | 285 | pub struct field_ty { |
1a4d82fc JJ |
286 | pub name: Name, |
287 | pub id: DefId, | |
288 | pub vis: ast::Visibility, | |
289 | pub origin: ast::DefId, // The DefId of the struct in which the field is declared. | |
223e47cc LB |
290 | } |
291 | ||
1a4d82fc JJ |
292 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)] |
293 | pub struct ItemVariances { | |
294 | pub types: VecPerParamSpace<Variance>, | |
295 | pub regions: VecPerParamSpace<Variance>, | |
296 | } | |
297 | ||
62682a34 | 298 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)] |
1a4d82fc JJ |
299 | pub enum Variance { |
300 | Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type | |
301 | Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell | |
302 | Contravariant, // T<A> <: T<B> iff B <: A -- e.g., function param type | |
303 | Bivariant, // T<A> <: T<B> -- e.g., unused type parameter | |
304 | } | |
305 | ||
62682a34 | 306 | #[derive(Copy, Clone)] |
1a4d82fc | 307 | pub enum AutoAdjustment<'tcx> { |
9346a6ac AL |
308 | AdjustReifyFnPointer, // go from a fn-item type to a fn-pointer type |
309 | AdjustUnsafeFnPointer, // go from a safe fn pointer to an unsafe fn pointer | |
310 | AdjustDerefRef(AutoDerefRef<'tcx>), | |
1a4d82fc | 311 | } |
223e47cc | 312 | |
9346a6ac AL |
313 | /// Represents coercing a pointer to a different kind of pointer - where 'kind' |
314 | /// here means either or both of raw vs borrowed vs unique and fat vs thin. | |
315 | /// | |
316 | /// We transform pointers by following the following steps in order: | |
317 | /// 1. Deref the pointer `self.autoderefs` times (may be 0). | |
318 | /// 2. If `autoref` is `Some(_)`, then take the address and produce either a | |
319 | /// `&` or `*` pointer. | |
320 | /// 3. If `unsize` is `Some(_)`, then apply the unsize transformation, | |
321 | /// which will do things like convert thin pointers to fat | |
322 | /// pointers, or convert structs containing thin pointers to | |
323 | /// structs containing fat pointers, or convert between fat | |
324 | /// pointers. We don't store the details of how the transform is | |
325 | /// done (in fact, we don't know that, because it might depend on | |
326 | /// the precise type parameters). We just store the target | |
327 | /// type. Trans figures out what has to be done at monomorphization | |
328 | /// time based on the precise source/target type at hand. | |
329 | /// | |
330 | /// To make that more concrete, here are some common scenarios: | |
331 | /// | |
332 | /// 1. The simplest cases are where the pointer is not adjusted fat vs thin. | |
333 | /// Here the pointer will be dereferenced N times (where a dereference can | |
334 | /// happen to to raw or borrowed pointers or any smart pointer which implements | |
335 | /// Deref, including Box<_>). The number of dereferences is given by | |
336 | /// `autoderefs`. It can then be auto-referenced zero or one times, indicated | |
337 | /// by `autoref`, to either a raw or borrowed pointer. In these cases unsize is | |
338 | /// None. | |
339 | /// | |
340 | /// 2. A thin-to-fat coercon involves unsizing the underlying data. We start | |
341 | /// with a thin pointer, deref a number of times, unsize the underlying data, | |
342 | /// then autoref. The 'unsize' phase may change a fixed length array to a | |
343 | /// dynamically sized one, a concrete object to a trait object, or statically | |
344 | /// sized struct to a dyncamically sized one. E.g., &[i32; 4] -> &[i32] is | |
345 | /// represented by: | |
346 | /// | |
347 | /// ``` | |
348 | /// AutoDerefRef { | |
349 | /// autoderefs: 1, // &[i32; 4] -> [i32; 4] | |
350 | /// autoref: Some(AutoPtr), // [i32] -> &[i32] | |
351 | /// unsize: Some([i32]), // [i32; 4] -> [i32] | |
352 | /// } | |
353 | /// ``` | |
354 | /// | |
355 | /// Note that for a struct, the 'deep' unsizing of the struct is not recorded. | |
356 | /// E.g., `struct Foo<T> { x: T }` we can coerce &Foo<[i32; 4]> to &Foo<[i32]> | |
357 | /// The autoderef and -ref are the same as in the above example, but the type | |
358 | /// stored in `unsize` is `Foo<[i32]>`, we don't store any further detail about | |
359 | /// the underlying conversions from `[i32; 4]` to `[i32]`. | |
360 | /// | |
361 | /// 3. Coercing a `Box<T>` to `Box<Trait>` is an interesting special case. In | |
362 | /// that case, we have the pointer we need coming in, so there are no | |
363 | /// autoderefs, and no autoref. Instead we just do the `Unsize` transformation. | |
364 | /// At some point, of course, `Box` should move out of the compiler, in which | |
365 | /// case this is analogous to transformating a struct. E.g., Box<[i32; 4]> -> | |
366 | /// Box<[i32]> is represented by: | |
367 | /// | |
368 | /// ``` | |
369 | /// AutoDerefRef { | |
370 | /// autoderefs: 0, | |
371 | /// autoref: None, | |
372 | /// unsize: Some(Box<[i32]>), | |
373 | /// } | |
374 | /// ``` | |
62682a34 | 375 | #[derive(Copy, Clone)] |
1a4d82fc | 376 | pub struct AutoDerefRef<'tcx> { |
9346a6ac | 377 | /// Step 1. Apply a number of dereferences, producing an lvalue. |
c34b1796 | 378 | pub autoderefs: usize, |
223e47cc | 379 | |
9346a6ac AL |
380 | /// Step 2. Optionally produce a pointer/reference from the value. |
381 | pub autoref: Option<AutoRef<'tcx>>, | |
1a4d82fc | 382 | |
9346a6ac AL |
383 | /// Step 3. Unsize a pointer/reference value, e.g. `&[T; n]` to |
384 | /// `&[T]`. The stored type is the target pointer type. Note that | |
385 | /// the source could be a thin or fat pointer. | |
386 | pub unsize: Option<Ty<'tcx>>, | |
223e47cc LB |
387 | } |
388 | ||
9346a6ac AL |
389 | #[derive(Copy, Clone, PartialEq, Debug)] |
390 | pub enum AutoRef<'tcx> { | |
391 | /// Convert from T to &T. | |
392 | AutoPtr(&'tcx Region, ast::Mutability), | |
223e47cc | 393 | |
9346a6ac AL |
394 | /// Convert from T to *T. |
395 | /// Value to thin pointer. | |
396 | AutoUnsafe(ast::Mutability), | |
223e47cc LB |
397 | } |
398 | ||
d9579d0f AL |
399 | #[derive(Clone, Copy, RustcEncodable, RustcDecodable, Debug)] |
400 | pub enum CustomCoerceUnsized { | |
401 | /// Records the index of the field being coerced. | |
402 | Struct(usize) | |
403 | } | |
404 | ||
62682a34 | 405 | #[derive(Clone)] |
1a4d82fc JJ |
406 | pub enum MethodOrigin<'tcx> { |
407 | // fully statically resolved method | |
408 | MethodStatic(ast::DefId), | |
223e47cc | 409 | |
85aaf69f SL |
410 | // fully statically resolved closure invocation |
411 | MethodStaticClosure(ast::DefId), | |
223e47cc | 412 | |
1a4d82fc JJ |
413 | // method invoked on a type parameter with a bounded trait |
414 | MethodTypeParam(MethodParam<'tcx>), | |
223e47cc | 415 | |
1a4d82fc JJ |
416 | // method invoked on a trait instance |
417 | MethodTraitObject(MethodObject<'tcx>), | |
970d7e83 | 418 | |
223e47cc LB |
419 | } |
420 | ||
1a4d82fc JJ |
421 | // details for a method invoked with a receiver whose type is a type parameter |
422 | // with a bounded trait. | |
62682a34 | 423 | #[derive(Clone)] |
1a4d82fc JJ |
424 | pub struct MethodParam<'tcx> { |
425 | // the precise trait reference that occurs as a bound -- this may | |
426 | // be a supertrait of what the user actually typed. Note that it | |
427 | // never contains bound regions; those regions should have been | |
428 | // instantiated with fresh variables at this point. | |
d9579d0f | 429 | pub trait_ref: ty::TraitRef<'tcx>, |
1a4d82fc | 430 | |
c34b1796 | 431 | // index of usize in the list of trait items. Note that this is NOT |
85aaf69f SL |
432 | // the index into the vtable, because the list of trait items |
433 | // includes associated types. | |
c34b1796 | 434 | pub method_num: usize, |
85aaf69f SL |
435 | |
436 | /// The impl for the trait from which the method comes. This | |
437 | /// should only be used for certain linting/heuristic purposes | |
438 | /// since there is no guarantee that this is Some in every | |
439 | /// situation that it could/should be. | |
440 | pub impl_def_id: Option<ast::DefId>, | |
1a4d82fc JJ |
441 | } |
442 | ||
443 | // details for a method invoked with a receiver whose type is an object | |
62682a34 | 444 | #[derive(Clone)] |
1a4d82fc JJ |
445 | pub struct MethodObject<'tcx> { |
446 | // the (super)trait containing the method to be invoked | |
d9579d0f | 447 | pub trait_ref: TraitRef<'tcx>, |
223e47cc | 448 | |
1a4d82fc JJ |
449 | // the actual base trait id of the object |
450 | pub object_trait_id: ast::DefId, | |
223e47cc | 451 | |
85aaf69f | 452 | // index of the method to be invoked amongst the trait's items |
c34b1796 | 453 | pub method_num: usize, |
1a4d82fc JJ |
454 | |
455 | // index into the actual runtime vtable. | |
456 | // the vtable is formed by concatenating together the method lists of | |
85aaf69f | 457 | // the base object trait and all supertraits; this is the index into |
1a4d82fc | 458 | // that vtable |
c34b1796 | 459 | pub vtable_index: usize, |
223e47cc | 460 | } |
1a4d82fc | 461 | |
d9579d0f | 462 | #[derive(Clone, Debug)] |
1a4d82fc JJ |
463 | pub struct MethodCallee<'tcx> { |
464 | pub origin: MethodOrigin<'tcx>, | |
465 | pub ty: Ty<'tcx>, | |
466 | pub substs: subst::Substs<'tcx> | |
223e47cc | 467 | } |
1a4d82fc JJ |
468 | |
469 | /// With method calls, we store some extra information in | |
470 | /// side tables (i.e method_map). We use | |
471 | /// MethodCall as a key to index into these tables instead of | |
472 | /// just directly using the expression's NodeId. The reason | |
473 | /// for this being that we may apply adjustments (coercions) | |
474 | /// with the resulting expression also needing to use the | |
475 | /// side tables. The problem with this is that we don't | |
476 | /// assign a separate NodeId to this new expression | |
477 | /// and so it would clash with the base expression if both | |
478 | /// needed to add to the side tables. Thus to disambiguate | |
479 | /// we also keep track of whether there's an adjustment in | |
480 | /// our key. | |
85aaf69f | 481 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
482 | pub struct MethodCall { |
483 | pub expr_id: ast::NodeId, | |
9346a6ac | 484 | pub autoderef: u32 |
223e47cc LB |
485 | } |
486 | ||
1a4d82fc JJ |
487 | impl MethodCall { |
488 | pub fn expr(id: ast::NodeId) -> MethodCall { | |
489 | MethodCall { | |
490 | expr_id: id, | |
9346a6ac | 491 | autoderef: 0 |
1a4d82fc JJ |
492 | } |
493 | } | |
494 | ||
9346a6ac | 495 | pub fn autoderef(expr_id: ast::NodeId, autoderef: u32) -> MethodCall { |
1a4d82fc JJ |
496 | MethodCall { |
497 | expr_id: expr_id, | |
9346a6ac | 498 | autoderef: 1 + autoderef |
1a4d82fc JJ |
499 | } |
500 | } | |
223e47cc LB |
501 | } |
502 | ||
1a4d82fc JJ |
503 | // maps from an expression id that corresponds to a method call to the details |
504 | // of the method to be invoked | |
505 | pub type MethodMap<'tcx> = RefCell<FnvHashMap<MethodCall, MethodCallee<'tcx>>>; | |
223e47cc | 506 | |
62682a34 SL |
507 | // Contains information needed to resolve types and (in the future) look up |
508 | // the types of AST nodes. | |
509 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
510 | pub struct creader_cache_key { | |
511 | pub cnum: CrateNum, | |
512 | pub pos: usize, | |
513 | pub len: usize | |
970d7e83 LB |
514 | } |
515 | ||
1a4d82fc JJ |
516 | /// A restriction that certain types must be the same size. The use of |
517 | /// `transmute` gives rise to these restrictions. These generally | |
518 | /// cannot be checked until trans; therefore, each call to `transmute` | |
519 | /// will push one or more such restriction into the | |
520 | /// `transmute_restrictions` vector during `intrinsicck`. They are | |
521 | /// then checked during `trans` by the fn `check_intrinsics`. | |
c34b1796 | 522 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
523 | pub struct TransmuteRestriction<'tcx> { |
524 | /// The span whence the restriction comes. | |
525 | pub span: Span, | |
970d7e83 | 526 | |
1a4d82fc JJ |
527 | /// The type being transmuted from. |
528 | pub original_from: Ty<'tcx>, | |
970d7e83 | 529 | |
1a4d82fc JJ |
530 | /// The type being transmuted to. |
531 | pub original_to: Ty<'tcx>, | |
970d7e83 | 532 | |
1a4d82fc JJ |
533 | /// The type being transmuted from, with all type parameters |
534 | /// substituted for an arbitrary representative. Not to be shown | |
535 | /// to the end user. | |
536 | pub substituted_from: Ty<'tcx>, | |
223e47cc | 537 | |
1a4d82fc JJ |
538 | /// The type being transmuted to, with all type parameters |
539 | /// substituted for an arbitrary representative. Not to be shown | |
540 | /// to the end user. | |
541 | pub substituted_to: Ty<'tcx>, | |
223e47cc | 542 | |
1a4d82fc JJ |
543 | /// NodeId of the transmute intrinsic. |
544 | pub id: ast::NodeId, | |
223e47cc LB |
545 | } |
546 | ||
1a4d82fc JJ |
547 | /// Internal storage |
548 | pub struct CtxtArenas<'tcx> { | |
d9579d0f | 549 | // internings |
1a4d82fc JJ |
550 | type_: TypedArena<TyS<'tcx>>, |
551 | substs: TypedArena<Substs<'tcx>>, | |
552 | bare_fn: TypedArena<BareFnTy<'tcx>>, | |
553 | region: TypedArena<Region>, | |
62682a34 | 554 | stability: TypedArena<attr::Stability>, |
d9579d0f AL |
555 | |
556 | // references | |
62682a34 | 557 | trait_defs: TypedArena<TraitDef<'tcx>>, |
970d7e83 LB |
558 | } |
559 | ||
1a4d82fc JJ |
560 | impl<'tcx> CtxtArenas<'tcx> { |
561 | pub fn new() -> CtxtArenas<'tcx> { | |
562 | CtxtArenas { | |
563 | type_: TypedArena::new(), | |
564 | substs: TypedArena::new(), | |
565 | bare_fn: TypedArena::new(), | |
566 | region: TypedArena::new(), | |
62682a34 | 567 | stability: TypedArena::new(), |
d9579d0f AL |
568 | |
569 | trait_defs: TypedArena::new() | |
1a4d82fc JJ |
570 | } |
571 | } | |
223e47cc LB |
572 | } |
573 | ||
1a4d82fc JJ |
574 | pub struct CommonTypes<'tcx> { |
575 | pub bool: Ty<'tcx>, | |
576 | pub char: Ty<'tcx>, | |
c34b1796 | 577 | pub isize: Ty<'tcx>, |
1a4d82fc JJ |
578 | pub i8: Ty<'tcx>, |
579 | pub i16: Ty<'tcx>, | |
580 | pub i32: Ty<'tcx>, | |
581 | pub i64: Ty<'tcx>, | |
c34b1796 | 582 | pub usize: Ty<'tcx>, |
1a4d82fc JJ |
583 | pub u8: Ty<'tcx>, |
584 | pub u16: Ty<'tcx>, | |
585 | pub u32: Ty<'tcx>, | |
586 | pub u64: Ty<'tcx>, | |
587 | pub f32: Ty<'tcx>, | |
588 | pub f64: Ty<'tcx>, | |
589 | pub err: Ty<'tcx>, | |
590 | } | |
591 | ||
592 | /// The data structure to keep track of all the information that typechecker | |
593 | /// generates so that so that it can be reused and doesn't have to be redone | |
594 | /// later on. | |
595 | pub struct ctxt<'tcx> { | |
596 | /// The arenas that types etc are allocated from. | |
597 | arenas: &'tcx CtxtArenas<'tcx>, | |
598 | ||
599 | /// Specifically use a speedy hash algorithm for this hash map, it's used | |
600 | /// quite often. | |
601 | // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can | |
602 | // queried from a HashSet. | |
603 | interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>, | |
604 | ||
605 | // FIXME as above, use a hashset if equivalent elements can be queried. | |
606 | substs_interner: RefCell<FnvHashMap<&'tcx Substs<'tcx>, &'tcx Substs<'tcx>>>, | |
607 | bare_fn_interner: RefCell<FnvHashMap<&'tcx BareFnTy<'tcx>, &'tcx BareFnTy<'tcx>>>, | |
608 | region_interner: RefCell<FnvHashMap<&'tcx Region, &'tcx Region>>, | |
62682a34 | 609 | stability_interner: RefCell<FnvHashMap<&'tcx attr::Stability, &'tcx attr::Stability>>, |
1a4d82fc JJ |
610 | |
611 | /// Common types, pre-interned for your convenience. | |
612 | pub types: CommonTypes<'tcx>, | |
613 | ||
614 | pub sess: Session, | |
615 | pub def_map: DefMap, | |
616 | ||
617 | pub named_region_map: resolve_lifetime::NamedRegionMap, | |
618 | ||
bd371182 AL |
619 | pub region_maps: RegionMaps, |
620 | ||
621 | // For each fn declared in the local crate, type check stores the | |
622 | // free-region relationships that were deduced from its where | |
623 | // clauses and parameter types. These are then read-again by | |
624 | // borrowck. (They are not used during trans, and hence are not | |
625 | // serialized or needed for cross-crate fns.) | |
626 | free_region_maps: RefCell<NodeMap<FreeRegionMap>>, | |
1a4d82fc JJ |
627 | |
628 | /// Stores the types for various nodes in the AST. Note that this table | |
629 | /// is not guaranteed to be populated until after typeck. See | |
630 | /// typeck::check::fn_ctxt for details. | |
c34b1796 | 631 | node_types: RefCell<NodeMap<Ty<'tcx>>>, |
1a4d82fc JJ |
632 | |
633 | /// Stores the type parameters which were substituted to obtain the type | |
634 | /// of this node. This only applies to nodes that refer to entities | |
635 | /// parameterized by type parameters, such as generic fns, types, or | |
636 | /// other items. | |
637 | pub item_substs: RefCell<NodeMap<ItemSubsts<'tcx>>>, | |
638 | ||
639 | /// Maps from a trait item to the trait item "descriptor" | |
640 | pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem<'tcx>>>, | |
641 | ||
642 | /// Maps from a trait def-id to a list of the def-ids of its trait items | |
643 | pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItemId>>>>, | |
644 | ||
645 | /// A cache for the trait_items() routine | |
646 | pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>, | |
647 | ||
62682a34 | 648 | pub impl_trait_refs: RefCell<DefIdMap<Option<TraitRef<'tcx>>>>, |
d9579d0f | 649 | pub trait_defs: RefCell<DefIdMap<&'tcx TraitDef<'tcx>>>, |
1a4d82fc | 650 | |
85aaf69f SL |
651 | /// Maps from the def-id of an item (trait/struct/enum/fn) to its |
652 | /// associated predicates. | |
653 | pub predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>, | |
654 | ||
c34b1796 AL |
655 | /// Maps from the def-id of a trait to the list of |
656 | /// super-predicates. This is a subset of the full list of | |
657 | /// predicates. We store these in a separate map because we must | |
658 | /// evaluate them even during type conversion, often before the | |
659 | /// full predicates are available (note that supertraits have | |
660 | /// additional acyclicity requirements). | |
661 | pub super_predicates: RefCell<DefIdMap<GenericPredicates<'tcx>>>, | |
662 | ||
1a4d82fc | 663 | pub map: ast_map::Map<'tcx>, |
1a4d82fc JJ |
664 | pub freevars: RefCell<FreevarMap>, |
665 | pub tcache: RefCell<DefIdMap<TypeScheme<'tcx>>>, | |
666 | pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>, | |
1a4d82fc | 667 | pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>, |
c34b1796 | 668 | pub ast_ty_to_ty_cache: RefCell<NodeMap<Ty<'tcx>>>, |
1a4d82fc JJ |
669 | pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>, |
670 | pub ty_param_defs: RefCell<NodeMap<TypeParameterDef<'tcx>>>, | |
671 | pub adjustments: RefCell<NodeMap<AutoAdjustment<'tcx>>>, | |
672 | pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>, | |
673 | pub lang_items: middle::lang_items::LanguageItems, | |
674 | /// A mapping of fake provided method def_ids to the default implementation | |
675 | pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>, | |
676 | pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>, | |
677 | ||
678 | /// Maps from def-id of a type or region parameter to its | |
679 | /// (inferred) variance. | |
680 | pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>, | |
681 | ||
682 | /// True if the variance has been computed yet; false otherwise. | |
683 | pub variance_computed: Cell<bool>, | |
684 | ||
685 | /// A mapping from the def ID of an enum or struct type to the def ID | |
686 | /// of the method that implements its destructor. If the type is not | |
687 | /// present in this map, it does not have a destructor. This map is | |
688 | /// populated during the coherence phase of typechecking. | |
689 | pub destructor_for_type: RefCell<DefIdMap<ast::DefId>>, | |
690 | ||
691 | /// A method will be in this list if and only if it is a destructor. | |
692 | pub destructors: RefCell<DefIdSet>, | |
693 | ||
1a4d82fc JJ |
694 | /// Maps a DefId of a type to a list of its inherent impls. |
695 | /// Contains implementations of methods that are inherent to a type. | |
696 | /// Methods in these implementations don't need to be exported. | |
697 | pub inherent_impls: RefCell<DefIdMap<Rc<Vec<ast::DefId>>>>, | |
698 | ||
699 | /// Maps a DefId of an impl to a list of its items. | |
700 | /// Note that this contains all of the impls that we know about, | |
701 | /// including ones in other crates. It's not clear that this is the best | |
702 | /// way to do it. | |
703 | pub impl_items: RefCell<DefIdMap<Vec<ImplOrTraitItemId>>>, | |
704 | ||
705 | /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not | |
706 | /// present in this set can be warned about. | |
707 | pub used_unsafe: RefCell<NodeSet>, | |
708 | ||
709 | /// Set of nodes which mark locals as mutable which end up getting used at | |
710 | /// some point. Local variable definitions not in this set can be warned | |
711 | /// about. | |
712 | pub used_mut_nodes: RefCell<NodeSet>, | |
713 | ||
714 | /// The set of external nominal types whose implementations have been read. | |
715 | /// This is used for lazy resolution of methods. | |
716 | pub populated_external_types: RefCell<DefIdSet>, | |
d9579d0f AL |
717 | /// The set of external primitive types whose implementations have been read. |
718 | /// FIXME(arielb1): why is this separate from populated_external_types? | |
c34b1796 AL |
719 | pub populated_external_primitive_impls: RefCell<DefIdSet>, |
720 | ||
1a4d82fc | 721 | /// Borrows |
85aaf69f | 722 | pub upvar_capture_map: RefCell<UpvarCaptureMap>, |
1a4d82fc | 723 | |
62682a34 | 724 | /// These caches are used by const_eval when decoding external constants. |
1a4d82fc JJ |
725 | pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>, |
726 | pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>, | |
62682a34 | 727 | pub extern_const_fns: RefCell<DefIdMap<ast::NodeId>>, |
1a4d82fc JJ |
728 | |
729 | pub method_map: MethodMap<'tcx>, | |
730 | ||
731 | pub dependency_formats: RefCell<dependency_format::Dependencies>, | |
732 | ||
85aaf69f SL |
733 | /// Records the type of each closure. The def ID is the ID of the |
734 | /// expression defining the closure. | |
735 | pub closure_kinds: RefCell<DefIdMap<ClosureKind>>, | |
736 | ||
737 | /// Records the type of each closure. The def ID is the ID of the | |
738 | /// expression defining the closure. | |
739 | pub closure_tys: RefCell<DefIdMap<ClosureTy<'tcx>>>, | |
1a4d82fc JJ |
740 | |
741 | pub node_lint_levels: RefCell<FnvHashMap<(ast::NodeId, lint::LintId), | |
742 | lint::LevelSource>>, | |
743 | ||
744 | /// The types that must be asserted to be the same size for `transmute` | |
745 | /// to be valid. We gather up these restrictions in the intrinsicck pass | |
746 | /// and check them in trans. | |
747 | pub transmute_restrictions: RefCell<Vec<TransmuteRestriction<'tcx>>>, | |
748 | ||
749 | /// Maps any item's def-id to its stability index. | |
62682a34 | 750 | pub stability: RefCell<stability::Index<'tcx>>, |
1a4d82fc JJ |
751 | |
752 | /// Caches the results of trait selection. This cache is used | |
753 | /// for things that do not have to do with the parameters in scope. | |
754 | pub selection_cache: traits::SelectionCache<'tcx>, | |
755 | ||
62682a34 SL |
756 | /// A set of predicates that have been fulfilled *somewhere*. |
757 | /// This is used to avoid duplicate work. Predicates are only | |
758 | /// added to this set when they mention only "global" names | |
759 | /// (i.e., no type or lifetime parameters). | |
760 | pub fulfilled_predicates: RefCell<traits::FulfilledPredicates<'tcx>>, | |
761 | ||
1a4d82fc JJ |
762 | /// Caches the representation hints for struct definitions. |
763 | pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>, | |
764 | ||
85aaf69f SL |
765 | /// Maps Expr NodeId's to their constant qualification. |
766 | pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>, | |
d9579d0f AL |
767 | |
768 | /// Caches CoerceUnsized kinds for impls on custom types. | |
769 | pub custom_coerce_unsized_kinds: RefCell<DefIdMap<CustomCoerceUnsized>>, | |
62682a34 SL |
770 | |
771 | /// Maps a cast expression to its kind. This is keyed on the | |
772 | /// *from* expression of the cast, not the cast itself. | |
773 | pub cast_kinds: RefCell<NodeMap<cast::CastKind>>, | |
1a4d82fc JJ |
774 | } |
775 | ||
c34b1796 AL |
776 | impl<'tcx> ctxt<'tcx> { |
777 | pub fn node_types(&self) -> Ref<NodeMap<Ty<'tcx>>> { self.node_types.borrow() } | |
778 | pub fn node_type_insert(&self, id: NodeId, ty: Ty<'tcx>) { | |
779 | self.node_types.borrow_mut().insert(id, ty); | |
780 | } | |
bd371182 | 781 | |
d9579d0f AL |
782 | pub fn intern_trait_def(&self, def: TraitDef<'tcx>) -> &'tcx TraitDef<'tcx> { |
783 | let did = def.trait_ref.def_id; | |
784 | let interned = self.arenas.trait_defs.alloc(def); | |
785 | self.trait_defs.borrow_mut().insert(did, interned); | |
786 | interned | |
787 | } | |
788 | ||
62682a34 SL |
789 | pub fn intern_stability(&self, stab: attr::Stability) -> &'tcx attr::Stability { |
790 | if let Some(st) = self.stability_interner.borrow().get(&stab) { | |
791 | return st; | |
792 | } | |
793 | ||
794 | let interned = self.arenas.stability.alloc(stab); | |
795 | self.stability_interner.borrow_mut().insert(interned, interned); | |
796 | interned | |
797 | } | |
798 | ||
bd371182 AL |
799 | pub fn store_free_region_map(&self, id: NodeId, map: FreeRegionMap) { |
800 | self.free_region_maps.borrow_mut() | |
801 | .insert(id, map); | |
802 | } | |
803 | ||
804 | pub fn free_region_map(&self, id: NodeId) -> FreeRegionMap { | |
805 | self.free_region_maps.borrow()[&id].clone() | |
806 | } | |
62682a34 SL |
807 | |
808 | pub fn lift<T: ?Sized + Lift<'tcx>>(&self, value: &T) -> Option<T::Lifted> { | |
809 | value.lift_to_tcx(self) | |
810 | } | |
811 | } | |
812 | ||
813 | /// A trait implemented for all X<'a> types which can be safely and | |
814 | /// efficiently converted to X<'tcx> as long as they are part of the | |
815 | /// provided ty::ctxt<'tcx>. | |
816 | /// This can be done, for example, for Ty<'tcx> or &'tcx Substs<'tcx> | |
817 | /// by looking them up in their respective interners. | |
818 | /// None is returned if the value or one of the components is not part | |
819 | /// of the provided context. | |
820 | /// For Ty, None can be returned if either the type interner doesn't | |
821 | /// contain the TypeVariants key or if the address of the interned | |
822 | /// pointer differs. The latter case is possible if a primitive type, | |
823 | /// e.g. `()` or `u8`, was interned in a different context. | |
824 | pub trait Lift<'tcx> { | |
825 | type Lifted; | |
826 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted>; | |
827 | } | |
828 | ||
829 | impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) { | |
830 | type Lifted = (A::Lifted, B::Lifted); | |
831 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> { | |
832 | tcx.lift(&self.0).and_then(|a| tcx.lift(&self.1).map(|b| (a, b))) | |
833 | } | |
834 | } | |
835 | ||
836 | impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] { | |
837 | type Lifted = Vec<T::Lifted>; | |
838 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> { | |
839 | let mut result = Vec::with_capacity(self.len()); | |
840 | for x in self { | |
841 | if let Some(value) = tcx.lift(x) { | |
842 | result.push(value); | |
843 | } else { | |
844 | return None; | |
845 | } | |
846 | } | |
847 | Some(result) | |
848 | } | |
849 | } | |
850 | ||
851 | impl<'tcx> Lift<'tcx> for Region { | |
852 | type Lifted = Self; | |
853 | fn lift_to_tcx(&self, _: &ctxt<'tcx>) -> Option<Region> { | |
854 | Some(*self) | |
855 | } | |
856 | } | |
857 | ||
858 | impl<'a, 'tcx> Lift<'tcx> for Ty<'a> { | |
859 | type Lifted = Ty<'tcx>; | |
860 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Ty<'tcx>> { | |
861 | if let Some(&ty) = tcx.interner.borrow().get(&self.sty) { | |
862 | if *self as *const _ == ty as *const _ { | |
863 | return Some(ty); | |
864 | } | |
865 | } | |
866 | None | |
867 | } | |
868 | } | |
869 | ||
870 | impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> { | |
871 | type Lifted = &'tcx Substs<'tcx>; | |
872 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<&'tcx Substs<'tcx>> { | |
873 | if let Some(&substs) = tcx.substs_interner.borrow().get(*self) { | |
874 | if *self as *const _ == substs as *const _ { | |
875 | return Some(substs); | |
876 | } | |
877 | } | |
878 | None | |
879 | } | |
880 | } | |
881 | ||
882 | impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> { | |
883 | type Lifted = TraitRef<'tcx>; | |
884 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<TraitRef<'tcx>> { | |
885 | tcx.lift(&self.substs).map(|substs| TraitRef { | |
886 | def_id: self.def_id, | |
887 | substs: substs | |
888 | }) | |
889 | } | |
890 | } | |
891 | ||
892 | impl<'a, 'tcx> Lift<'tcx> for TraitPredicate<'a> { | |
893 | type Lifted = TraitPredicate<'tcx>; | |
894 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<TraitPredicate<'tcx>> { | |
895 | tcx.lift(&self.trait_ref).map(|trait_ref| TraitPredicate { | |
896 | trait_ref: trait_ref | |
897 | }) | |
898 | } | |
899 | } | |
900 | ||
901 | impl<'a, 'tcx> Lift<'tcx> for EquatePredicate<'a> { | |
902 | type Lifted = EquatePredicate<'tcx>; | |
903 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<EquatePredicate<'tcx>> { | |
904 | tcx.lift(&(self.0, self.1)).map(|(a, b)| EquatePredicate(a, b)) | |
905 | } | |
906 | } | |
907 | ||
908 | impl<'tcx, A: Copy+Lift<'tcx>, B: Copy+Lift<'tcx>> Lift<'tcx> for OutlivesPredicate<A, B> { | |
909 | type Lifted = OutlivesPredicate<A::Lifted, B::Lifted>; | |
910 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> { | |
911 | tcx.lift(&(self.0, self.1)).map(|(a, b)| OutlivesPredicate(a, b)) | |
912 | } | |
913 | } | |
914 | ||
915 | impl<'a, 'tcx> Lift<'tcx> for ProjectionPredicate<'a> { | |
916 | type Lifted = ProjectionPredicate<'tcx>; | |
917 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<ProjectionPredicate<'tcx>> { | |
918 | tcx.lift(&(self.projection_ty.trait_ref, self.ty)).map(|(trait_ref, ty)| { | |
919 | ProjectionPredicate { | |
920 | projection_ty: ProjectionTy { | |
921 | trait_ref: trait_ref, | |
922 | item_name: self.projection_ty.item_name | |
923 | }, | |
924 | ty: ty | |
925 | } | |
926 | }) | |
927 | } | |
928 | } | |
929 | ||
930 | impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Binder<T> { | |
931 | type Lifted = Binder<T::Lifted>; | |
932 | fn lift_to_tcx(&self, tcx: &ctxt<'tcx>) -> Option<Self::Lifted> { | |
933 | tcx.lift(&self.0).map(|x| Binder(x)) | |
934 | } | |
935 | } | |
936 | ||
937 | pub mod tls { | |
938 | use ast_map; | |
939 | use middle::ty; | |
940 | use session::Session; | |
941 | ||
942 | use std::fmt; | |
943 | use syntax::ast; | |
944 | use syntax::codemap; | |
945 | ||
946 | /// Marker type used for the scoped TLS slot. | |
947 | /// The type context cannot be used directly because the scoped TLS | |
948 | /// in libstd doesn't allow types generic over lifetimes. | |
949 | struct ThreadLocalTyCx; | |
950 | ||
951 | scoped_thread_local!(static TLS_TCX: ThreadLocalTyCx); | |
952 | ||
953 | fn def_id_debug(def_id: ast::DefId, f: &mut fmt::Formatter) -> fmt::Result { | |
954 | // Unfortunately, there seems to be no way to attempt to print | |
955 | // a path for a def-id, so I'll just make a best effort for now | |
956 | // and otherwise fallback to just printing the crate/node pair | |
957 | with(|tcx| { | |
958 | if def_id.krate == ast::LOCAL_CRATE { | |
959 | match tcx.map.find(def_id.node) { | |
960 | Some(ast_map::NodeItem(..)) | | |
961 | Some(ast_map::NodeForeignItem(..)) | | |
962 | Some(ast_map::NodeImplItem(..)) | | |
963 | Some(ast_map::NodeTraitItem(..)) | | |
964 | Some(ast_map::NodeVariant(..)) | | |
965 | Some(ast_map::NodeStructCtor(..)) => { | |
966 | return write!(f, "{}", ty::item_path_str(tcx, def_id)); | |
967 | } | |
968 | _ => {} | |
969 | } | |
970 | } | |
971 | Ok(()) | |
972 | }) | |
973 | } | |
974 | ||
975 | fn span_debug(span: codemap::Span, f: &mut fmt::Formatter) -> fmt::Result { | |
976 | with(|tcx| { | |
977 | write!(f, "{}", tcx.sess.codemap().span_to_string(span)) | |
978 | }) | |
979 | } | |
980 | ||
981 | pub fn enter<'tcx, F: FnOnce(&ty::ctxt<'tcx>) -> R, R>(tcx: ty::ctxt<'tcx>, f: F) | |
982 | -> (Session, R) { | |
983 | let result = ast::DEF_ID_DEBUG.with(|def_id_dbg| { | |
984 | codemap::SPAN_DEBUG.with(|span_dbg| { | |
985 | let original_def_id_debug = def_id_dbg.get(); | |
986 | def_id_dbg.set(def_id_debug); | |
987 | let original_span_debug = span_dbg.get(); | |
988 | span_dbg.set(span_debug); | |
989 | let tls_ptr = &tcx as *const _ as *const ThreadLocalTyCx; | |
990 | let result = TLS_TCX.set(unsafe { &*tls_ptr }, || f(&tcx)); | |
991 | def_id_dbg.set(original_def_id_debug); | |
992 | span_dbg.set(original_span_debug); | |
993 | result | |
994 | }) | |
995 | }); | |
996 | (tcx.sess, result) | |
997 | } | |
998 | ||
999 | pub fn with<F: FnOnce(&ty::ctxt) -> R, R>(f: F) -> R { | |
1000 | TLS_TCX.with(|tcx| f(unsafe { &*(tcx as *const _ as *const ty::ctxt) })) | |
1001 | } | |
c34b1796 AL |
1002 | } |
1003 | ||
1a4d82fc JJ |
1004 | // Flags that we track on types. These flags are propagated upwards |
1005 | // through the type during type construction, so that we can quickly | |
1006 | // check whether the type has various kinds of types in it without | |
1007 | // recursing over the type itself. | |
1008 | bitflags! { | |
1009 | flags TypeFlags: u32 { | |
62682a34 SL |
1010 | const HAS_PARAMS = 1 << 0, |
1011 | const HAS_SELF = 1 << 1, | |
1012 | const HAS_TY_INFER = 1 << 2, | |
1013 | const HAS_RE_INFER = 1 << 3, | |
1014 | const HAS_RE_EARLY_BOUND = 1 << 4, | |
1015 | const HAS_FREE_REGIONS = 1 << 5, | |
1016 | const HAS_TY_ERR = 1 << 6, | |
1017 | const HAS_PROJECTION = 1 << 7, | |
1018 | const HAS_TY_CLOSURE = 1 << 8, | |
1019 | ||
1020 | // true if there are "names" of types and regions and so forth | |
1021 | // that are local to a particular fn | |
1022 | const HAS_LOCAL_NAMES = 1 << 9, | |
1023 | ||
1024 | const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | | |
1025 | TypeFlags::HAS_SELF.bits | | |
1026 | TypeFlags::HAS_RE_EARLY_BOUND.bits, | |
1027 | ||
1028 | // Flags representing the nominal content of a type, | |
1029 | // computed by FlagsComputation. If you add a new nominal | |
1030 | // flag, it should be added here too. | |
1031 | const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits | | |
d9579d0f | 1032 | TypeFlags::HAS_SELF.bits | |
62682a34 SL |
1033 | TypeFlags::HAS_TY_INFER.bits | |
1034 | TypeFlags::HAS_RE_INFER.bits | | |
1035 | TypeFlags::HAS_RE_EARLY_BOUND.bits | | |
1036 | TypeFlags::HAS_FREE_REGIONS.bits | | |
1037 | TypeFlags::HAS_TY_ERR.bits | | |
1038 | TypeFlags::HAS_PROJECTION.bits | | |
1039 | TypeFlags::HAS_TY_CLOSURE.bits | | |
1040 | TypeFlags::HAS_LOCAL_NAMES.bits, | |
1041 | ||
1042 | // Caches for type_is_sized, type_moves_by_default | |
1043 | const SIZEDNESS_CACHED = 1 << 16, | |
1044 | const IS_SIZED = 1 << 17, | |
1045 | const MOVENESS_CACHED = 1 << 18, | |
1046 | const MOVES_BY_DEFAULT = 1 << 19, | |
1a4d82fc JJ |
1047 | } |
1048 | } | |
1049 | ||
1050 | macro_rules! sty_debug_print { | |
1051 | ($ctxt: expr, $($variant: ident),*) => {{ | |
1052 | // curious inner module to allow variant names to be used as | |
1053 | // variable names. | |
62682a34 | 1054 | #[allow(non_snake_case)] |
1a4d82fc JJ |
1055 | mod inner { |
1056 | use middle::ty; | |
c34b1796 | 1057 | #[derive(Copy, Clone)] |
1a4d82fc | 1058 | struct DebugStat { |
c34b1796 AL |
1059 | total: usize, |
1060 | region_infer: usize, | |
1061 | ty_infer: usize, | |
1062 | both_infer: usize, | |
1a4d82fc | 1063 | } |
223e47cc | 1064 | |
1a4d82fc JJ |
1065 | pub fn go(tcx: &ty::ctxt) { |
1066 | let mut total = DebugStat { | |
1067 | total: 0, | |
1068 | region_infer: 0, ty_infer: 0, both_infer: 0, | |
1069 | }; | |
1070 | $(let mut $variant = total;)* | |
1071 | ||
1072 | ||
62682a34 | 1073 | for (_, t) in tcx.interner.borrow().iter() { |
1a4d82fc | 1074 | let variant = match t.sty { |
62682a34 SL |
1075 | ty::TyBool | ty::TyChar | ty::TyInt(..) | ty::TyUint(..) | |
1076 | ty::TyFloat(..) | ty::TyStr => continue, | |
1077 | ty::TyError => /* unimportant */ continue, | |
1a4d82fc JJ |
1078 | $(ty::$variant(..) => &mut $variant,)* |
1079 | }; | |
62682a34 SL |
1080 | let region = t.flags.get().intersects(ty::TypeFlags::HAS_RE_INFER); |
1081 | let ty = t.flags.get().intersects(ty::TypeFlags::HAS_TY_INFER); | |
1a4d82fc JJ |
1082 | |
1083 | variant.total += 1; | |
1084 | total.total += 1; | |
1085 | if region { total.region_infer += 1; variant.region_infer += 1 } | |
1086 | if ty { total.ty_infer += 1; variant.ty_infer += 1 } | |
1087 | if region && ty { total.both_infer += 1; variant.both_infer += 1 } | |
1088 | } | |
1089 | println!("Ty interner total ty region both"); | |
1090 | $(println!(" {:18}: {uses:6} {usespc:4.1}%, \ | |
1091 | {ty:4.1}% {region:5.1}% {both:4.1}%", | |
1092 | stringify!($variant), | |
1093 | uses = $variant.total, | |
1094 | usespc = $variant.total as f64 * 100.0 / total.total as f64, | |
1095 | ty = $variant.ty_infer as f64 * 100.0 / total.total as f64, | |
1096 | region = $variant.region_infer as f64 * 100.0 / total.total as f64, | |
1097 | both = $variant.both_infer as f64 * 100.0 / total.total as f64); | |
1098 | )* | |
1099 | println!(" total {uses:6} \ | |
1100 | {ty:4.1}% {region:5.1}% {both:4.1}%", | |
1101 | uses = total.total, | |
1102 | ty = total.ty_infer as f64 * 100.0 / total.total as f64, | |
1103 | region = total.region_infer as f64 * 100.0 / total.total as f64, | |
1104 | both = total.both_infer as f64 * 100.0 / total.total as f64) | |
1105 | } | |
1106 | } | |
223e47cc | 1107 | |
1a4d82fc JJ |
1108 | inner::go($ctxt) |
1109 | }} | |
223e47cc LB |
1110 | } |
1111 | ||
1a4d82fc JJ |
1112 | impl<'tcx> ctxt<'tcx> { |
1113 | pub fn print_debug_stats(&self) { | |
1114 | sty_debug_print!( | |
1115 | self, | |
62682a34 SL |
1116 | TyEnum, TyBox, TyArray, TySlice, TyRawPtr, TyRef, TyBareFn, TyTrait, |
1117 | TyStruct, TyClosure, TyTuple, TyParam, TyInfer, TyProjection); | |
1a4d82fc JJ |
1118 | |
1119 | println!("Substs interner: #{}", self.substs_interner.borrow().len()); | |
1120 | println!("BareFnTy interner: #{}", self.bare_fn_interner.borrow().len()); | |
1121 | println!("Region interner: #{}", self.region_interner.borrow().len()); | |
62682a34 | 1122 | println!("Stability interner: #{}", self.stability_interner.borrow().len()); |
1a4d82fc | 1123 | } |
223e47cc LB |
1124 | } |
1125 | ||
1a4d82fc | 1126 | pub struct TyS<'tcx> { |
62682a34 SL |
1127 | pub sty: TypeVariants<'tcx>, |
1128 | pub flags: Cell<TypeFlags>, | |
970d7e83 | 1129 | |
1a4d82fc JJ |
1130 | // the maximal depth of any bound regions appearing in this type. |
1131 | region_depth: u32, | |
970d7e83 LB |
1132 | } |
1133 | ||
85aaf69f | 1134 | impl fmt::Debug for TypeFlags { |
1a4d82fc JJ |
1135 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1136 | write!(f, "{}", self.bits) | |
1137 | } | |
970d7e83 LB |
1138 | } |
1139 | ||
1a4d82fc | 1140 | impl<'tcx> PartialEq for TyS<'tcx> { |
d9579d0f | 1141 | #[inline] |
1a4d82fc | 1142 | fn eq(&self, other: &TyS<'tcx>) -> bool { |
85aaf69f SL |
1143 | // (self as *const _) == (other as *const _) |
1144 | (self as *const TyS<'tcx>) == (other as *const TyS<'tcx>) | |
1a4d82fc | 1145 | } |
970d7e83 | 1146 | } |
1a4d82fc | 1147 | impl<'tcx> Eq for TyS<'tcx> {} |
970d7e83 | 1148 | |
85aaf69f SL |
1149 | impl<'tcx> Hash for TyS<'tcx> { |
1150 | fn hash<H: Hasher>(&self, s: &mut H) { | |
c34b1796 | 1151 | (self as *const TyS).hash(s) |
970d7e83 LB |
1152 | } |
1153 | } | |
1154 | ||
1a4d82fc | 1155 | pub type Ty<'tcx> = &'tcx TyS<'tcx>; |
223e47cc | 1156 | |
1a4d82fc JJ |
1157 | /// An entry in the type interner. |
1158 | pub struct InternedTy<'tcx> { | |
1159 | ty: Ty<'tcx> | |
223e47cc LB |
1160 | } |
1161 | ||
1a4d82fc JJ |
1162 | // NB: An InternedTy compares and hashes as a sty. |
1163 | impl<'tcx> PartialEq for InternedTy<'tcx> { | |
1164 | fn eq(&self, other: &InternedTy<'tcx>) -> bool { | |
1165 | self.ty.sty == other.ty.sty | |
1166 | } | |
223e47cc LB |
1167 | } |
1168 | ||
1a4d82fc | 1169 | impl<'tcx> Eq for InternedTy<'tcx> {} |
223e47cc | 1170 | |
85aaf69f SL |
1171 | impl<'tcx> Hash for InternedTy<'tcx> { |
1172 | fn hash<H: Hasher>(&self, s: &mut H) { | |
1173 | self.ty.sty.hash(s) | |
1174 | } | |
1175 | } | |
223e47cc | 1176 | |
62682a34 SL |
1177 | impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> { |
1178 | fn borrow<'a>(&'a self) -> &'a TypeVariants<'tcx> { | |
85aaf69f | 1179 | &self.ty.sty |
1a4d82fc | 1180 | } |
223e47cc LB |
1181 | } |
1182 | ||
1a4d82fc | 1183 | pub fn type_has_params(ty: Ty) -> bool { |
62682a34 | 1184 | ty.flags.get().intersects(TypeFlags::HAS_PARAMS) |
223e47cc | 1185 | } |
1a4d82fc | 1186 | pub fn type_has_self(ty: Ty) -> bool { |
62682a34 | 1187 | ty.flags.get().intersects(TypeFlags::HAS_SELF) |
1a4d82fc JJ |
1188 | } |
1189 | pub fn type_has_ty_infer(ty: Ty) -> bool { | |
62682a34 | 1190 | ty.flags.get().intersects(TypeFlags::HAS_TY_INFER) |
1a4d82fc JJ |
1191 | } |
1192 | pub fn type_needs_infer(ty: Ty) -> bool { | |
62682a34 SL |
1193 | ty.flags.get().intersects(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER) |
1194 | } | |
1195 | pub fn type_is_global(ty: Ty) -> bool { | |
1196 | !ty.flags.get().intersects(TypeFlags::HAS_LOCAL_NAMES) | |
1a4d82fc JJ |
1197 | } |
1198 | pub fn type_has_projection(ty: Ty) -> bool { | |
62682a34 SL |
1199 | ty.flags.get().intersects(TypeFlags::HAS_PROJECTION) |
1200 | } | |
1201 | pub fn type_has_ty_closure(ty: Ty) -> bool { | |
1202 | ty.flags.get().intersects(TypeFlags::HAS_TY_CLOSURE) | |
223e47cc LB |
1203 | } |
1204 | ||
62682a34 SL |
1205 | pub fn type_has_erasable_regions(ty: Ty) -> bool { |
1206 | ty.flags.get().intersects(TypeFlags::HAS_RE_EARLY_BOUND | | |
1207 | TypeFlags::HAS_RE_INFER | | |
1208 | TypeFlags::HAS_FREE_REGIONS) | |
223e47cc LB |
1209 | } |
1210 | ||
1a4d82fc JJ |
1211 | /// An "escaping region" is a bound region whose binder is not part of `t`. |
1212 | /// | |
1213 | /// So, for example, consider a type like the following, which has two binders: | |
1214 | /// | |
c34b1796 | 1215 | /// for<'a> fn(x: for<'b> fn(&'a isize, &'b isize)) |
1a4d82fc JJ |
1216 | /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope |
1217 | /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope | |
1218 | /// | |
1219 | /// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the | |
1220 | /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner | |
1221 | /// fn type*, that type has an escaping region: `'a`. | |
1222 | /// | |
1223 | /// Note that what I'm calling an "escaping region" is often just called a "free region". However, | |
1224 | /// we already use the term "free region". It refers to the regions that we use to represent bound | |
1225 | /// regions on a fn definition while we are typechecking its body. | |
1226 | /// | |
1227 | /// To clarify, conceptually there is no particular difference between an "escaping" region and a | |
1228 | /// "free" region. However, there is a big difference in practice. Basically, when "entering" a | |
1229 | /// binding level, one is generally required to do some sort of processing to a bound region, such | |
1230 | /// as replacing it with a fresh/skolemized region, or making an entry in the environment to | |
1231 | /// represent the scope to which it is attached, etc. An escaping region represents a bound region | |
1232 | /// for which this processing has not yet been done. | |
1233 | pub fn type_has_escaping_regions(ty: Ty) -> bool { | |
1234 | type_escapes_depth(ty, 0) | |
223e47cc LB |
1235 | } |
1236 | ||
1a4d82fc JJ |
1237 | pub fn type_escapes_depth(ty: Ty, depth: u32) -> bool { |
1238 | ty.region_depth > depth | |
223e47cc LB |
1239 | } |
1240 | ||
85aaf69f | 1241 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
1242 | pub struct BareFnTy<'tcx> { |
1243 | pub unsafety: ast::Unsafety, | |
1244 | pub abi: abi::Abi, | |
1245 | pub sig: PolyFnSig<'tcx>, | |
223e47cc LB |
1246 | } |
1247 | ||
62682a34 | 1248 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
1249 | pub struct ClosureTy<'tcx> { |
1250 | pub unsafety: ast::Unsafety, | |
1a4d82fc | 1251 | pub abi: abi::Abi, |
85aaf69f | 1252 | pub sig: PolyFnSig<'tcx>, |
223e47cc LB |
1253 | } |
1254 | ||
85aaf69f | 1255 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
1256 | pub enum FnOutput<'tcx> { |
1257 | FnConverging(Ty<'tcx>), | |
1258 | FnDiverging | |
223e47cc LB |
1259 | } |
1260 | ||
1a4d82fc JJ |
1261 | impl<'tcx> FnOutput<'tcx> { |
1262 | pub fn diverges(&self) -> bool { | |
1263 | *self == FnDiverging | |
223e47cc | 1264 | } |
223e47cc | 1265 | |
1a4d82fc JJ |
1266 | pub fn unwrap(self) -> Ty<'tcx> { |
1267 | match self { | |
1268 | ty::FnConverging(t) => t, | |
1269 | ty::FnDiverging => unreachable!() | |
223e47cc LB |
1270 | } |
1271 | } | |
9346a6ac AL |
1272 | |
1273 | pub fn unwrap_or(self, def: Ty<'tcx>) -> Ty<'tcx> { | |
1274 | match self { | |
1275 | ty::FnConverging(t) => t, | |
1276 | ty::FnDiverging => def | |
1277 | } | |
1278 | } | |
223e47cc LB |
1279 | } |
1280 | ||
1a4d82fc JJ |
1281 | pub type PolyFnOutput<'tcx> = Binder<FnOutput<'tcx>>; |
1282 | ||
1283 | impl<'tcx> PolyFnOutput<'tcx> { | |
1284 | pub fn diverges(&self) -> bool { | |
1285 | self.0.diverges() | |
223e47cc LB |
1286 | } |
1287 | } | |
1288 | ||
1a4d82fc JJ |
1289 | /// Signature of a function type, which I have arbitrarily |
1290 | /// decided to use to refer to the input/output types. | |
1291 | /// | |
1292 | /// - `inputs` is the list of arguments and their modes. | |
1293 | /// - `output` is the return type. | |
1294 | /// - `variadic` indicates whether this is a variadic function. (only true for foreign fns) | |
1295 | #[derive(Clone, PartialEq, Eq, Hash)] | |
1296 | pub struct FnSig<'tcx> { | |
1297 | pub inputs: Vec<Ty<'tcx>>, | |
1298 | pub output: FnOutput<'tcx>, | |
1299 | pub variadic: bool | |
223e47cc LB |
1300 | } |
1301 | ||
1a4d82fc | 1302 | pub type PolyFnSig<'tcx> = Binder<FnSig<'tcx>>; |
223e47cc | 1303 | |
1a4d82fc JJ |
1304 | impl<'tcx> PolyFnSig<'tcx> { |
1305 | pub fn inputs(&self) -> ty::Binder<Vec<Ty<'tcx>>> { | |
c34b1796 | 1306 | self.map_bound_ref(|fn_sig| fn_sig.inputs.clone()) |
223e47cc | 1307 | } |
c34b1796 AL |
1308 | pub fn input(&self, index: usize) -> ty::Binder<Ty<'tcx>> { |
1309 | self.map_bound_ref(|fn_sig| fn_sig.inputs[index]) | |
1a4d82fc JJ |
1310 | } |
1311 | pub fn output(&self) -> ty::Binder<FnOutput<'tcx>> { | |
c34b1796 | 1312 | self.map_bound_ref(|fn_sig| fn_sig.output.clone()) |
1a4d82fc JJ |
1313 | } |
1314 | pub fn variadic(&self) -> bool { | |
c34b1796 | 1315 | self.skip_binder().variadic |
1a4d82fc JJ |
1316 | } |
1317 | } | |
1318 | ||
62682a34 | 1319 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
1320 | pub struct ParamTy { |
1321 | pub space: subst::ParamSpace, | |
1322 | pub idx: u32, | |
1323 | pub name: ast::Name, | |
223e47cc LB |
1324 | } |
1325 | ||
1a4d82fc JJ |
1326 | /// A [De Bruijn index][dbi] is a standard means of representing |
1327 | /// regions (and perhaps later types) in a higher-ranked setting. In | |
1328 | /// particular, imagine a type like this: | |
1329 | /// | |
c34b1796 | 1330 | /// for<'a> fn(for<'b> fn(&'b isize, &'a isize), &'a char) |
1a4d82fc JJ |
1331 | /// ^ ^ | | | |
1332 | /// | | | | | | |
1333 | /// | +------------+ 1 | | | |
1334 | /// | | | | |
1335 | /// +--------------------------------+ 2 | | |
1336 | /// | | | |
1337 | /// +------------------------------------------+ 1 | |
223e47cc | 1338 | /// |
1a4d82fc JJ |
1339 | /// In this type, there are two binders (the outer fn and the inner |
1340 | /// fn). We need to be able to determine, for any given region, which | |
1341 | /// fn type it is bound by, the inner or the outer one. There are | |
1342 | /// various ways you can do this, but a De Bruijn index is one of the | |
1343 | /// more convenient and has some nice properties. The basic idea is to | |
1344 | /// count the number of binders, inside out. Some examples should help | |
1345 | /// clarify what I mean. | |
223e47cc | 1346 | /// |
c34b1796 | 1347 | /// Let's start with the reference type `&'b isize` that is the first |
1a4d82fc JJ |
1348 | /// argument to the inner function. This region `'b` is assigned a De |
1349 | /// Bruijn index of 1, meaning "the innermost binder" (in this case, a | |
1350 | /// fn). The region `'a` that appears in the second argument type (`&'a | |
c34b1796 | 1351 | /// isize`) would then be assigned a De Bruijn index of 2, meaning "the |
1a4d82fc JJ |
1352 | /// second-innermost binder". (These indices are written on the arrays |
1353 | /// in the diagram). | |
223e47cc | 1354 | /// |
1a4d82fc JJ |
1355 | /// What is interesting is that De Bruijn index attached to a particular |
1356 | /// variable will vary depending on where it appears. For example, | |
1357 | /// the final type `&'a char` also refers to the region `'a` declared on | |
1358 | /// the outermost fn. But this time, this reference is not nested within | |
1359 | /// any other binders (i.e., it is not an argument to the inner fn, but | |
1360 | /// rather the outer one). Therefore, in this case, it is assigned a | |
1361 | /// De Bruijn index of 1, because the innermost binder in that location | |
1362 | /// is the outer fn. | |
1363 | /// | |
1364 | /// [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index | |
85aaf69f | 1365 | #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug, Copy)] |
1a4d82fc JJ |
1366 | pub struct DebruijnIndex { |
1367 | // We maintain the invariant that this is never 0. So 1 indicates | |
1368 | // the innermost binder. To ensure this, create with `DebruijnIndex::new`. | |
1369 | pub depth: u32, | |
223e47cc LB |
1370 | } |
1371 | ||
1a4d82fc | 1372 | /// Representation of regions: |
62682a34 | 1373 | #[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Copy)] |
1a4d82fc JJ |
1374 | pub enum Region { |
1375 | // Region bound in a type or fn declaration which will be | |
1376 | // substituted 'early' -- that is, at the same time when type | |
1377 | // parameters are substituted. | |
9346a6ac | 1378 | ReEarlyBound(EarlyBoundRegion), |
1a4d82fc JJ |
1379 | |
1380 | // Region bound in a function scope, which will be substituted when the | |
1381 | // function is called. | |
1382 | ReLateBound(DebruijnIndex, BoundRegion), | |
970d7e83 | 1383 | |
1a4d82fc JJ |
1384 | /// When checking a function body, the types of all arguments and so forth |
1385 | /// that refer to bound region parameters are modified to refer to free | |
1386 | /// region parameters. | |
1387 | ReFree(FreeRegion), | |
223e47cc | 1388 | |
85aaf69f SL |
1389 | /// A concrete region naming some statically determined extent |
1390 | /// (e.g. an expression or sequence of statements) within the | |
1391 | /// current function. | |
1a4d82fc | 1392 | ReScope(region::CodeExtent), |
223e47cc | 1393 | |
1a4d82fc JJ |
1394 | /// Static data that has an "infinite" lifetime. Top in the region lattice. |
1395 | ReStatic, | |
223e47cc | 1396 | |
1a4d82fc JJ |
1397 | /// A region variable. Should not exist after typeck. |
1398 | ReInfer(InferRegion), | |
970d7e83 | 1399 | |
1a4d82fc JJ |
1400 | /// Empty lifetime is for data that is never accessed. |
1401 | /// Bottom in the region lattice. We treat ReEmpty somewhat | |
1402 | /// specially; at least right now, we do not generate instances of | |
1403 | /// it during the GLB computations, but rather | |
1404 | /// generate an error instead. This is to improve error messages. | |
1405 | /// The only way to get an instance of ReEmpty is to have a region | |
1406 | /// variable with no constraints. | |
1407 | ReEmpty, | |
1408 | } | |
1409 | ||
9346a6ac AL |
1410 | #[derive(Copy, Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, Debug)] |
1411 | pub struct EarlyBoundRegion { | |
1412 | pub param_id: ast::NodeId, | |
1413 | pub space: subst::ParamSpace, | |
1414 | pub index: u32, | |
1415 | pub name: ast::Name, | |
1416 | } | |
1417 | ||
1a4d82fc JJ |
1418 | /// Upvars do not get their own node-id. Instead, we use the pair of |
1419 | /// the original var id (that is, the root variable that is referenced | |
1420 | /// by the upvar) and the id of the closure expression. | |
62682a34 | 1421 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
1422 | pub struct UpvarId { |
1423 | pub var_id: ast::NodeId, | |
1424 | pub closure_expr_id: ast::NodeId, | |
1425 | } | |
1426 | ||
85aaf69f | 1427 | #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)] |
1a4d82fc JJ |
1428 | pub enum BorrowKind { |
1429 | /// Data must be immutable and is aliasable. | |
1430 | ImmBorrow, | |
1431 | ||
1432 | /// Data must be immutable but not aliasable. This kind of borrow | |
1433 | /// cannot currently be expressed by the user and is used only in | |
1434 | /// implicit closure bindings. It is needed when you the closure | |
1435 | /// is borrowing or mutating a mutable referent, e.g.: | |
1436 | /// | |
c34b1796 | 1437 | /// let x: &mut isize = ...; |
1a4d82fc JJ |
1438 | /// let y = || *x += 5; |
1439 | /// | |
1440 | /// If we were to try to translate this closure into a more explicit | |
1441 | /// form, we'd encounter an error with the code as written: | |
1442 | /// | |
c34b1796 AL |
1443 | /// struct Env { x: & &mut isize } |
1444 | /// let x: &mut isize = ...; | |
1a4d82fc JJ |
1445 | /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn |
1446 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } | |
1447 | /// | |
1448 | /// This is then illegal because you cannot mutate a `&mut` found | |
1449 | /// in an aliasable location. To solve, you'd have to translate with | |
1450 | /// an `&mut` borrow: | |
1451 | /// | |
c34b1796 AL |
1452 | /// struct Env { x: & &mut isize } |
1453 | /// let x: &mut isize = ...; | |
1a4d82fc JJ |
1454 | /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x |
1455 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } | |
1456 | /// | |
1457 | /// Now the assignment to `**env.x` is legal, but creating a | |
1458 | /// mutable pointer to `x` is not because `x` is not mutable. We | |
1459 | /// could fix this by declaring `x` as `let mut x`. This is ok in | |
1460 | /// user code, if awkward, but extra weird for closures, since the | |
1461 | /// borrow is hidden. | |
1462 | /// | |
1463 | /// So we introduce a "unique imm" borrow -- the referent is | |
1464 | /// immutable, but not aliasable. This solves the problem. For | |
1465 | /// simplicity, we don't give users the way to express this | |
1466 | /// borrow, it's just used when translating closures. | |
1467 | UniqueImmBorrow, | |
1468 | ||
1469 | /// Data is mutable and not aliasable. | |
1470 | MutBorrow | |
1471 | } | |
1472 | ||
85aaf69f SL |
1473 | /// Information describing the capture of an upvar. This is computed |
1474 | /// during `typeck`, specifically by `regionck`. | |
1475 | #[derive(PartialEq, Clone, RustcEncodable, RustcDecodable, Debug, Copy)] | |
1476 | pub enum UpvarCapture { | |
1477 | /// Upvar is captured by value. This is always true when the | |
1478 | /// closure is labeled `move`, but can also be true in other cases | |
1479 | /// depending on inference. | |
1480 | ByValue, | |
1481 | ||
1482 | /// Upvar is captured by reference. | |
1483 | ByRef(UpvarBorrow), | |
1484 | } | |
1485 | ||
62682a34 | 1486 | #[derive(PartialEq, Clone, RustcEncodable, RustcDecodable, Copy)] |
1a4d82fc | 1487 | pub struct UpvarBorrow { |
85aaf69f SL |
1488 | /// The kind of borrow: by-ref upvars have access to shared |
1489 | /// immutable borrows, which are not part of the normal language | |
1490 | /// syntax. | |
1a4d82fc | 1491 | pub kind: BorrowKind, |
85aaf69f SL |
1492 | |
1493 | /// Region of the resulting reference. | |
1a4d82fc JJ |
1494 | pub region: ty::Region, |
1495 | } | |
1496 | ||
85aaf69f | 1497 | pub type UpvarCaptureMap = FnvHashMap<UpvarId, UpvarCapture>; |
223e47cc | 1498 | |
1a4d82fc | 1499 | impl Region { |
62682a34 SL |
1500 | pub fn is_global(&self) -> bool { |
1501 | // does this represent a region that can be named in a global | |
1502 | // way? used in fulfillment caching. | |
1503 | match *self { | |
1504 | ty::ReStatic | ty::ReEmpty => true, | |
1505 | _ => false, | |
1506 | } | |
1507 | } | |
1508 | ||
1a4d82fc JJ |
1509 | pub fn is_bound(&self) -> bool { |
1510 | match *self { | |
1511 | ty::ReEarlyBound(..) => true, | |
1512 | ty::ReLateBound(..) => true, | |
1513 | _ => false | |
223e47cc LB |
1514 | } |
1515 | } | |
223e47cc | 1516 | |
1a4d82fc JJ |
1517 | pub fn escapes_depth(&self, depth: u32) -> bool { |
1518 | match *self { | |
1519 | ty::ReLateBound(debruijn, _) => debruijn.depth > depth, | |
1520 | _ => false, | |
1521 | } | |
970d7e83 LB |
1522 | } |
1523 | } | |
1524 | ||
1a4d82fc | 1525 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, |
62682a34 | 1526 | RustcEncodable, RustcDecodable, Copy)] |
1a4d82fc JJ |
1527 | /// A "free" region `fr` can be interpreted as "some region |
1528 | /// at least as big as the scope `fr.scope`". | |
1529 | pub struct FreeRegion { | |
85aaf69f | 1530 | pub scope: region::DestructionScopeData, |
1a4d82fc | 1531 | pub bound_region: BoundRegion |
223e47cc LB |
1532 | } |
1533 | ||
1a4d82fc | 1534 | #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, |
62682a34 | 1535 | RustcEncodable, RustcDecodable, Copy, Debug)] |
1a4d82fc JJ |
1536 | pub enum BoundRegion { |
1537 | /// An anonymous region parameter for a given fn (&T) | |
1538 | BrAnon(u32), | |
223e47cc | 1539 | |
1a4d82fc JJ |
1540 | /// Named region parameters for functions (a in &'a T) |
1541 | /// | |
1542 | /// The def-id is needed to distinguish free regions in | |
1543 | /// the event of shadowing. | |
1544 | BrNamed(ast::DefId, ast::Name), | |
223e47cc | 1545 | |
1a4d82fc JJ |
1546 | /// Fresh bound identifiers created during GLB computations. |
1547 | BrFresh(u32), | |
223e47cc | 1548 | |
1a4d82fc JJ |
1549 | // Anonymous region for the implicit env pointer parameter |
1550 | // to a closure | |
1551 | BrEnv | |
1552 | } | |
223e47cc | 1553 | |
1a4d82fc JJ |
1554 | // NB: If you change this, you'll probably want to change the corresponding |
1555 | // AST structure in libsyntax/ast.rs as well. | |
85aaf69f | 1556 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
62682a34 SL |
1557 | pub enum TypeVariants<'tcx> { |
1558 | /// The primitive boolean type. Written as `bool`. | |
1559 | TyBool, | |
1560 | ||
1561 | /// The primitive character type; holds a Unicode scalar value | |
1562 | /// (a non-surrogate code point). Written as `char`. | |
1563 | TyChar, | |
1564 | ||
1565 | /// A primitive signed integer type. For example, `i32`. | |
1566 | TyInt(ast::IntTy), | |
1567 | ||
1568 | /// A primitive unsigned integer type. For example, `u32`. | |
1569 | TyUint(ast::UintTy), | |
1570 | ||
1571 | /// A primitive floating-point type. For example, `f64`. | |
1572 | TyFloat(ast::FloatTy), | |
1573 | ||
1574 | /// An enumerated type, defined with `enum`. | |
1575 | /// | |
1576 | /// Substs here, possibly against intuition, *may* contain `TyParam`s. | |
1a4d82fc | 1577 | /// That is, even after substitution it is possible that there are type |
62682a34 SL |
1578 | /// variables. This happens when the `TyEnum` corresponds to an enum |
1579 | /// definition and not a concrete use of it. To get the correct `TyEnum` | |
1a4d82fc | 1580 | /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in |
62682a34 | 1581 | /// the `ast_ty_to_ty_cache`. This is probably true for `TyStruct` as |
c34b1796 | 1582 | /// well. |
62682a34 | 1583 | TyEnum(DefId, &'tcx Substs<'tcx>), |
1a4d82fc | 1584 | |
62682a34 SL |
1585 | /// A structure type, defined with `struct`. |
1586 | /// | |
1587 | /// See warning about substitutions for enumerated types. | |
1588 | TyStruct(DefId, &'tcx Substs<'tcx>), | |
1a4d82fc | 1589 | |
62682a34 SL |
1590 | /// `Box<T>`; this is nominally a struct in the documentation, but is |
1591 | /// special-cased internally. For example, it is possible to implicitly | |
1592 | /// move the contents of a box out of that box, and methods of any type | |
1593 | /// can have type `Box<Self>`. | |
1594 | TyBox(Ty<'tcx>), | |
1a4d82fc | 1595 | |
62682a34 SL |
1596 | /// The pointee of a string slice. Written as `str`. |
1597 | TyStr, | |
1a4d82fc | 1598 | |
62682a34 SL |
1599 | /// An array with the given length. Written as `[T; n]`. |
1600 | TyArray(Ty<'tcx>, usize), | |
1a4d82fc | 1601 | |
62682a34 SL |
1602 | /// The pointee of an array slice. Written as `[T]`. |
1603 | TySlice(Ty<'tcx>), | |
1a4d82fc | 1604 | |
62682a34 SL |
1605 | /// A raw pointer. Written as `*mut T` or `*const T` |
1606 | TyRawPtr(mt<'tcx>), | |
1607 | ||
1608 | /// A reference; a pointer with an associated lifetime. Written as | |
1609 | /// `&a mut T` or `&'a T`. | |
1610 | TyRef(&'tcx Region, mt<'tcx>), | |
1611 | ||
1612 | /// If the def-id is Some(_), then this is the type of a specific | |
1613 | /// fn item. Otherwise, if None(_), it a fn pointer type. | |
1614 | /// | |
1615 | /// FIXME: Conflating function pointers and the type of a | |
1616 | /// function is probably a terrible idea; a function pointer is a | |
1617 | /// value with a specific type, but a function can be polymorphic | |
1618 | /// or dynamically dispatched. | |
1619 | TyBareFn(Option<DefId>, &'tcx BareFnTy<'tcx>), | |
1620 | ||
1621 | /// A trait, defined with `trait`. | |
1622 | TyTrait(Box<TraitTy<'tcx>>), | |
1623 | ||
1624 | /// The anonymous type of a closure. Used to represent the type of | |
1625 | /// `|a| a`. | |
1626 | TyClosure(DefId, &'tcx Substs<'tcx>), | |
1627 | ||
1628 | /// A tuple type. For example, `(i32, bool)`. | |
1629 | TyTuple(Vec<Ty<'tcx>>), | |
1630 | ||
1631 | /// The projection of an associated type. For example, | |
1632 | /// `<T as Trait<..>>::N`. | |
1633 | TyProjection(ProjectionTy<'tcx>), | |
1634 | ||
1635 | /// A type parameter; for example, `T` in `fn f<T>(x: T) {} | |
1636 | TyParam(ParamTy), | |
1637 | ||
1638 | /// A type variable used during type-checking. | |
1639 | TyInfer(InferTy), | |
1640 | ||
1641 | /// A placeholder for a type which could not be computed; this is | |
1642 | /// propagated to avoid useless error messages. | |
1643 | TyError, | |
1a4d82fc | 1644 | } |
223e47cc | 1645 | |
62682a34 SL |
1646 | #[derive(Clone, PartialEq, Eq, Hash)] |
1647 | pub struct TraitTy<'tcx> { | |
1a4d82fc JJ |
1648 | pub principal: ty::PolyTraitRef<'tcx>, |
1649 | pub bounds: ExistentialBounds<'tcx>, | |
1650 | } | |
223e47cc | 1651 | |
62682a34 | 1652 | impl<'tcx> TraitTy<'tcx> { |
1a4d82fc JJ |
1653 | pub fn principal_def_id(&self) -> ast::DefId { |
1654 | self.principal.0.def_id | |
1655 | } | |
223e47cc | 1656 | |
1a4d82fc JJ |
1657 | /// Object types don't have a self-type specified. Therefore, when |
1658 | /// we convert the principal trait-ref into a normal trait-ref, | |
1659 | /// you must give *some* self-type. A common choice is `mk_err()` | |
1660 | /// or some skolemized type. | |
1661 | pub fn principal_trait_ref_with_self_ty(&self, | |
1662 | tcx: &ctxt<'tcx>, | |
1663 | self_ty: Ty<'tcx>) | |
1664 | -> ty::PolyTraitRef<'tcx> | |
1665 | { | |
1666 | // otherwise the escaping regions would be captured by the binder | |
1667 | assert!(!self_ty.has_escaping_regions()); | |
223e47cc | 1668 | |
d9579d0f | 1669 | ty::Binder(TraitRef { |
1a4d82fc JJ |
1670 | def_id: self.principal.0.def_id, |
1671 | substs: tcx.mk_substs(self.principal.0.substs.with_self_ty(self_ty)), | |
d9579d0f | 1672 | }) |
1a4d82fc | 1673 | } |
223e47cc | 1674 | |
1a4d82fc JJ |
1675 | pub fn projection_bounds_with_self_ty(&self, |
1676 | tcx: &ctxt<'tcx>, | |
1677 | self_ty: Ty<'tcx>) | |
1678 | -> Vec<ty::PolyProjectionPredicate<'tcx>> | |
1679 | { | |
1680 | // otherwise the escaping regions would be captured by the binders | |
1681 | assert!(!self_ty.has_escaping_regions()); | |
1682 | ||
1683 | self.bounds.projection_bounds.iter() | |
1684 | .map(|in_poly_projection_predicate| { | |
1685 | let in_projection_ty = &in_poly_projection_predicate.0.projection_ty; | |
1686 | let substs = tcx.mk_substs(in_projection_ty.trait_ref.substs.with_self_ty(self_ty)); | |
d9579d0f AL |
1687 | let trait_ref = ty::TraitRef::new(in_projection_ty.trait_ref.def_id, |
1688 | substs); | |
1a4d82fc JJ |
1689 | let projection_ty = ty::ProjectionTy { |
1690 | trait_ref: trait_ref, | |
1691 | item_name: in_projection_ty.item_name | |
1692 | }; | |
1693 | ty::Binder(ty::ProjectionPredicate { | |
1694 | projection_ty: projection_ty, | |
1695 | ty: in_poly_projection_predicate.0.ty | |
1696 | }) | |
1697 | }) | |
1698 | .collect() | |
1699 | } | |
1700 | } | |
223e47cc | 1701 | |
1a4d82fc JJ |
1702 | /// A complete reference to a trait. These take numerous guises in syntax, |
1703 | /// but perhaps the most recognizable form is in a where clause: | |
1704 | /// | |
1705 | /// T : Foo<U> | |
1706 | /// | |
1707 | /// This would be represented by a trait-reference where the def-id is the | |
1708 | /// def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the | |
1709 | /// `SelfSpace` and `U` as parameter 0 in the `TypeSpace`. | |
1710 | /// | |
1711 | /// Trait references also appear in object types like `Foo<U>`, but in | |
1712 | /// that case the `Self` parameter is absent from the substitutions. | |
1713 | /// | |
1714 | /// Note that a `TraitRef` introduces a level of region binding, to | |
1715 | /// account for higher-ranked trait bounds like `T : for<'a> Foo<&'a | |
1716 | /// U>` or higher-ranked object types. | |
62682a34 | 1717 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
1718 | pub struct TraitRef<'tcx> { |
1719 | pub def_id: DefId, | |
1720 | pub substs: &'tcx Substs<'tcx>, | |
1721 | } | |
223e47cc | 1722 | |
d9579d0f | 1723 | pub type PolyTraitRef<'tcx> = Binder<TraitRef<'tcx>>; |
223e47cc | 1724 | |
1a4d82fc JJ |
1725 | impl<'tcx> PolyTraitRef<'tcx> { |
1726 | pub fn self_ty(&self) -> Ty<'tcx> { | |
1727 | self.0.self_ty() | |
1728 | } | |
223e47cc | 1729 | |
1a4d82fc JJ |
1730 | pub fn def_id(&self) -> ast::DefId { |
1731 | self.0.def_id | |
1732 | } | |
223e47cc | 1733 | |
1a4d82fc JJ |
1734 | pub fn substs(&self) -> &'tcx Substs<'tcx> { |
1735 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> | |
1736 | self.0.substs | |
970d7e83 | 1737 | } |
223e47cc | 1738 | |
1a4d82fc JJ |
1739 | pub fn input_types(&self) -> &[Ty<'tcx>] { |
1740 | // FIXME(#20664) every use of this fn is probably a bug, it should yield Binder<> | |
1741 | self.0.input_types() | |
970d7e83 | 1742 | } |
223e47cc | 1743 | |
1a4d82fc JJ |
1744 | pub fn to_poly_trait_predicate(&self) -> PolyTraitPredicate<'tcx> { |
1745 | // Note that we preserve binding levels | |
1746 | Binder(TraitPredicate { trait_ref: self.0.clone() }) | |
970d7e83 | 1747 | } |
223e47cc LB |
1748 | } |
1749 | ||
1a4d82fc | 1750 | /// Binder is a binder for higher-ranked lifetimes. It is part of the |
c34b1796 | 1751 | /// compiler's representation for things like `for<'a> Fn(&'a isize)` |
1a4d82fc JJ |
1752 | /// (which would be represented by the type `PolyTraitRef == |
1753 | /// Binder<TraitRef>`). Note that when we skolemize, instantiate, | |
85aaf69f | 1754 | /// erase, or otherwise "discharge" these bound regions, we change the |
1a4d82fc JJ |
1755 | /// type from `Binder<T>` to just `T` (see |
1756 | /// e.g. `liberate_late_bound_regions`). | |
85aaf69f | 1757 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc | 1758 | pub struct Binder<T>(pub T); |
223e47cc | 1759 | |
c34b1796 AL |
1760 | impl<T> Binder<T> { |
1761 | /// Skips the binder and returns the "bound" value. This is a | |
1762 | /// risky thing to do because it's easy to get confused about | |
1763 | /// debruijn indices and the like. It is usually better to | |
1764 | /// discharge the binder using `no_late_bound_regions` or | |
1765 | /// `replace_late_bound_regions` or something like | |
1766 | /// that. `skip_binder` is only valid when you are either | |
1767 | /// extracting data that has nothing to do with bound regions, you | |
1768 | /// are doing some sort of test that does not involve bound | |
1769 | /// regions, or you are being very careful about your depth | |
1770 | /// accounting. | |
1771 | /// | |
1772 | /// Some examples where `skip_binder` is reasonable: | |
1773 | /// - extracting the def-id from a PolyTraitRef; | |
1774 | /// - comparing the self type of a PolyTraitRef to see if it is equal to | |
1775 | /// a type parameter `X`, since the type `X` does not reference any regions | |
1776 | pub fn skip_binder(&self) -> &T { | |
1777 | &self.0 | |
1778 | } | |
1779 | ||
1780 | pub fn as_ref(&self) -> Binder<&T> { | |
1781 | ty::Binder(&self.0) | |
1782 | } | |
1783 | ||
1784 | pub fn map_bound_ref<F,U>(&self, f: F) -> Binder<U> | |
1785 | where F: FnOnce(&T) -> U | |
1786 | { | |
1787 | self.as_ref().map_bound(f) | |
1788 | } | |
1789 | ||
1790 | pub fn map_bound<F,U>(self, f: F) -> Binder<U> | |
1791 | where F: FnOnce(T) -> U | |
1792 | { | |
1793 | ty::Binder(f(self.0)) | |
1794 | } | |
1795 | } | |
1796 | ||
1a4d82fc JJ |
1797 | #[derive(Clone, Copy, PartialEq)] |
1798 | pub enum IntVarValue { | |
1799 | IntType(ast::IntTy), | |
1800 | UintType(ast::UintTy), | |
223e47cc LB |
1801 | } |
1802 | ||
85aaf69f | 1803 | #[derive(Clone, Copy, Debug)] |
1a4d82fc JJ |
1804 | pub enum terr_vstore_kind { |
1805 | terr_vec, | |
1806 | terr_str, | |
1807 | terr_fn, | |
1808 | terr_trait | |
223e47cc LB |
1809 | } |
1810 | ||
85aaf69f | 1811 | #[derive(Clone, Copy, Debug)] |
1a4d82fc JJ |
1812 | pub struct expected_found<T> { |
1813 | pub expected: T, | |
1814 | pub found: T | |
223e47cc LB |
1815 | } |
1816 | ||
1a4d82fc | 1817 | // Data structures used in type unification |
85aaf69f | 1818 | #[derive(Clone, Copy, Debug)] |
1a4d82fc JJ |
1819 | pub enum type_err<'tcx> { |
1820 | terr_mismatch, | |
1821 | terr_unsafety_mismatch(expected_found<ast::Unsafety>), | |
1a4d82fc JJ |
1822 | terr_abi_mismatch(expected_found<abi::Abi>), |
1823 | terr_mutability, | |
1a4d82fc JJ |
1824 | terr_box_mutability, |
1825 | terr_ptr_mutability, | |
1826 | terr_ref_mutability, | |
1827 | terr_vec_mutability, | |
c34b1796 AL |
1828 | terr_tuple_size(expected_found<usize>), |
1829 | terr_fixed_array_size(expected_found<usize>), | |
1830 | terr_ty_param_size(expected_found<usize>), | |
1a4d82fc JJ |
1831 | terr_arg_count, |
1832 | terr_regions_does_not_outlive(Region, Region), | |
1833 | terr_regions_not_same(Region, Region), | |
1834 | terr_regions_no_overlap(Region, Region), | |
1835 | terr_regions_insufficiently_polymorphic(BoundRegion, Region), | |
1836 | terr_regions_overly_polymorphic(BoundRegion, Region), | |
1a4d82fc JJ |
1837 | terr_sorts(expected_found<Ty<'tcx>>), |
1838 | terr_integer_as_char, | |
1839 | terr_int_mismatch(expected_found<IntVarValue>), | |
1840 | terr_float_mismatch(expected_found<ast::FloatTy>), | |
1841 | terr_traits(expected_found<ast::DefId>), | |
1842 | terr_builtin_bounds(expected_found<BuiltinBounds>), | |
1843 | terr_variadic_mismatch(expected_found<bool>), | |
1844 | terr_cyclic_ty, | |
1845 | terr_convergence_mismatch(expected_found<bool>), | |
1846 | terr_projection_name_mismatched(expected_found<ast::Name>), | |
c34b1796 | 1847 | terr_projection_bounds_length(expected_found<usize>), |
1a4d82fc JJ |
1848 | } |
1849 | ||
1a4d82fc | 1850 | /// Bounds suitable for an existentially quantified type parameter |
62682a34 SL |
1851 | /// such as those that appear in object types or closure types. |
1852 | #[derive(PartialEq, Eq, Hash, Clone)] | |
1a4d82fc JJ |
1853 | pub struct ExistentialBounds<'tcx> { |
1854 | pub region_bound: ty::Region, | |
1855 | pub builtin_bounds: BuiltinBounds, | |
1856 | pub projection_bounds: Vec<PolyProjectionPredicate<'tcx>>, | |
62682a34 SL |
1857 | |
1858 | // If true, this TyTrait used a "default bound" in the surface | |
1859 | // syntax. This makes no difference to the type system but is | |
1860 | // handy for error reporting. | |
1861 | pub region_bound_will_change: bool, | |
223e47cc LB |
1862 | } |
1863 | ||
62682a34 SL |
1864 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] |
1865 | pub struct BuiltinBounds(EnumSet<BuiltinBound>); | |
223e47cc | 1866 | |
62682a34 SL |
1867 | impl BuiltinBounds { |
1868 | pub fn empty() -> BuiltinBounds { | |
1869 | BuiltinBounds(EnumSet::new()) | |
1870 | } | |
1871 | ||
1872 | pub fn iter(&self) -> enum_set::Iter<BuiltinBound> { | |
1873 | self.into_iter() | |
1874 | } | |
1875 | ||
1876 | pub fn to_predicates<'tcx>(&self, | |
1877 | tcx: &ty::ctxt<'tcx>, | |
1878 | self_ty: Ty<'tcx>) -> Vec<Predicate<'tcx>> { | |
1879 | self.iter().filter_map(|builtin_bound| | |
1880 | match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, self_ty) { | |
1881 | Ok(trait_ref) => Some(trait_ref.as_predicate()), | |
1882 | Err(ErrorReported) => { None } | |
1883 | } | |
1884 | ).collect() | |
1885 | } | |
1886 | } | |
1887 | ||
1888 | impl ops::Deref for BuiltinBounds { | |
1889 | type Target = EnumSet<BuiltinBound>; | |
1890 | fn deref(&self) -> &Self::Target { &self.0 } | |
1891 | } | |
1892 | ||
1893 | impl ops::DerefMut for BuiltinBounds { | |
1894 | fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } | |
223e47cc LB |
1895 | } |
1896 | ||
62682a34 SL |
1897 | impl<'a> IntoIterator for &'a BuiltinBounds { |
1898 | type Item = BuiltinBound; | |
1899 | type IntoIter = enum_set::Iter<BuiltinBound>; | |
1900 | fn into_iter(self) -> Self::IntoIter { | |
1901 | (**self).into_iter() | |
1902 | } | |
223e47cc LB |
1903 | } |
1904 | ||
62682a34 SL |
1905 | #[derive(Clone, RustcEncodable, PartialEq, Eq, RustcDecodable, Hash, |
1906 | Debug, Copy)] | |
1907 | #[repr(usize)] | |
1908 | pub enum BuiltinBound { | |
1909 | Send, | |
1910 | Sized, | |
1911 | Copy, | |
1912 | Sync, | |
223e47cc LB |
1913 | } |
1914 | ||
1a4d82fc JJ |
1915 | /// An existential bound that does not implement any traits. |
1916 | pub fn region_existential_bound<'tcx>(r: ty::Region) -> ExistentialBounds<'tcx> { | |
1917 | ty::ExistentialBounds { region_bound: r, | |
62682a34 SL |
1918 | builtin_bounds: BuiltinBounds::empty(), |
1919 | projection_bounds: Vec::new(), | |
1920 | region_bound_will_change: false, } | |
223e47cc LB |
1921 | } |
1922 | ||
1a4d82fc | 1923 | impl CLike for BuiltinBound { |
c34b1796 AL |
1924 | fn to_usize(&self) -> usize { |
1925 | *self as usize | |
1a4d82fc | 1926 | } |
c34b1796 | 1927 | fn from_usize(v: usize) -> BuiltinBound { |
1a4d82fc JJ |
1928 | unsafe { mem::transmute(v) } |
1929 | } | |
223e47cc LB |
1930 | } |
1931 | ||
1a4d82fc JJ |
1932 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1933 | pub struct TyVid { | |
1934 | pub index: u32 | |
223e47cc | 1935 | } |
223e47cc | 1936 | |
1a4d82fc JJ |
1937 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1938 | pub struct IntVid { | |
1939 | pub index: u32 | |
223e47cc LB |
1940 | } |
1941 | ||
1a4d82fc JJ |
1942 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1943 | pub struct FloatVid { | |
1944 | pub index: u32 | |
223e47cc LB |
1945 | } |
1946 | ||
1a4d82fc JJ |
1947 | #[derive(Clone, PartialEq, Eq, RustcEncodable, RustcDecodable, Hash, Copy)] |
1948 | pub struct RegionVid { | |
1949 | pub index: u32 | |
223e47cc LB |
1950 | } |
1951 | ||
1a4d82fc JJ |
1952 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] |
1953 | pub enum InferTy { | |
1954 | TyVar(TyVid), | |
1955 | IntVar(IntVid), | |
1956 | FloatVar(FloatVid), | |
223e47cc | 1957 | |
1a4d82fc JJ |
1958 | /// A `FreshTy` is one that is generated as a replacement for an |
1959 | /// unbound type variable. This is convenient for caching etc. See | |
1960 | /// `middle::infer::freshen` for more details. | |
1961 | FreshTy(u32), | |
1a4d82fc | 1962 | FreshIntTy(u32), |
d9579d0f | 1963 | FreshFloatTy(u32) |
223e47cc LB |
1964 | } |
1965 | ||
85aaf69f | 1966 | #[derive(Clone, RustcEncodable, RustcDecodable, PartialEq, Eq, Hash, Debug, Copy)] |
1a4d82fc JJ |
1967 | pub enum UnconstrainedNumeric { |
1968 | UnconstrainedFloat, | |
1969 | UnconstrainedInt, | |
1970 | Neither, | |
1971 | } | |
223e47cc | 1972 | |
223e47cc | 1973 | |
85aaf69f | 1974 | #[derive(Clone, RustcEncodable, RustcDecodable, Eq, Hash, Debug, Copy)] |
1a4d82fc JJ |
1975 | pub enum InferRegion { |
1976 | ReVar(RegionVid), | |
1977 | ReSkolemized(u32, BoundRegion) | |
1978 | } | |
223e47cc | 1979 | |
1a4d82fc JJ |
1980 | impl cmp::PartialEq for InferRegion { |
1981 | fn eq(&self, other: &InferRegion) -> bool { | |
1982 | match ((*self), *other) { | |
1983 | (ReVar(rva), ReVar(rvb)) => { | |
1984 | rva == rvb | |
1985 | } | |
1986 | (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => { | |
1987 | rva == rvb | |
1988 | } | |
1989 | _ => false | |
1990 | } | |
1991 | } | |
1992 | fn ne(&self, other: &InferRegion) -> bool { | |
1993 | !((*self) == (*other)) | |
1994 | } | |
1995 | } | |
223e47cc | 1996 | |
85aaf69f | 1997 | impl fmt::Debug for TyVid { |
62682a34 | 1998 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
1a4d82fc JJ |
1999 | write!(f, "_#{}t", self.index) |
2000 | } | |
223e47cc LB |
2001 | } |
2002 | ||
85aaf69f | 2003 | impl fmt::Debug for IntVid { |
1a4d82fc JJ |
2004 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2005 | write!(f, "_#{}i", self.index) | |
2006 | } | |
2007 | } | |
223e47cc | 2008 | |
85aaf69f | 2009 | impl fmt::Debug for FloatVid { |
1a4d82fc JJ |
2010 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2011 | write!(f, "_#{}f", self.index) | |
2012 | } | |
223e47cc LB |
2013 | } |
2014 | ||
85aaf69f | 2015 | impl fmt::Debug for RegionVid { |
1a4d82fc JJ |
2016 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2017 | write!(f, "'_#{}r", self.index) | |
2018 | } | |
2019 | } | |
223e47cc | 2020 | |
85aaf69f | 2021 | impl<'tcx> fmt::Debug for FnSig<'tcx> { |
1a4d82fc JJ |
2022 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2023 | write!(f, "({:?}; variadic: {})->{:?}", self.inputs, self.variadic, self.output) | |
2024 | } | |
223e47cc LB |
2025 | } |
2026 | ||
85aaf69f | 2027 | impl fmt::Debug for InferTy { |
1a4d82fc JJ |
2028 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2029 | match *self { | |
2030 | TyVar(ref v) => v.fmt(f), | |
2031 | IntVar(ref v) => v.fmt(f), | |
2032 | FloatVar(ref v) => v.fmt(f), | |
2033 | FreshTy(v) => write!(f, "FreshTy({:?})", v), | |
2034 | FreshIntTy(v) => write!(f, "FreshIntTy({:?})", v), | |
d9579d0f | 2035 | FreshFloatTy(v) => write!(f, "FreshFloatTy({:?})", v) |
1a4d82fc | 2036 | } |
970d7e83 | 2037 | } |
1a4d82fc JJ |
2038 | } |
2039 | ||
85aaf69f | 2040 | impl fmt::Debug for IntVarValue { |
1a4d82fc JJ |
2041 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
2042 | match *self { | |
2043 | IntType(ref v) => v.fmt(f), | |
2044 | UintType(ref v) => v.fmt(f), | |
2045 | } | |
223e47cc LB |
2046 | } |
2047 | } | |
2048 | ||
85aaf69f SL |
2049 | /// Default region to use for the bound of objects that are |
2050 | /// supplied as the value for this type parameter. This is derived | |
2051 | /// from `T:'a` annotations appearing in the type definition. If | |
2052 | /// this is `None`, then the default is inherited from the | |
2053 | /// surrounding context. See RFC #599 for details. | |
62682a34 | 2054 | #[derive(Copy, Clone)] |
85aaf69f SL |
2055 | pub enum ObjectLifetimeDefault { |
2056 | /// Require an explicit annotation. Occurs when multiple | |
2057 | /// `T:'a` constraints are found. | |
2058 | Ambiguous, | |
2059 | ||
62682a34 SL |
2060 | /// Use the base default, typically 'static, but in a fn body it is a fresh variable |
2061 | BaseDefault, | |
2062 | ||
85aaf69f SL |
2063 | /// Use the given region as the default. |
2064 | Specific(Region), | |
2065 | } | |
2066 | ||
62682a34 | 2067 | #[derive(Clone)] |
1a4d82fc JJ |
2068 | pub struct TypeParameterDef<'tcx> { |
2069 | pub name: ast::Name, | |
2070 | pub def_id: ast::DefId, | |
2071 | pub space: subst::ParamSpace, | |
2072 | pub index: u32, | |
1a4d82fc | 2073 | pub default: Option<Ty<'tcx>>, |
62682a34 | 2074 | pub object_lifetime_default: ObjectLifetimeDefault, |
223e47cc LB |
2075 | } |
2076 | ||
85aaf69f | 2077 | #[derive(RustcEncodable, RustcDecodable, Clone, Debug)] |
1a4d82fc JJ |
2078 | pub struct RegionParameterDef { |
2079 | pub name: ast::Name, | |
2080 | pub def_id: ast::DefId, | |
2081 | pub space: subst::ParamSpace, | |
2082 | pub index: u32, | |
2083 | pub bounds: Vec<ty::Region>, | |
2084 | } | |
223e47cc | 2085 | |
1a4d82fc JJ |
2086 | impl RegionParameterDef { |
2087 | pub fn to_early_bound_region(&self) -> ty::Region { | |
9346a6ac AL |
2088 | ty::ReEarlyBound(ty::EarlyBoundRegion { |
2089 | param_id: self.def_id.node, | |
2090 | space: self.space, | |
2091 | index: self.index, | |
2092 | name: self.name, | |
2093 | }) | |
223e47cc | 2094 | } |
c34b1796 AL |
2095 | pub fn to_bound_region(&self) -> ty::BoundRegion { |
2096 | ty::BoundRegion::BrNamed(self.def_id, self.name) | |
2097 | } | |
223e47cc LB |
2098 | } |
2099 | ||
1a4d82fc JJ |
2100 | /// Information about the formal type/lifetime parameters associated |
2101 | /// with an item or method. Analogous to ast::Generics. | |
85aaf69f | 2102 | #[derive(Clone, Debug)] |
1a4d82fc JJ |
2103 | pub struct Generics<'tcx> { |
2104 | pub types: VecPerParamSpace<TypeParameterDef<'tcx>>, | |
2105 | pub regions: VecPerParamSpace<RegionParameterDef>, | |
970d7e83 LB |
2106 | } |
2107 | ||
1a4d82fc JJ |
2108 | impl<'tcx> Generics<'tcx> { |
2109 | pub fn empty() -> Generics<'tcx> { | |
2110 | Generics { | |
2111 | types: VecPerParamSpace::empty(), | |
2112 | regions: VecPerParamSpace::empty(), | |
1a4d82fc | 2113 | } |
223e47cc LB |
2114 | } |
2115 | ||
85aaf69f SL |
2116 | pub fn is_empty(&self) -> bool { |
2117 | self.types.is_empty() && self.regions.is_empty() | |
2118 | } | |
2119 | ||
1a4d82fc JJ |
2120 | pub fn has_type_params(&self, space: subst::ParamSpace) -> bool { |
2121 | !self.types.is_empty_in(space) | |
223e47cc | 2122 | } |
223e47cc | 2123 | |
1a4d82fc JJ |
2124 | pub fn has_region_params(&self, space: subst::ParamSpace) -> bool { |
2125 | !self.regions.is_empty_in(space) | |
223e47cc | 2126 | } |
85aaf69f | 2127 | } |
223e47cc | 2128 | |
85aaf69f | 2129 | /// Bounds on generics. |
62682a34 | 2130 | #[derive(Clone)] |
85aaf69f SL |
2131 | pub struct GenericPredicates<'tcx> { |
2132 | pub predicates: VecPerParamSpace<Predicate<'tcx>>, | |
2133 | } | |
2134 | ||
2135 | impl<'tcx> GenericPredicates<'tcx> { | |
2136 | pub fn empty() -> GenericPredicates<'tcx> { | |
2137 | GenericPredicates { | |
2138 | predicates: VecPerParamSpace::empty(), | |
2139 | } | |
1a4d82fc JJ |
2140 | } |
2141 | ||
85aaf69f SL |
2142 | pub fn instantiate(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>) |
2143 | -> InstantiatedPredicates<'tcx> { | |
2144 | InstantiatedPredicates { | |
1a4d82fc | 2145 | predicates: self.predicates.subst(tcx, substs), |
223e47cc LB |
2146 | } |
2147 | } | |
c34b1796 AL |
2148 | |
2149 | pub fn instantiate_supertrait(&self, | |
2150 | tcx: &ty::ctxt<'tcx>, | |
2151 | poly_trait_ref: &ty::PolyTraitRef<'tcx>) | |
2152 | -> InstantiatedPredicates<'tcx> | |
2153 | { | |
2154 | InstantiatedPredicates { | |
2155 | predicates: self.predicates.map(|pred| pred.subst_supertrait(tcx, poly_trait_ref)) | |
2156 | } | |
2157 | } | |
223e47cc LB |
2158 | } |
2159 | ||
62682a34 | 2160 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
2161 | pub enum Predicate<'tcx> { |
2162 | /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be | |
2163 | /// the `Self` type of the trait reference and `A`, `B`, and `C` | |
2164 | /// would be the parameters in the `TypeSpace`. | |
2165 | Trait(PolyTraitPredicate<'tcx>), | |
2166 | ||
2167 | /// where `T1 == T2`. | |
2168 | Equate(PolyEquatePredicate<'tcx>), | |
2169 | ||
2170 | /// where 'a : 'b | |
2171 | RegionOutlives(PolyRegionOutlivesPredicate), | |
2172 | ||
2173 | /// where T : 'a | |
2174 | TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), | |
223e47cc | 2175 | |
1a4d82fc JJ |
2176 | /// where <T as TraitRef>::Name == X, approximately. |
2177 | /// See `ProjectionPredicate` struct for details. | |
2178 | Projection(PolyProjectionPredicate<'tcx>), | |
223e47cc LB |
2179 | } |
2180 | ||
c34b1796 | 2181 | impl<'tcx> Predicate<'tcx> { |
d9579d0f | 2182 | /// Performs a substitution suitable for going from a |
c34b1796 AL |
2183 | /// poly-trait-ref to supertraits that must hold if that |
2184 | /// poly-trait-ref holds. This is slightly different from a normal | |
2185 | /// substitution in terms of what happens with bound regions. See | |
2186 | /// lengthy comment below for details. | |
2187 | pub fn subst_supertrait(&self, | |
2188 | tcx: &ty::ctxt<'tcx>, | |
2189 | trait_ref: &ty::PolyTraitRef<'tcx>) | |
2190 | -> ty::Predicate<'tcx> | |
2191 | { | |
2192 | // The interaction between HRTB and supertraits is not entirely | |
2193 | // obvious. Let me walk you (and myself) through an example. | |
2194 | // | |
2195 | // Let's start with an easy case. Consider two traits: | |
2196 | // | |
2197 | // trait Foo<'a> : Bar<'a,'a> { } | |
2198 | // trait Bar<'b,'c> { } | |
2199 | // | |
2200 | // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then | |
2201 | // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we | |
2202 | // knew that `Foo<'x>` (for any 'x) then we also know that | |
2203 | // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from | |
2204 | // normal substitution. | |
2205 | // | |
2206 | // In terms of why this is sound, the idea is that whenever there | |
2207 | // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` | |
2208 | // holds. So if there is an impl of `T:Foo<'a>` that applies to | |
2209 | // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all | |
2210 | // `'a`. | |
2211 | // | |
2212 | // Another example to be careful of is this: | |
2213 | // | |
2214 | // trait Foo1<'a> : for<'b> Bar1<'a,'b> { } | |
2215 | // trait Bar1<'b,'c> { } | |
2216 | // | |
2217 | // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know? | |
2218 | // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The | |
2219 | // reason is similar to the previous example: any impl of | |
2220 | // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So | |
2221 | // basically we would want to collapse the bound lifetimes from | |
2222 | // the input (`trait_ref`) and the supertraits. | |
2223 | // | |
2224 | // To achieve this in practice is fairly straightforward. Let's | |
2225 | // consider the more complicated scenario: | |
2226 | // | |
2227 | // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x` | |
2228 | // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`, | |
2229 | // where both `'x` and `'b` would have a DB index of 1. | |
2230 | // The substitution from the input trait-ref is therefore going to be | |
2231 | // `'a => 'x` (where `'x` has a DB index of 1). | |
2232 | // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an | |
2233 | // early-bound parameter and `'b' is a late-bound parameter with a | |
2234 | // DB index of 1. | |
2235 | // - If we replace `'a` with `'x` from the input, it too will have | |
2236 | // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` | |
2237 | // just as we wanted. | |
2238 | // | |
2239 | // There is only one catch. If we just apply the substitution `'a | |
2240 | // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will | |
2241 | // adjust the DB index because we substituting into a binder (it | |
2242 | // tries to be so smart...) resulting in `for<'x> for<'b> | |
2243 | // Bar1<'x,'b>` (we have no syntax for this, so use your | |
2244 | // imagination). Basically the 'x will have DB index of 2 and 'b | |
2245 | // will have DB index of 1. Not quite what we want. So we apply | |
2246 | // the substitution to the *contents* of the trait reference, | |
2247 | // rather than the trait reference itself (put another way, the | |
2248 | // substitution code expects equal binding levels in the values | |
2249 | // from the substitution and the value being substituted into, and | |
2250 | // this trick achieves that). | |
2251 | ||
2252 | let substs = &trait_ref.0.substs; | |
2253 | match *self { | |
2254 | Predicate::Trait(ty::Binder(ref data)) => | |
2255 | Predicate::Trait(ty::Binder(data.subst(tcx, substs))), | |
2256 | Predicate::Equate(ty::Binder(ref data)) => | |
2257 | Predicate::Equate(ty::Binder(data.subst(tcx, substs))), | |
2258 | Predicate::RegionOutlives(ty::Binder(ref data)) => | |
2259 | Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))), | |
2260 | Predicate::TypeOutlives(ty::Binder(ref data)) => | |
2261 | Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))), | |
2262 | Predicate::Projection(ty::Binder(ref data)) => | |
2263 | Predicate::Projection(ty::Binder(data.subst(tcx, substs))), | |
2264 | } | |
2265 | } | |
62682a34 SL |
2266 | |
2267 | // Indicates whether this predicate references only 'global' | |
2268 | // types/lifetimes that are the same regardless of what fn we are | |
2269 | // in. This is used for caching. Errs on the side of returning | |
2270 | // false. | |
2271 | pub fn is_global(&self) -> bool { | |
2272 | match *self { | |
2273 | ty::Predicate::Trait(ref data) => { | |
2274 | let substs = data.skip_binder().trait_ref.substs; | |
2275 | ||
2276 | substs.types.iter().all(|t| ty::type_is_global(t)) && { | |
2277 | match substs.regions { | |
2278 | subst::ErasedRegions => true, | |
2279 | subst::NonerasedRegions(ref r) => r.iter().all(|r| r.is_global()), | |
2280 | } | |
2281 | } | |
2282 | } | |
2283 | ||
2284 | _ => { | |
2285 | false | |
2286 | } | |
2287 | } | |
2288 | } | |
c34b1796 AL |
2289 | } |
2290 | ||
62682a34 | 2291 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc | 2292 | pub struct TraitPredicate<'tcx> { |
d9579d0f | 2293 | pub trait_ref: TraitRef<'tcx> |
223e47cc | 2294 | } |
1a4d82fc | 2295 | pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>; |
223e47cc | 2296 | |
1a4d82fc JJ |
2297 | impl<'tcx> TraitPredicate<'tcx> { |
2298 | pub fn def_id(&self) -> ast::DefId { | |
2299 | self.trait_ref.def_id | |
2300 | } | |
223e47cc | 2301 | |
1a4d82fc JJ |
2302 | pub fn input_types(&self) -> &[Ty<'tcx>] { |
2303 | self.trait_ref.substs.types.as_slice() | |
2304 | } | |
223e47cc | 2305 | |
1a4d82fc JJ |
2306 | pub fn self_ty(&self) -> Ty<'tcx> { |
2307 | self.trait_ref.self_ty() | |
2308 | } | |
223e47cc LB |
2309 | } |
2310 | ||
1a4d82fc JJ |
2311 | impl<'tcx> PolyTraitPredicate<'tcx> { |
2312 | pub fn def_id(&self) -> ast::DefId { | |
2313 | self.0.def_id() | |
2314 | } | |
223e47cc LB |
2315 | } |
2316 | ||
85aaf69f | 2317 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
2318 | pub struct EquatePredicate<'tcx>(pub Ty<'tcx>, pub Ty<'tcx>); // `0 == 1` |
2319 | pub type PolyEquatePredicate<'tcx> = ty::Binder<EquatePredicate<'tcx>>; | |
970d7e83 | 2320 | |
85aaf69f | 2321 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
2322 | pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B` |
2323 | pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>; | |
2324 | pub type PolyRegionOutlivesPredicate = PolyOutlivesPredicate<ty::Region, ty::Region>; | |
2325 | pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region>; | |
970d7e83 | 2326 | |
1a4d82fc JJ |
2327 | /// This kind of predicate has no *direct* correspondent in the |
2328 | /// syntax, but it roughly corresponds to the syntactic forms: | |
2329 | /// | |
2330 | /// 1. `T : TraitRef<..., Item=Type>` | |
2331 | /// 2. `<T as TraitRef<...>>::Item == Type` (NYI) | |
2332 | /// | |
2333 | /// In particular, form #1 is "desugared" to the combination of a | |
2334 | /// normal trait predicate (`T : TraitRef<...>`) and one of these | |
2335 | /// predicates. Form #2 is a broader form in that it also permits | |
2336 | /// equality between arbitrary types. Processing an instance of Form | |
2337 | /// #2 eventually yields one of these `ProjectionPredicate` | |
2338 | /// instances to normalize the LHS. | |
62682a34 | 2339 | #[derive(Clone, PartialEq, Eq, Hash)] |
1a4d82fc JJ |
2340 | pub struct ProjectionPredicate<'tcx> { |
2341 | pub projection_ty: ProjectionTy<'tcx>, | |
2342 | pub ty: Ty<'tcx>, | |
223e47cc LB |
2343 | } |
2344 | ||
1a4d82fc | 2345 | pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>; |
223e47cc | 2346 | |
1a4d82fc JJ |
2347 | impl<'tcx> PolyProjectionPredicate<'tcx> { |
2348 | pub fn item_name(&self) -> ast::Name { | |
2349 | self.0.projection_ty.item_name // safe to skip the binder to access a name | |
970d7e83 | 2350 | } |
970d7e83 | 2351 | |
1a4d82fc JJ |
2352 | pub fn sort_key(&self) -> (ast::DefId, ast::Name) { |
2353 | self.0.projection_ty.sort_key() | |
223e47cc LB |
2354 | } |
2355 | } | |
2356 | ||
1a4d82fc JJ |
2357 | /// Represents the projection of an associated type. In explicit UFCS |
2358 | /// form this would be written `<T as Trait<..>>::N`. | |
85aaf69f | 2359 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] |
1a4d82fc JJ |
2360 | pub struct ProjectionTy<'tcx> { |
2361 | /// The trait reference `T as Trait<..>`. | |
d9579d0f | 2362 | pub trait_ref: ty::TraitRef<'tcx>, |
1a4d82fc JJ |
2363 | |
2364 | /// The name `N` of the associated type. | |
2365 | pub item_name: ast::Name, | |
223e47cc LB |
2366 | } |
2367 | ||
1a4d82fc JJ |
2368 | impl<'tcx> ProjectionTy<'tcx> { |
2369 | pub fn sort_key(&self) -> (ast::DefId, ast::Name) { | |
2370 | (self.trait_ref.def_id, self.item_name) | |
970d7e83 LB |
2371 | } |
2372 | } | |
2373 | ||
1a4d82fc JJ |
2374 | pub trait ToPolyTraitRef<'tcx> { |
2375 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; | |
223e47cc LB |
2376 | } |
2377 | ||
d9579d0f | 2378 | impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> { |
1a4d82fc JJ |
2379 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { |
2380 | assert!(!self.has_escaping_regions()); | |
2381 | ty::Binder(self.clone()) | |
970d7e83 LB |
2382 | } |
2383 | } | |
2384 | ||
1a4d82fc JJ |
2385 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { |
2386 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
c34b1796 | 2387 | self.map_bound_ref(|trait_pred| trait_pred.trait_ref.clone()) |
970d7e83 LB |
2388 | } |
2389 | } | |
2390 | ||
1a4d82fc JJ |
2391 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> { |
2392 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
2393 | // Note: unlike with TraitRef::to_poly_trait_ref(), | |
2394 | // self.0.trait_ref is permitted to have escaping regions. | |
2395 | // This is because here `self` has a `Binder` and so does our | |
2396 | // return value, so we are preserving the number of binding | |
2397 | // levels. | |
2398 | ty::Binder(self.0.projection_ty.trait_ref.clone()) | |
223e47cc LB |
2399 | } |
2400 | } | |
2401 | ||
1a4d82fc JJ |
2402 | pub trait AsPredicate<'tcx> { |
2403 | fn as_predicate(&self) -> Predicate<'tcx>; | |
223e47cc LB |
2404 | } |
2405 | ||
d9579d0f | 2406 | impl<'tcx> AsPredicate<'tcx> for TraitRef<'tcx> { |
1a4d82fc JJ |
2407 | fn as_predicate(&self) -> Predicate<'tcx> { |
2408 | // we're about to add a binder, so let's check that we don't | |
2409 | // accidentally capture anything, or else that might be some | |
2410 | // weird debruijn accounting. | |
2411 | assert!(!self.has_escaping_regions()); | |
2412 | ||
2413 | ty::Predicate::Trait(ty::Binder(ty::TraitPredicate { | |
2414 | trait_ref: self.clone() | |
2415 | })) | |
223e47cc LB |
2416 | } |
2417 | } | |
2418 | ||
1a4d82fc JJ |
2419 | impl<'tcx> AsPredicate<'tcx> for PolyTraitRef<'tcx> { |
2420 | fn as_predicate(&self) -> Predicate<'tcx> { | |
2421 | ty::Predicate::Trait(self.to_poly_trait_predicate()) | |
223e47cc LB |
2422 | } |
2423 | } | |
2424 | ||
1a4d82fc JJ |
2425 | impl<'tcx> AsPredicate<'tcx> for PolyEquatePredicate<'tcx> { |
2426 | fn as_predicate(&self) -> Predicate<'tcx> { | |
2427 | Predicate::Equate(self.clone()) | |
223e47cc LB |
2428 | } |
2429 | } | |
2430 | ||
1a4d82fc JJ |
2431 | impl<'tcx> AsPredicate<'tcx> for PolyRegionOutlivesPredicate { |
2432 | fn as_predicate(&self) -> Predicate<'tcx> { | |
2433 | Predicate::RegionOutlives(self.clone()) | |
223e47cc LB |
2434 | } |
2435 | } | |
2436 | ||
1a4d82fc JJ |
2437 | impl<'tcx> AsPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { |
2438 | fn as_predicate(&self) -> Predicate<'tcx> { | |
2439 | Predicate::TypeOutlives(self.clone()) | |
223e47cc LB |
2440 | } |
2441 | } | |
2442 | ||
1a4d82fc JJ |
2443 | impl<'tcx> AsPredicate<'tcx> for PolyProjectionPredicate<'tcx> { |
2444 | fn as_predicate(&self) -> Predicate<'tcx> { | |
2445 | Predicate::Projection(self.clone()) | |
223e47cc LB |
2446 | } |
2447 | } | |
2448 | ||
1a4d82fc | 2449 | impl<'tcx> Predicate<'tcx> { |
85aaf69f SL |
2450 | /// Iterates over the types in this predicate. Note that in all |
2451 | /// cases this is skipping over a binder, so late-bound regions | |
2452 | /// with depth 0 are bound by the predicate. | |
2453 | pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> { | |
2454 | let vec: Vec<_> = match *self { | |
2455 | ty::Predicate::Trait(ref data) => { | |
2456 | data.0.trait_ref.substs.types.as_slice().to_vec() | |
2457 | } | |
2458 | ty::Predicate::Equate(ty::Binder(ref data)) => { | |
2459 | vec![data.0, data.1] | |
2460 | } | |
2461 | ty::Predicate::TypeOutlives(ty::Binder(ref data)) => { | |
2462 | vec![data.0] | |
2463 | } | |
2464 | ty::Predicate::RegionOutlives(..) => { | |
2465 | vec![] | |
2466 | } | |
2467 | ty::Predicate::Projection(ref data) => { | |
2468 | let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice(); | |
2469 | trait_inputs.iter() | |
2470 | .cloned() | |
62682a34 | 2471 | .chain(Some(data.0.ty)) |
85aaf69f SL |
2472 | .collect() |
2473 | } | |
2474 | }; | |
2475 | ||
2476 | // The only reason to collect into a vector here is that I was | |
2477 | // too lazy to make the full (somewhat complicated) iterator | |
2478 | // type that would be needed here. But I wanted this fn to | |
2479 | // return an iterator conceptually, rather than a `Vec`, so as | |
2480 | // to be closer to `Ty::walk`. | |
2481 | vec.into_iter() | |
2482 | } | |
2483 | ||
1a4d82fc JJ |
2484 | pub fn has_escaping_regions(&self) -> bool { |
2485 | match *self { | |
2486 | Predicate::Trait(ref trait_ref) => trait_ref.has_escaping_regions(), | |
2487 | Predicate::Equate(ref p) => p.has_escaping_regions(), | |
2488 | Predicate::RegionOutlives(ref p) => p.has_escaping_regions(), | |
2489 | Predicate::TypeOutlives(ref p) => p.has_escaping_regions(), | |
2490 | Predicate::Projection(ref p) => p.has_escaping_regions(), | |
2491 | } | |
223e47cc | 2492 | } |
223e47cc | 2493 | |
1a4d82fc JJ |
2494 | pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> { |
2495 | match *self { | |
2496 | Predicate::Trait(ref t) => { | |
2497 | Some(t.to_poly_trait_ref()) | |
2498 | } | |
2499 | Predicate::Projection(..) | | |
2500 | Predicate::Equate(..) | | |
2501 | Predicate::RegionOutlives(..) | | |
2502 | Predicate::TypeOutlives(..) => { | |
2503 | None | |
2504 | } | |
2505 | } | |
223e47cc LB |
2506 | } |
2507 | } | |
2508 | ||
1a4d82fc JJ |
2509 | /// Represents the bounds declared on a particular set of type |
2510 | /// parameters. Should eventually be generalized into a flag list of | |
85aaf69f SL |
2511 | /// where clauses. You can obtain a `InstantiatedPredicates` list from a |
2512 | /// `GenericPredicates` by using the `instantiate` method. Note that this method | |
2513 | /// reflects an important semantic invariant of `InstantiatedPredicates`: while | |
2514 | /// the `GenericPredicates` are expressed in terms of the bound type | |
2515 | /// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance | |
1a4d82fc JJ |
2516 | /// represented a set of bounds for some particular instantiation, |
2517 | /// meaning that the generic parameters have been substituted with | |
2518 | /// their values. | |
2519 | /// | |
2520 | /// Example: | |
2521 | /// | |
2522 | /// struct Foo<T,U:Bar<T>> { ... } | |
2523 | /// | |
85aaf69f | 2524 | /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like |
1a4d82fc | 2525 | /// `[[], [U:Bar<T>]]`. Now if there were some particular reference |
c34b1796 AL |
2526 | /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], |
2527 | /// [usize:Bar<isize>]]`. | |
62682a34 | 2528 | #[derive(Clone)] |
85aaf69f | 2529 | pub struct InstantiatedPredicates<'tcx> { |
1a4d82fc | 2530 | pub predicates: VecPerParamSpace<Predicate<'tcx>>, |
223e47cc LB |
2531 | } |
2532 | ||
85aaf69f SL |
2533 | impl<'tcx> InstantiatedPredicates<'tcx> { |
2534 | pub fn empty() -> InstantiatedPredicates<'tcx> { | |
2535 | InstantiatedPredicates { predicates: VecPerParamSpace::empty() } | |
223e47cc LB |
2536 | } |
2537 | ||
1a4d82fc JJ |
2538 | pub fn has_escaping_regions(&self) -> bool { |
2539 | self.predicates.any(|p| p.has_escaping_regions()) | |
223e47cc LB |
2540 | } |
2541 | ||
1a4d82fc JJ |
2542 | pub fn is_empty(&self) -> bool { |
2543 | self.predicates.is_empty() | |
223e47cc | 2544 | } |
223e47cc LB |
2545 | } |
2546 | ||
1a4d82fc JJ |
2547 | impl<'tcx> TraitRef<'tcx> { |
2548 | pub fn new(def_id: ast::DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { | |
2549 | TraitRef { def_id: def_id, substs: substs } | |
970d7e83 LB |
2550 | } |
2551 | ||
1a4d82fc JJ |
2552 | pub fn self_ty(&self) -> Ty<'tcx> { |
2553 | self.substs.self_ty().unwrap() | |
970d7e83 LB |
2554 | } |
2555 | ||
1a4d82fc JJ |
2556 | pub fn input_types(&self) -> &[Ty<'tcx>] { |
2557 | // Select only the "input types" from a trait-reference. For | |
2558 | // now this is all the types that appear in the | |
2559 | // trait-reference, but it should eventually exclude | |
2560 | // associated types. | |
2561 | self.substs.types.as_slice() | |
223e47cc | 2562 | } |
1a4d82fc | 2563 | } |
223e47cc | 2564 | |
1a4d82fc JJ |
2565 | /// When type checking, we use the `ParameterEnvironment` to track |
2566 | /// details about the type/lifetime parameters that are in scope. | |
2567 | /// It primarily stores the bounds information. | |
2568 | /// | |
2569 | /// Note: This information might seem to be redundant with the data in | |
2570 | /// `tcx.ty_param_defs`, but it is not. That table contains the | |
2571 | /// parameter definitions from an "outside" perspective, but this | |
2572 | /// struct will contain the bounds for a parameter as seen from inside | |
2573 | /// the function body. Currently the only real distinction is that | |
2574 | /// bound lifetime parameters are replaced with free ones, but in the | |
2575 | /// future I hope to refine the representation of types so as to make | |
2576 | /// more distinctions clearer. | |
2577 | #[derive(Clone)] | |
2578 | pub struct ParameterEnvironment<'a, 'tcx:'a> { | |
2579 | pub tcx: &'a ctxt<'tcx>, | |
2580 | ||
85aaf69f | 2581 | /// See `construct_free_substs` for details. |
1a4d82fc JJ |
2582 | pub free_substs: Substs<'tcx>, |
2583 | ||
2584 | /// Each type parameter has an implicit region bound that | |
2585 | /// indicates it must outlive at least the function body (the user | |
2586 | /// may specify stronger requirements). This field indicates the | |
2587 | /// region of the callee. | |
2588 | pub implicit_region_bound: ty::Region, | |
2589 | ||
2590 | /// Obligations that the caller must satisfy. This is basically | |
2591 | /// the set of bounds on the in-scope type parameters, translated | |
62682a34 | 2592 | /// into Obligations, and elaborated and normalized. |
85aaf69f | 2593 | pub caller_bounds: Vec<ty::Predicate<'tcx>>, |
1a4d82fc JJ |
2594 | |
2595 | /// Caches the results of trait selection. This cache is used | |
2596 | /// for things that have to do with the parameters in scope. | |
2597 | pub selection_cache: traits::SelectionCache<'tcx>, | |
2598 | } | |
2599 | ||
2600 | impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { | |
85aaf69f SL |
2601 | pub fn with_caller_bounds(&self, |
2602 | caller_bounds: Vec<ty::Predicate<'tcx>>) | |
2603 | -> ParameterEnvironment<'a,'tcx> | |
2604 | { | |
2605 | ParameterEnvironment { | |
2606 | tcx: self.tcx, | |
2607 | free_substs: self.free_substs.clone(), | |
2608 | implicit_region_bound: self.implicit_region_bound, | |
2609 | caller_bounds: caller_bounds, | |
2610 | selection_cache: traits::SelectionCache::new(), | |
2611 | } | |
2612 | } | |
2613 | ||
1a4d82fc JJ |
2614 | pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx> { |
2615 | match cx.map.find(id) { | |
2616 | Some(ast_map::NodeImplItem(ref impl_item)) => { | |
c34b1796 | 2617 | match impl_item.node { |
d9579d0f AL |
2618 | ast::ConstImplItem(_, _) => { |
2619 | let def_id = ast_util::local_def(id); | |
2620 | let scheme = lookup_item_type(cx, def_id); | |
2621 | let predicates = lookup_predicates(cx, def_id); | |
2622 | construct_parameter_environment(cx, | |
2623 | impl_item.span, | |
2624 | &scheme.generics, | |
2625 | &predicates, | |
2626 | id) | |
2627 | } | |
c34b1796 | 2628 | ast::MethodImplItem(_, ref body) => { |
1a4d82fc JJ |
2629 | let method_def_id = ast_util::local_def(id); |
2630 | match ty::impl_or_trait_item(cx, method_def_id) { | |
2631 | MethodTraitItem(ref method_ty) => { | |
2632 | let method_generics = &method_ty.generics; | |
85aaf69f | 2633 | let method_bounds = &method_ty.predicates; |
1a4d82fc JJ |
2634 | construct_parameter_environment( |
2635 | cx, | |
c34b1796 | 2636 | impl_item.span, |
1a4d82fc | 2637 | method_generics, |
85aaf69f | 2638 | method_bounds, |
c34b1796 | 2639 | body.id) |
1a4d82fc | 2640 | } |
d9579d0f | 2641 | _ => { |
1a4d82fc JJ |
2642 | cx.sess |
2643 | .bug("ParameterEnvironment::for_item(): \ | |
d9579d0f | 2644 | got non-method item from impl method?!") |
1a4d82fc JJ |
2645 | } |
2646 | } | |
2647 | } | |
2648 | ast::TypeImplItem(_) => { | |
2649 | cx.sess.bug("ParameterEnvironment::for_item(): \ | |
2650 | can't create a parameter environment \ | |
2651 | for type impl items") | |
2652 | } | |
c34b1796 | 2653 | ast::MacImplItem(_) => cx.sess.bug("unexpanded macro") |
1a4d82fc JJ |
2654 | } |
2655 | } | |
c34b1796 AL |
2656 | Some(ast_map::NodeTraitItem(trait_item)) => { |
2657 | match trait_item.node { | |
d9579d0f AL |
2658 | ast::ConstTraitItem(_, ref default) => { |
2659 | match *default { | |
2660 | Some(_) => { | |
2661 | let def_id = ast_util::local_def(id); | |
2662 | let scheme = lookup_item_type(cx, def_id); | |
2663 | let predicates = lookup_predicates(cx, def_id); | |
2664 | construct_parameter_environment(cx, | |
2665 | trait_item.span, | |
2666 | &scheme.generics, | |
2667 | &predicates, | |
2668 | id) | |
2669 | } | |
2670 | None => { | |
2671 | cx.sess.bug("ParameterEnvironment::from_item(): \ | |
2672 | can't create a parameter environment \ | |
2673 | for const trait items without defaults") | |
2674 | } | |
2675 | } | |
2676 | } | |
c34b1796 AL |
2677 | ast::MethodTraitItem(_, None) => { |
2678 | cx.sess.span_bug(trait_item.span, | |
1a4d82fc JJ |
2679 | "ParameterEnvironment::for_item(): |
2680 | can't create a parameter \ | |
2681 | environment for required trait \ | |
2682 | methods") | |
2683 | } | |
c34b1796 | 2684 | ast::MethodTraitItem(_, Some(ref body)) => { |
1a4d82fc JJ |
2685 | let method_def_id = ast_util::local_def(id); |
2686 | match ty::impl_or_trait_item(cx, method_def_id) { | |
2687 | MethodTraitItem(ref method_ty) => { | |
2688 | let method_generics = &method_ty.generics; | |
85aaf69f | 2689 | let method_bounds = &method_ty.predicates; |
1a4d82fc JJ |
2690 | construct_parameter_environment( |
2691 | cx, | |
c34b1796 | 2692 | trait_item.span, |
1a4d82fc | 2693 | method_generics, |
85aaf69f | 2694 | method_bounds, |
c34b1796 | 2695 | body.id) |
1a4d82fc | 2696 | } |
d9579d0f | 2697 | _ => { |
1a4d82fc JJ |
2698 | cx.sess |
2699 | .bug("ParameterEnvironment::for_item(): \ | |
d9579d0f AL |
2700 | got non-method item from provided \ |
2701 | method?!") | |
1a4d82fc JJ |
2702 | } |
2703 | } | |
2704 | } | |
c34b1796 | 2705 | ast::TypeTraitItem(..) => { |
1a4d82fc JJ |
2706 | cx.sess.bug("ParameterEnvironment::from_item(): \ |
2707 | can't create a parameter environment \ | |
2708 | for type trait items") | |
2709 | } | |
2710 | } | |
2711 | } | |
2712 | Some(ast_map::NodeItem(item)) => { | |
2713 | match item.node { | |
62682a34 | 2714 | ast::ItemFn(_, _, _, _, _, ref body) => { |
1a4d82fc JJ |
2715 | // We assume this is a function. |
2716 | let fn_def_id = ast_util::local_def(id); | |
85aaf69f SL |
2717 | let fn_scheme = lookup_item_type(cx, fn_def_id); |
2718 | let fn_predicates = lookup_predicates(cx, fn_def_id); | |
1a4d82fc JJ |
2719 | |
2720 | construct_parameter_environment(cx, | |
85aaf69f SL |
2721 | item.span, |
2722 | &fn_scheme.generics, | |
2723 | &fn_predicates, | |
1a4d82fc JJ |
2724 | body.id) |
2725 | } | |
2726 | ast::ItemEnum(..) | | |
2727 | ast::ItemStruct(..) | | |
2728 | ast::ItemImpl(..) | | |
2729 | ast::ItemConst(..) | | |
2730 | ast::ItemStatic(..) => { | |
2731 | let def_id = ast_util::local_def(id); | |
85aaf69f SL |
2732 | let scheme = lookup_item_type(cx, def_id); |
2733 | let predicates = lookup_predicates(cx, def_id); | |
2734 | construct_parameter_environment(cx, | |
2735 | item.span, | |
2736 | &scheme.generics, | |
2737 | &predicates, | |
2738 | id) | |
1a4d82fc JJ |
2739 | } |
2740 | _ => { | |
2741 | cx.sess.span_bug(item.span, | |
2742 | "ParameterEnvironment::from_item(): | |
2743 | can't create a parameter \ | |
2744 | environment for this kind of item") | |
2745 | } | |
2746 | } | |
2747 | } | |
2748 | Some(ast_map::NodeExpr(..)) => { | |
2749 | // This is a convenience to allow closures to work. | |
2750 | ParameterEnvironment::for_item(cx, cx.map.get_parent(id)) | |
2751 | } | |
2752 | _ => { | |
2753 | cx.sess.bug(&format!("ParameterEnvironment::from_item(): \ | |
2754 | `{}` is not an item", | |
c34b1796 | 2755 | cx.map.node_to_string(id))) |
1a4d82fc JJ |
2756 | } |
2757 | } | |
223e47cc | 2758 | } |
1a4d82fc | 2759 | } |
223e47cc | 2760 | |
1a4d82fc JJ |
2761 | /// A "type scheme", in ML terminology, is a type combined with some |
2762 | /// set of generic types that the type is, well, generic over. In Rust | |
2763 | /// terms, it is the "type" of a fn item or struct -- this type will | |
2764 | /// include various generic parameters that must be substituted when | |
2765 | /// the item/struct is referenced. That is called converting the type | |
2766 | /// scheme to a monotype. | |
2767 | /// | |
2768 | /// - `generics`: the set of type parameters and their bounds | |
2769 | /// - `ty`: the base types, which may reference the parameters defined | |
2770 | /// in `generics` | |
2771 | /// | |
2772 | /// Note that TypeSchemes are also sometimes called "polytypes" (and | |
2773 | /// in fact this struct used to carry that name, so you may find some | |
2774 | /// stray references in a comment or something). We try to reserve the | |
2775 | /// "poly" prefix to refer to higher-ranked things, as in | |
2776 | /// `PolyTraitRef`. | |
85aaf69f SL |
2777 | /// |
2778 | /// Note that each item also comes with predicates, see | |
2779 | /// `lookup_predicates`. | |
2780 | #[derive(Clone, Debug)] | |
1a4d82fc JJ |
2781 | pub struct TypeScheme<'tcx> { |
2782 | pub generics: Generics<'tcx>, | |
85aaf69f | 2783 | pub ty: Ty<'tcx>, |
1a4d82fc JJ |
2784 | } |
2785 | ||
d9579d0f AL |
2786 | bitflags! { |
2787 | flags TraitFlags: u32 { | |
2788 | const NO_TRAIT_FLAGS = 0, | |
2789 | const HAS_DEFAULT_IMPL = 1 << 0, | |
2790 | const IS_OBJECT_SAFE = 1 << 1, | |
2791 | const OBJECT_SAFETY_VALID = 1 << 2, | |
2792 | const IMPLS_VALID = 1 << 3, | |
2793 | } | |
2794 | } | |
2795 | ||
1a4d82fc JJ |
2796 | /// As `TypeScheme` but for a trait ref. |
2797 | pub struct TraitDef<'tcx> { | |
2798 | pub unsafety: ast::Unsafety, | |
2799 | ||
85aaf69f SL |
2800 | /// If `true`, then this trait had the `#[rustc_paren_sugar]` |
2801 | /// attribute, indicating that it should be used with `Foo()` | |
2802 | /// sugar. This is a temporary thing -- eventually any trait wil | |
2803 | /// be usable with the sugar (or without it). | |
2804 | pub paren_sugar: bool, | |
2805 | ||
1a4d82fc JJ |
2806 | /// Generic type definitions. Note that `Self` is listed in here |
2807 | /// as having a single bound, the trait itself (e.g., in the trait | |
2808 | /// `Eq`, there is a single bound `Self : Eq`). This is so that | |
2809 | /// default methods get to assume that the `Self` parameters | |
2810 | /// implements the trait. | |
2811 | pub generics: Generics<'tcx>, | |
2812 | ||
d9579d0f | 2813 | pub trait_ref: TraitRef<'tcx>, |
1a4d82fc JJ |
2814 | |
2815 | /// A list of the associated types defined in this trait. Useful | |
2816 | /// for resolving `X::Foo` type markers. | |
2817 | pub associated_type_names: Vec<ast::Name>, | |
d9579d0f AL |
2818 | |
2819 | // Impls of this trait. To allow for quicker lookup, the impls are indexed | |
2820 | // by a simplified version of their Self type: impls with a simplifiable | |
2821 | // Self are stored in nonblanket_impls keyed by it, while all other impls | |
2822 | // are stored in blanket_impls. | |
2823 | ||
2824 | /// Impls of the trait. | |
2825 | pub nonblanket_impls: RefCell< | |
2826 | FnvHashMap<fast_reject::SimplifiedType, Vec<DefId>> | |
2827 | >, | |
2828 | ||
2829 | /// Blanket impls associated with the trait. | |
2830 | pub blanket_impls: RefCell<Vec<DefId>>, | |
2831 | ||
2832 | /// Various flags | |
2833 | pub flags: Cell<TraitFlags> | |
2834 | } | |
2835 | ||
2836 | impl<'tcx> TraitDef<'tcx> { | |
2837 | // returns None if not yet calculated | |
2838 | pub fn object_safety(&self) -> Option<bool> { | |
2839 | if self.flags.get().intersects(TraitFlags::OBJECT_SAFETY_VALID) { | |
2840 | Some(self.flags.get().intersects(TraitFlags::IS_OBJECT_SAFE)) | |
2841 | } else { | |
2842 | None | |
2843 | } | |
2844 | } | |
2845 | ||
2846 | pub fn set_object_safety(&self, is_safe: bool) { | |
2847 | assert!(self.object_safety().map(|cs| cs == is_safe).unwrap_or(true)); | |
2848 | self.flags.set( | |
2849 | self.flags.get() | if is_safe { | |
2850 | TraitFlags::OBJECT_SAFETY_VALID | TraitFlags::IS_OBJECT_SAFE | |
2851 | } else { | |
2852 | TraitFlags::OBJECT_SAFETY_VALID | |
2853 | } | |
2854 | ); | |
2855 | } | |
2856 | ||
2857 | /// Records a trait-to-implementation mapping. | |
2858 | pub fn record_impl(&self, | |
2859 | tcx: &ctxt<'tcx>, | |
2860 | impl_def_id: DefId, | |
2861 | impl_trait_ref: TraitRef<'tcx>) { | |
62682a34 SL |
2862 | debug!("TraitDef::record_impl for {:?}, from {:?}", |
2863 | self, impl_trait_ref); | |
d9579d0f AL |
2864 | |
2865 | // We don't want to borrow_mut after we already populated all impls, | |
2866 | // so check if an impl is present with an immutable borrow first. | |
2867 | if let Some(sty) = fast_reject::simplify_type(tcx, | |
2868 | impl_trait_ref.self_ty(), false) { | |
2869 | if let Some(is) = self.nonblanket_impls.borrow().get(&sty) { | |
2870 | if is.contains(&impl_def_id) { | |
2871 | return // duplicate - skip | |
2872 | } | |
2873 | } | |
2874 | ||
2875 | self.nonblanket_impls.borrow_mut().entry(sty).or_insert(vec![]).push(impl_def_id) | |
2876 | } else { | |
2877 | if self.blanket_impls.borrow().contains(&impl_def_id) { | |
2878 | return // duplicate - skip | |
2879 | } | |
2880 | self.blanket_impls.borrow_mut().push(impl_def_id) | |
2881 | } | |
2882 | } | |
2883 | ||
2884 | ||
2885 | pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: &ctxt<'tcx>, mut f: F) { | |
2886 | ty::populate_implementations_for_trait_if_necessary(tcx, self.trait_ref.def_id); | |
2887 | ||
2888 | for &impl_def_id in self.blanket_impls.borrow().iter() { | |
2889 | f(impl_def_id); | |
2890 | } | |
2891 | ||
2892 | for v in self.nonblanket_impls.borrow().values() { | |
2893 | for &impl_def_id in v { | |
2894 | f(impl_def_id); | |
2895 | } | |
2896 | } | |
2897 | } | |
2898 | ||
2899 | pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self, | |
2900 | tcx: &ctxt<'tcx>, | |
2901 | self_ty: Ty<'tcx>, | |
2902 | mut f: F) | |
2903 | { | |
2904 | ty::populate_implementations_for_trait_if_necessary(tcx, self.trait_ref.def_id); | |
2905 | ||
2906 | for &impl_def_id in self.blanket_impls.borrow().iter() { | |
2907 | f(impl_def_id); | |
2908 | } | |
2909 | ||
2910 | if let Some(simp) = fast_reject::simplify_type(tcx, self_ty, false) { | |
2911 | if let Some(impls) = self.nonblanket_impls.borrow().get(&simp) { | |
2912 | for &impl_def_id in impls { | |
2913 | f(impl_def_id); | |
2914 | } | |
2915 | return; // we don't need to process the other non-blanket impls | |
2916 | } | |
2917 | } | |
2918 | ||
2919 | for v in self.nonblanket_impls.borrow().values() { | |
2920 | for &impl_def_id in v { | |
2921 | f(impl_def_id); | |
2922 | } | |
2923 | } | |
2924 | } | |
2925 | ||
1a4d82fc JJ |
2926 | } |
2927 | ||
2928 | /// Records the substitutions used to translate the polytype for an | |
2929 | /// item into the monotype of an item reference. | |
2930 | #[derive(Clone)] | |
2931 | pub struct ItemSubsts<'tcx> { | |
2932 | pub substs: Substs<'tcx>, | |
2933 | } | |
2934 | ||
c34b1796 | 2935 | #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)] |
85aaf69f | 2936 | pub enum ClosureKind { |
c34b1796 AL |
2937 | // Warning: Ordering is significant here! The ordering is chosen |
2938 | // because the trait Fn is a subtrait of FnMut and so in turn, and | |
2939 | // hence we order it so that Fn < FnMut < FnOnce. | |
85aaf69f SL |
2940 | FnClosureKind, |
2941 | FnMutClosureKind, | |
2942 | FnOnceClosureKind, | |
1a4d82fc JJ |
2943 | } |
2944 | ||
85aaf69f | 2945 | impl ClosureKind { |
1a4d82fc JJ |
2946 | pub fn trait_did(&self, cx: &ctxt) -> ast::DefId { |
2947 | let result = match *self { | |
85aaf69f SL |
2948 | FnClosureKind => cx.lang_items.require(FnTraitLangItem), |
2949 | FnMutClosureKind => { | |
1a4d82fc JJ |
2950 | cx.lang_items.require(FnMutTraitLangItem) |
2951 | } | |
85aaf69f | 2952 | FnOnceClosureKind => { |
1a4d82fc JJ |
2953 | cx.lang_items.require(FnOnceTraitLangItem) |
2954 | } | |
2955 | }; | |
2956 | match result { | |
2957 | Ok(trait_did) => trait_did, | |
85aaf69f | 2958 | Err(err) => cx.sess.fatal(&err[..]), |
1a4d82fc | 2959 | } |
223e47cc | 2960 | } |
c34b1796 AL |
2961 | |
2962 | /// True if this a type that impls this closure kind | |
2963 | /// must also implement `other`. | |
2964 | pub fn extends(self, other: ty::ClosureKind) -> bool { | |
2965 | match (self, other) { | |
2966 | (FnClosureKind, FnClosureKind) => true, | |
2967 | (FnClosureKind, FnMutClosureKind) => true, | |
2968 | (FnClosureKind, FnOnceClosureKind) => true, | |
2969 | (FnMutClosureKind, FnMutClosureKind) => true, | |
2970 | (FnMutClosureKind, FnOnceClosureKind) => true, | |
2971 | (FnOnceClosureKind, FnOnceClosureKind) => true, | |
2972 | _ => false, | |
2973 | } | |
2974 | } | |
1a4d82fc | 2975 | } |
223e47cc | 2976 | |
85aaf69f SL |
2977 | pub trait ClosureTyper<'tcx> { |
2978 | fn tcx(&self) -> &ty::ctxt<'tcx> { | |
2979 | self.param_env().tcx | |
2980 | } | |
2981 | ||
1a4d82fc | 2982 | fn param_env<'a>(&'a self) -> &'a ty::ParameterEnvironment<'a, 'tcx>; |
223e47cc | 2983 | |
85aaf69f SL |
2984 | /// Is this a `Fn`, `FnMut` or `FnOnce` closure? During typeck, |
2985 | /// returns `None` if the kind of this closure has not yet been | |
2986 | /// inferred. | |
2987 | fn closure_kind(&self, | |
2988 | def_id: ast::DefId) | |
2989 | -> Option<ty::ClosureKind>; | |
223e47cc | 2990 | |
85aaf69f SL |
2991 | /// Returns the argument/return types of this closure. |
2992 | fn closure_type(&self, | |
2993 | def_id: ast::DefId, | |
2994 | substs: &subst::Substs<'tcx>) | |
2995 | -> ty::ClosureTy<'tcx>; | |
223e47cc | 2996 | |
85aaf69f SL |
2997 | /// Returns the set of all upvars and their transformed |
2998 | /// types. During typeck, maybe return `None` if the upvar types | |
2999 | /// have not yet been inferred. | |
3000 | fn closure_upvars(&self, | |
3001 | def_id: ast::DefId, | |
3002 | substs: &Substs<'tcx>) | |
3003 | -> Option<Vec<ClosureUpvar<'tcx>>>; | |
1a4d82fc | 3004 | } |
223e47cc | 3005 | |
1a4d82fc JJ |
3006 | impl<'tcx> CommonTypes<'tcx> { |
3007 | fn new(arena: &'tcx TypedArena<TyS<'tcx>>, | |
3008 | interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>) | |
3009 | -> CommonTypes<'tcx> | |
3010 | { | |
3011 | CommonTypes { | |
62682a34 SL |
3012 | bool: intern_ty(arena, interner, TyBool), |
3013 | char: intern_ty(arena, interner, TyChar), | |
3014 | err: intern_ty(arena, interner, TyError), | |
3015 | isize: intern_ty(arena, interner, TyInt(ast::TyIs)), | |
3016 | i8: intern_ty(arena, interner, TyInt(ast::TyI8)), | |
3017 | i16: intern_ty(arena, interner, TyInt(ast::TyI16)), | |
3018 | i32: intern_ty(arena, interner, TyInt(ast::TyI32)), | |
3019 | i64: intern_ty(arena, interner, TyInt(ast::TyI64)), | |
3020 | usize: intern_ty(arena, interner, TyUint(ast::TyUs)), | |
3021 | u8: intern_ty(arena, interner, TyUint(ast::TyU8)), | |
3022 | u16: intern_ty(arena, interner, TyUint(ast::TyU16)), | |
3023 | u32: intern_ty(arena, interner, TyUint(ast::TyU32)), | |
3024 | u64: intern_ty(arena, interner, TyUint(ast::TyU64)), | |
3025 | f32: intern_ty(arena, interner, TyFloat(ast::TyF32)), | |
3026 | f64: intern_ty(arena, interner, TyFloat(ast::TyF64)), | |
3027 | } | |
3028 | } | |
3029 | } | |
3030 | ||
3031 | /// Create a type context and call the closure with a `&ty::ctxt` reference | |
3032 | /// to the context. The closure enforces that the type context and any interned | |
3033 | /// value (types, substs, etc.) can only be used while `ty::tls` has a valid | |
3034 | /// reference to the context, to allow formatting values that need it. | |
3035 | pub fn with_ctxt<'tcx, F, R>(s: Session, | |
3036 | arenas: &'tcx CtxtArenas<'tcx>, | |
3037 | def_map: DefMap, | |
3038 | named_region_map: resolve_lifetime::NamedRegionMap, | |
3039 | map: ast_map::Map<'tcx>, | |
3040 | freevars: RefCell<FreevarMap>, | |
3041 | region_maps: RegionMaps, | |
3042 | lang_items: middle::lang_items::LanguageItems, | |
3043 | stability: stability::Index<'tcx>, | |
3044 | f: F) -> (Session, R) | |
3045 | where F: FnOnce(&ctxt<'tcx>) -> R | |
1a4d82fc | 3046 | { |
85aaf69f | 3047 | let mut interner = FnvHashMap(); |
1a4d82fc JJ |
3048 | let common_types = CommonTypes::new(&arenas.type_, &mut interner); |
3049 | ||
62682a34 | 3050 | tls::enter(ctxt { |
1a4d82fc JJ |
3051 | arenas: arenas, |
3052 | interner: RefCell::new(interner), | |
85aaf69f SL |
3053 | substs_interner: RefCell::new(FnvHashMap()), |
3054 | bare_fn_interner: RefCell::new(FnvHashMap()), | |
3055 | region_interner: RefCell::new(FnvHashMap()), | |
62682a34 | 3056 | stability_interner: RefCell::new(FnvHashMap()), |
1a4d82fc JJ |
3057 | types: common_types, |
3058 | named_region_map: named_region_map, | |
bd371182 AL |
3059 | region_maps: region_maps, |
3060 | free_region_maps: RefCell::new(FnvHashMap()), | |
85aaf69f | 3061 | item_variance_map: RefCell::new(DefIdMap()), |
1a4d82fc JJ |
3062 | variance_computed: Cell::new(false), |
3063 | sess: s, | |
c34b1796 | 3064 | def_map: def_map, |
85aaf69f SL |
3065 | node_types: RefCell::new(FnvHashMap()), |
3066 | item_substs: RefCell::new(NodeMap()), | |
62682a34 | 3067 | impl_trait_refs: RefCell::new(DefIdMap()), |
85aaf69f SL |
3068 | trait_defs: RefCell::new(DefIdMap()), |
3069 | predicates: RefCell::new(DefIdMap()), | |
c34b1796 | 3070 | super_predicates: RefCell::new(DefIdMap()), |
62682a34 | 3071 | fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()), |
1a4d82fc | 3072 | map: map, |
1a4d82fc | 3073 | freevars: freevars, |
85aaf69f SL |
3074 | tcache: RefCell::new(DefIdMap()), |
3075 | rcache: RefCell::new(FnvHashMap()), | |
85aaf69f SL |
3076 | tc_cache: RefCell::new(FnvHashMap()), |
3077 | ast_ty_to_ty_cache: RefCell::new(NodeMap()), | |
3078 | enum_var_cache: RefCell::new(DefIdMap()), | |
3079 | impl_or_trait_items: RefCell::new(DefIdMap()), | |
3080 | trait_item_def_ids: RefCell::new(DefIdMap()), | |
3081 | trait_items_cache: RefCell::new(DefIdMap()), | |
85aaf69f SL |
3082 | ty_param_defs: RefCell::new(NodeMap()), |
3083 | adjustments: RefCell::new(NodeMap()), | |
3084 | normalized_cache: RefCell::new(FnvHashMap()), | |
1a4d82fc | 3085 | lang_items: lang_items, |
85aaf69f SL |
3086 | provided_method_sources: RefCell::new(DefIdMap()), |
3087 | struct_fields: RefCell::new(DefIdMap()), | |
3088 | destructor_for_type: RefCell::new(DefIdMap()), | |
3089 | destructors: RefCell::new(DefIdSet()), | |
85aaf69f SL |
3090 | inherent_impls: RefCell::new(DefIdMap()), |
3091 | impl_items: RefCell::new(DefIdMap()), | |
3092 | used_unsafe: RefCell::new(NodeSet()), | |
3093 | used_mut_nodes: RefCell::new(NodeSet()), | |
3094 | populated_external_types: RefCell::new(DefIdSet()), | |
c34b1796 | 3095 | populated_external_primitive_impls: RefCell::new(DefIdSet()), |
85aaf69f SL |
3096 | upvar_capture_map: RefCell::new(FnvHashMap()), |
3097 | extern_const_statics: RefCell::new(DefIdMap()), | |
3098 | extern_const_variants: RefCell::new(DefIdMap()), | |
62682a34 | 3099 | extern_const_fns: RefCell::new(DefIdMap()), |
85aaf69f SL |
3100 | method_map: RefCell::new(FnvHashMap()), |
3101 | dependency_formats: RefCell::new(FnvHashMap()), | |
3102 | closure_kinds: RefCell::new(DefIdMap()), | |
3103 | closure_tys: RefCell::new(DefIdMap()), | |
3104 | node_lint_levels: RefCell::new(FnvHashMap()), | |
1a4d82fc JJ |
3105 | transmute_restrictions: RefCell::new(Vec::new()), |
3106 | stability: RefCell::new(stability), | |
1a4d82fc | 3107 | selection_cache: traits::SelectionCache::new(), |
85aaf69f | 3108 | repr_hint_cache: RefCell::new(DefIdMap()), |
85aaf69f | 3109 | const_qualif_map: RefCell::new(NodeMap()), |
d9579d0f | 3110 | custom_coerce_unsized_kinds: RefCell::new(DefIdMap()), |
62682a34 SL |
3111 | cast_kinds: RefCell::new(NodeMap()), |
3112 | }, f) | |
1a4d82fc | 3113 | } |
223e47cc | 3114 | |
1a4d82fc | 3115 | // Type constructors |
223e47cc | 3116 | |
1a4d82fc JJ |
3117 | impl<'tcx> ctxt<'tcx> { |
3118 | pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> { | |
3119 | if let Some(substs) = self.substs_interner.borrow().get(&substs) { | |
3120 | return *substs; | |
3121 | } | |
223e47cc | 3122 | |
1a4d82fc JJ |
3123 | let substs = self.arenas.substs.alloc(substs); |
3124 | self.substs_interner.borrow_mut().insert(substs, substs); | |
3125 | substs | |
223e47cc LB |
3126 | } |
3127 | ||
c34b1796 AL |
3128 | /// Create an unsafe fn ty based on a safe fn ty. |
3129 | pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> { | |
3130 | assert_eq!(bare_fn.unsafety, ast::Unsafety::Normal); | |
3131 | let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy { | |
3132 | unsafety: ast::Unsafety::Unsafe, | |
3133 | abi: bare_fn.abi, | |
3134 | sig: bare_fn.sig.clone() | |
3135 | }); | |
3136 | ty::mk_bare_fn(self, None, unsafe_fn_ty_a) | |
3137 | } | |
3138 | ||
1a4d82fc JJ |
3139 | pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> { |
3140 | if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) { | |
3141 | return *bare_fn; | |
3142 | } | |
223e47cc | 3143 | |
1a4d82fc JJ |
3144 | let bare_fn = self.arenas.bare_fn.alloc(bare_fn); |
3145 | self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn); | |
3146 | bare_fn | |
223e47cc LB |
3147 | } |
3148 | ||
1a4d82fc JJ |
3149 | pub fn mk_region(&self, region: Region) -> &'tcx Region { |
3150 | if let Some(region) = self.region_interner.borrow().get(®ion) { | |
3151 | return *region; | |
970d7e83 | 3152 | } |
223e47cc | 3153 | |
1a4d82fc JJ |
3154 | let region = self.arenas.region.alloc(region); |
3155 | self.region_interner.borrow_mut().insert(region, region); | |
3156 | region | |
223e47cc | 3157 | } |
223e47cc | 3158 | |
85aaf69f | 3159 | pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind { |
c34b1796 | 3160 | *self.closure_kinds.borrow().get(&def_id).unwrap() |
223e47cc | 3161 | } |
223e47cc | 3162 | |
85aaf69f SL |
3163 | pub fn closure_type(&self, |
3164 | def_id: ast::DefId, | |
3165 | substs: &subst::Substs<'tcx>) | |
3166 | -> ty::ClosureTy<'tcx> | |
1a4d82fc | 3167 | { |
c34b1796 AL |
3168 | self.closure_tys.borrow().get(&def_id).unwrap().subst(self, substs) |
3169 | } | |
3170 | ||
3171 | pub fn type_parameter_def(&self, | |
3172 | node_id: ast::NodeId) | |
3173 | -> TypeParameterDef<'tcx> | |
3174 | { | |
3175 | self.ty_param_defs.borrow().get(&node_id).unwrap().clone() | |
3176 | } | |
3177 | ||
62682a34 | 3178 | pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> Option<ast::Mutability> { |
c34b1796 AL |
3179 | pat_util::pat_contains_ref_binding(&self.def_map, pat) |
3180 | } | |
3181 | ||
62682a34 | 3182 | pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> Option<ast::Mutability> { |
c34b1796 | 3183 | pat_util::arm_contains_ref_binding(&self.def_map, arm) |
223e47cc LB |
3184 | } |
3185 | } | |
3186 | ||
1a4d82fc JJ |
3187 | // Interns a type/name combination, stores the resulting box in cx.interner, |
3188 | // and returns the box as cast to an unsafe ptr (see comments for Ty above). | |
62682a34 | 3189 | pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: TypeVariants<'tcx>) -> Ty<'tcx> { |
1a4d82fc JJ |
3190 | let mut interner = cx.interner.borrow_mut(); |
3191 | intern_ty(&cx.arenas.type_, &mut *interner, st) | |
223e47cc LB |
3192 | } |
3193 | ||
1a4d82fc JJ |
3194 | fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>, |
3195 | interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>, | |
62682a34 | 3196 | st: TypeVariants<'tcx>) |
1a4d82fc JJ |
3197 | -> Ty<'tcx> |
3198 | { | |
3199 | match interner.get(&st) { | |
3200 | Some(ty) => return *ty, | |
3201 | _ => () | |
3202 | } | |
223e47cc | 3203 | |
1a4d82fc | 3204 | let flags = FlagComputation::for_sty(&st); |
970d7e83 | 3205 | |
85aaf69f SL |
3206 | let ty = match () { |
3207 | () => type_arena.alloc(TyS { sty: st, | |
62682a34 | 3208 | flags: Cell::new(flags.flags), |
85aaf69f SL |
3209 | region_depth: flags.depth, }), |
3210 | }; | |
970d7e83 | 3211 | |
1a4d82fc | 3212 | debug!("Interned type: {:?} Pointer: {:?}", |
c34b1796 | 3213 | ty, ty as *const TyS); |
223e47cc | 3214 | |
1a4d82fc | 3215 | interner.insert(InternedTy { ty: ty }, ty); |
223e47cc | 3216 | |
1a4d82fc | 3217 | ty |
223e47cc LB |
3218 | } |
3219 | ||
1a4d82fc JJ |
3220 | struct FlagComputation { |
3221 | flags: TypeFlags, | |
223e47cc | 3222 | |
1a4d82fc JJ |
3223 | // maximum depth of any bound region that we have seen thus far |
3224 | depth: u32, | |
223e47cc LB |
3225 | } |
3226 | ||
1a4d82fc JJ |
3227 | impl FlagComputation { |
3228 | fn new() -> FlagComputation { | |
d9579d0f | 3229 | FlagComputation { flags: TypeFlags::empty(), depth: 0 } |
1a4d82fc | 3230 | } |
223e47cc | 3231 | |
62682a34 | 3232 | fn for_sty(st: &TypeVariants) -> FlagComputation { |
1a4d82fc JJ |
3233 | let mut result = FlagComputation::new(); |
3234 | result.add_sty(st); | |
3235 | result | |
223e47cc LB |
3236 | } |
3237 | ||
1a4d82fc | 3238 | fn add_flags(&mut self, flags: TypeFlags) { |
62682a34 | 3239 | self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS); |
1a4d82fc | 3240 | } |
223e47cc | 3241 | |
1a4d82fc JJ |
3242 | fn add_depth(&mut self, depth: u32) { |
3243 | if depth > self.depth { | |
3244 | self.depth = depth; | |
223e47cc | 3245 | } |
1a4d82fc | 3246 | } |
223e47cc | 3247 | |
1a4d82fc JJ |
3248 | /// Adds the flags/depth from a set of types that appear within the current type, but within a |
3249 | /// region binder. | |
3250 | fn add_bound_computation(&mut self, computation: &FlagComputation) { | |
3251 | self.add_flags(computation.flags); | |
223e47cc | 3252 | |
85aaf69f | 3253 | // The types that contributed to `computation` occurred within |
1a4d82fc JJ |
3254 | // a region binder, so subtract one from the region depth |
3255 | // within when adding the depth to `self`. | |
3256 | let depth = computation.depth; | |
3257 | if depth > 0 { | |
3258 | self.add_depth(depth - 1); | |
3259 | } | |
3260 | } | |
223e47cc | 3261 | |
62682a34 | 3262 | fn add_sty(&mut self, st: &TypeVariants) { |
1a4d82fc | 3263 | match st { |
62682a34 SL |
3264 | &TyBool | |
3265 | &TyChar | | |
3266 | &TyInt(_) | | |
3267 | &TyFloat(_) | | |
3268 | &TyUint(_) | | |
3269 | &TyStr => { | |
223e47cc LB |
3270 | } |
3271 | ||
62682a34 SL |
3272 | // You might think that we could just return TyError for |
3273 | // any type containing TyError as a component, and get | |
d9579d0f | 3274 | // rid of the TypeFlags::HAS_TY_ERR flag -- likewise for ty_bot (with |
1a4d82fc JJ |
3275 | // the exception of function types that return bot). |
3276 | // But doing so caused sporadic memory corruption, and | |
3277 | // neither I (tjc) nor nmatsakis could figure out why, | |
3278 | // so we're doing it this way. | |
62682a34 | 3279 | &TyError => { |
d9579d0f | 3280 | self.add_flags(TypeFlags::HAS_TY_ERR) |
223e47cc LB |
3281 | } |
3282 | ||
62682a34 SL |
3283 | &TyParam(ref p) => { |
3284 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
1a4d82fc | 3285 | if p.space == subst::SelfSpace { |
d9579d0f | 3286 | self.add_flags(TypeFlags::HAS_SELF); |
1a4d82fc | 3287 | } else { |
d9579d0f | 3288 | self.add_flags(TypeFlags::HAS_PARAMS); |
1a4d82fc | 3289 | } |
223e47cc LB |
3290 | } |
3291 | ||
62682a34 SL |
3292 | &TyClosure(_, substs) => { |
3293 | self.add_flags(TypeFlags::HAS_TY_CLOSURE); | |
3294 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
1a4d82fc | 3295 | self.add_substs(substs); |
223e47cc LB |
3296 | } |
3297 | ||
62682a34 SL |
3298 | &TyInfer(_) => { |
3299 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); // it might, right? | |
d9579d0f | 3300 | self.add_flags(TypeFlags::HAS_TY_INFER) |
223e47cc LB |
3301 | } |
3302 | ||
62682a34 | 3303 | &TyEnum(_, substs) | &TyStruct(_, substs) => { |
1a4d82fc | 3304 | self.add_substs(substs); |
223e47cc LB |
3305 | } |
3306 | ||
62682a34 | 3307 | &TyProjection(ref data) => { |
d9579d0f | 3308 | self.add_flags(TypeFlags::HAS_PROJECTION); |
85aaf69f | 3309 | self.add_projection_ty(data); |
223e47cc LB |
3310 | } |
3311 | ||
62682a34 | 3312 | &TyTrait(box TraitTy { ref principal, ref bounds }) => { |
1a4d82fc JJ |
3313 | let mut computation = FlagComputation::new(); |
3314 | computation.add_substs(principal.0.substs); | |
85aaf69f SL |
3315 | for projection_bound in &bounds.projection_bounds { |
3316 | let mut proj_computation = FlagComputation::new(); | |
3317 | proj_computation.add_projection_predicate(&projection_bound.0); | |
62682a34 | 3318 | self.add_bound_computation(&proj_computation); |
85aaf69f | 3319 | } |
1a4d82fc | 3320 | self.add_bound_computation(&computation); |
223e47cc | 3321 | |
1a4d82fc | 3322 | self.add_bounds(bounds); |
223e47cc LB |
3323 | } |
3324 | ||
62682a34 | 3325 | &TyBox(tt) | &TyArray(tt, _) | &TySlice(tt) => { |
1a4d82fc | 3326 | self.add_ty(tt) |
223e47cc LB |
3327 | } |
3328 | ||
62682a34 | 3329 | &TyRawPtr(ref m) => { |
1a4d82fc | 3330 | self.add_ty(m.ty); |
223e47cc LB |
3331 | } |
3332 | ||
62682a34 | 3333 | &TyRef(r, ref m) => { |
1a4d82fc JJ |
3334 | self.add_region(*r); |
3335 | self.add_ty(m.ty); | |
223e47cc LB |
3336 | } |
3337 | ||
62682a34 | 3338 | &TyTuple(ref ts) => { |
85aaf69f | 3339 | self.add_tys(&ts[..]); |
223e47cc LB |
3340 | } |
3341 | ||
62682a34 | 3342 | &TyBareFn(_, ref f) => { |
1a4d82fc | 3343 | self.add_fn_sig(&f.sig); |
223e47cc | 3344 | } |
1a4d82fc JJ |
3345 | } |
3346 | } | |
223e47cc | 3347 | |
1a4d82fc | 3348 | fn add_ty(&mut self, ty: Ty) { |
62682a34 | 3349 | self.add_flags(ty.flags.get()); |
1a4d82fc JJ |
3350 | self.add_depth(ty.region_depth); |
3351 | } | |
223e47cc | 3352 | |
1a4d82fc | 3353 | fn add_tys(&mut self, tys: &[Ty]) { |
85aaf69f | 3354 | for &ty in tys { |
1a4d82fc JJ |
3355 | self.add_ty(ty); |
3356 | } | |
3357 | } | |
223e47cc | 3358 | |
1a4d82fc JJ |
3359 | fn add_fn_sig(&mut self, fn_sig: &PolyFnSig) { |
3360 | let mut computation = FlagComputation::new(); | |
223e47cc | 3361 | |
c34b1796 | 3362 | computation.add_tys(&fn_sig.0.inputs); |
223e47cc | 3363 | |
1a4d82fc JJ |
3364 | if let ty::FnConverging(output) = fn_sig.0.output { |
3365 | computation.add_ty(output); | |
3366 | } | |
223e47cc | 3367 | |
1a4d82fc | 3368 | self.add_bound_computation(&computation); |
223e47cc LB |
3369 | } |
3370 | ||
1a4d82fc | 3371 | fn add_region(&mut self, r: Region) { |
1a4d82fc | 3372 | match r { |
d9579d0f | 3373 | ty::ReInfer(_) => { self.add_flags(TypeFlags::HAS_RE_INFER); } |
62682a34 SL |
3374 | ty::ReLateBound(debruijn, _) => { self.add_depth(debruijn.depth); } |
3375 | ty::ReEarlyBound(..) => { self.add_flags(TypeFlags::HAS_RE_EARLY_BOUND); } | |
3376 | ty::ReStatic => {} | |
3377 | _ => { self.add_flags(TypeFlags::HAS_FREE_REGIONS); } | |
3378 | } | |
3379 | ||
3380 | if !r.is_global() { | |
3381 | self.add_flags(TypeFlags::HAS_LOCAL_NAMES); | |
1a4d82fc | 3382 | } |
223e47cc LB |
3383 | } |
3384 | ||
85aaf69f SL |
3385 | fn add_projection_predicate(&mut self, projection_predicate: &ProjectionPredicate) { |
3386 | self.add_projection_ty(&projection_predicate.projection_ty); | |
3387 | self.add_ty(projection_predicate.ty); | |
3388 | } | |
3389 | ||
3390 | fn add_projection_ty(&mut self, projection_ty: &ProjectionTy) { | |
3391 | self.add_substs(projection_ty.trait_ref.substs); | |
3392 | } | |
3393 | ||
1a4d82fc JJ |
3394 | fn add_substs(&mut self, substs: &Substs) { |
3395 | self.add_tys(substs.types.as_slice()); | |
3396 | match substs.regions { | |
3397 | subst::ErasedRegions => {} | |
3398 | subst::NonerasedRegions(ref regions) => { | |
62682a34 | 3399 | for &r in regions { |
1a4d82fc JJ |
3400 | self.add_region(r); |
3401 | } | |
3402 | } | |
970d7e83 | 3403 | } |
970d7e83 LB |
3404 | } |
3405 | ||
1a4d82fc JJ |
3406 | fn add_bounds(&mut self, bounds: &ExistentialBounds) { |
3407 | self.add_region(bounds.region_bound); | |
970d7e83 | 3408 | } |
1a4d82fc | 3409 | } |
970d7e83 | 3410 | |
1a4d82fc JJ |
3411 | pub fn mk_mach_int<'tcx>(tcx: &ctxt<'tcx>, tm: ast::IntTy) -> Ty<'tcx> { |
3412 | match tm { | |
c34b1796 | 3413 | ast::TyIs => tcx.types.isize, |
1a4d82fc JJ |
3414 | ast::TyI8 => tcx.types.i8, |
3415 | ast::TyI16 => tcx.types.i16, | |
3416 | ast::TyI32 => tcx.types.i32, | |
3417 | ast::TyI64 => tcx.types.i64, | |
223e47cc | 3418 | } |
1a4d82fc | 3419 | } |
223e47cc | 3420 | |
1a4d82fc JJ |
3421 | pub fn mk_mach_uint<'tcx>(tcx: &ctxt<'tcx>, tm: ast::UintTy) -> Ty<'tcx> { |
3422 | match tm { | |
c34b1796 | 3423 | ast::TyUs => tcx.types.usize, |
1a4d82fc JJ |
3424 | ast::TyU8 => tcx.types.u8, |
3425 | ast::TyU16 => tcx.types.u16, | |
3426 | ast::TyU32 => tcx.types.u32, | |
3427 | ast::TyU64 => tcx.types.u64, | |
3428 | } | |
3429 | } | |
223e47cc | 3430 | |
1a4d82fc JJ |
3431 | pub fn mk_mach_float<'tcx>(tcx: &ctxt<'tcx>, tm: ast::FloatTy) -> Ty<'tcx> { |
3432 | match tm { | |
3433 | ast::TyF32 => tcx.types.f32, | |
3434 | ast::TyF64 => tcx.types.f64, | |
223e47cc | 3435 | } |
970d7e83 | 3436 | } |
223e47cc | 3437 | |
1a4d82fc | 3438 | pub fn mk_str<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { |
62682a34 | 3439 | mk_t(cx, TyStr) |
223e47cc LB |
3440 | } |
3441 | ||
1a4d82fc JJ |
3442 | pub fn mk_str_slice<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, m: ast::Mutability) -> Ty<'tcx> { |
3443 | mk_rptr(cx, r, | |
3444 | mt { | |
62682a34 | 3445 | ty: mk_t(cx, TyStr), |
1a4d82fc JJ |
3446 | mutbl: m |
3447 | }) | |
3448 | } | |
223e47cc | 3449 | |
1a4d82fc JJ |
3450 | pub fn mk_enum<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { |
3451 | // take a copy of substs so that we own the vectors inside | |
62682a34 | 3452 | mk_t(cx, TyEnum(did, substs)) |
1a4d82fc | 3453 | } |
223e47cc | 3454 | |
62682a34 | 3455 | pub fn mk_uniq<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, TyBox(ty)) } |
223e47cc | 3456 | |
62682a34 | 3457 | pub fn mk_ptr<'tcx>(cx: &ctxt<'tcx>, tm: mt<'tcx>) -> Ty<'tcx> { mk_t(cx, TyRawPtr(tm)) } |
223e47cc | 3458 | |
1a4d82fc | 3459 | pub fn mk_rptr<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx> { |
62682a34 | 3460 | mk_t(cx, TyRef(r, tm)) |
1a4d82fc | 3461 | } |
223e47cc | 3462 | |
1a4d82fc JJ |
3463 | pub fn mk_mut_rptr<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> { |
3464 | mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutMutable}) | |
3465 | } | |
3466 | pub fn mk_imm_rptr<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> { | |
3467 | mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutImmutable}) | |
3468 | } | |
223e47cc | 3469 | |
1a4d82fc JJ |
3470 | pub fn mk_mut_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { |
3471 | mk_ptr(cx, mt {ty: ty, mutbl: ast::MutMutable}) | |
3472 | } | |
223e47cc | 3473 | |
1a4d82fc JJ |
3474 | pub fn mk_imm_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { |
3475 | mk_ptr(cx, mt {ty: ty, mutbl: ast::MutImmutable}) | |
3476 | } | |
223e47cc | 3477 | |
1a4d82fc JJ |
3478 | pub fn mk_nil_ptr<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { |
3479 | mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::MutImmutable}) | |
3480 | } | |
223e47cc | 3481 | |
c34b1796 | 3482 | pub fn mk_vec<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, sz: Option<usize>) -> Ty<'tcx> { |
62682a34 SL |
3483 | match sz { |
3484 | Some(n) => mk_t(cx, TyArray(ty, n)), | |
3485 | None => mk_t(cx, TySlice(ty)) | |
3486 | } | |
1a4d82fc | 3487 | } |
223e47cc | 3488 | |
1a4d82fc JJ |
3489 | pub fn mk_slice<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx> { |
3490 | mk_rptr(cx, r, | |
3491 | mt { | |
3492 | ty: mk_vec(cx, tm.ty, None), | |
3493 | mutbl: tm.mutbl | |
3494 | }) | |
3495 | } | |
223e47cc | 3496 | |
1a4d82fc | 3497 | pub fn mk_tup<'tcx>(cx: &ctxt<'tcx>, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> { |
62682a34 | 3498 | mk_t(cx, TyTuple(ts)) |
1a4d82fc | 3499 | } |
223e47cc | 3500 | |
1a4d82fc JJ |
3501 | pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { |
3502 | mk_tup(cx, Vec::new()) | |
3503 | } | |
223e47cc | 3504 | |
c34b1796 | 3505 | pub fn mk_bool<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { |
62682a34 | 3506 | mk_t(cx, TyBool) |
c34b1796 AL |
3507 | } |
3508 | ||
1a4d82fc JJ |
3509 | pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, |
3510 | opt_def_id: Option<ast::DefId>, | |
3511 | fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> { | |
62682a34 | 3512 | mk_t(cx, TyBareFn(opt_def_id, fty)) |
223e47cc LB |
3513 | } |
3514 | ||
1a4d82fc JJ |
3515 | pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>, |
3516 | def_id: ast::DefId, | |
3517 | input_tys: &[Ty<'tcx>], | |
3518 | output: Ty<'tcx>) -> Ty<'tcx> { | |
85aaf69f | 3519 | let input_args = input_tys.iter().cloned().collect(); |
1a4d82fc JJ |
3520 | mk_bare_fn(cx, |
3521 | Some(def_id), | |
3522 | cx.mk_bare_fn(BareFnTy { | |
3523 | unsafety: ast::Unsafety::Normal, | |
3524 | abi: abi::Rust, | |
3525 | sig: ty::Binder(FnSig { | |
3526 | inputs: input_args, | |
3527 | output: ty::FnConverging(output), | |
3528 | variadic: false | |
3529 | }) | |
3530 | })) | |
3531 | } | |
223e47cc | 3532 | |
1a4d82fc JJ |
3533 | pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>, |
3534 | principal: ty::PolyTraitRef<'tcx>, | |
3535 | bounds: ExistentialBounds<'tcx>) | |
3536 | -> Ty<'tcx> | |
3537 | { | |
85aaf69f | 3538 | assert!(bound_list_is_sorted(&bounds.projection_bounds)); |
1a4d82fc | 3539 | |
62682a34 | 3540 | let inner = box TraitTy { |
1a4d82fc JJ |
3541 | principal: principal, |
3542 | bounds: bounds | |
3543 | }; | |
62682a34 | 3544 | mk_t(cx, TyTrait(inner)) |
223e47cc LB |
3545 | } |
3546 | ||
1a4d82fc | 3547 | fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool { |
9346a6ac | 3548 | bounds.is_empty() || |
1a4d82fc JJ |
3549 | bounds[1..].iter().enumerate().all( |
3550 | |(index, bound)| bounds[index].sort_key() <= bound.sort_key()) | |
223e47cc LB |
3551 | } |
3552 | ||
1a4d82fc JJ |
3553 | pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) { |
3554 | bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key())) | |
223e47cc LB |
3555 | } |
3556 | ||
1a4d82fc | 3557 | pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>, |
d9579d0f | 3558 | trait_ref: TraitRef<'tcx>, |
1a4d82fc JJ |
3559 | item_name: ast::Name) |
3560 | -> Ty<'tcx> { | |
3561 | // take a copy of substs so that we own the vectors inside | |
3562 | let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name }; | |
62682a34 | 3563 | mk_t(cx, TyProjection(inner)) |
223e47cc LB |
3564 | } |
3565 | ||
1a4d82fc JJ |
3566 | pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId, |
3567 | substs: &'tcx Substs<'tcx>) -> Ty<'tcx> { | |
3568 | // take a copy of substs so that we own the vectors inside | |
62682a34 | 3569 | mk_t(cx, TyStruct(struct_id, substs)) |
223e47cc LB |
3570 | } |
3571 | ||
c34b1796 | 3572 | pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &'tcx Substs<'tcx>) |
85aaf69f | 3573 | -> Ty<'tcx> { |
62682a34 | 3574 | mk_t(cx, TyClosure(closure_id, substs)) |
223e47cc LB |
3575 | } |
3576 | ||
1a4d82fc JJ |
3577 | pub fn mk_var<'tcx>(cx: &ctxt<'tcx>, v: TyVid) -> Ty<'tcx> { |
3578 | mk_infer(cx, TyVar(v)) | |
223e47cc LB |
3579 | } |
3580 | ||
1a4d82fc JJ |
3581 | pub fn mk_int_var<'tcx>(cx: &ctxt<'tcx>, v: IntVid) -> Ty<'tcx> { |
3582 | mk_infer(cx, IntVar(v)) | |
970d7e83 LB |
3583 | } |
3584 | ||
1a4d82fc JJ |
3585 | pub fn mk_float_var<'tcx>(cx: &ctxt<'tcx>, v: FloatVid) -> Ty<'tcx> { |
3586 | mk_infer(cx, FloatVar(v)) | |
3587 | } | |
223e47cc | 3588 | |
1a4d82fc | 3589 | pub fn mk_infer<'tcx>(cx: &ctxt<'tcx>, it: InferTy) -> Ty<'tcx> { |
62682a34 | 3590 | mk_t(cx, TyInfer(it)) |
1a4d82fc | 3591 | } |
223e47cc | 3592 | |
1a4d82fc JJ |
3593 | pub fn mk_param<'tcx>(cx: &ctxt<'tcx>, |
3594 | space: subst::ParamSpace, | |
3595 | index: u32, | |
3596 | name: ast::Name) -> Ty<'tcx> { | |
62682a34 | 3597 | mk_t(cx, TyParam(ParamTy { space: space, idx: index, name: name })) |
1a4d82fc | 3598 | } |
223e47cc | 3599 | |
1a4d82fc JJ |
3600 | pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> { |
3601 | mk_param(cx, subst::SelfSpace, 0, special_idents::type_self.name) | |
223e47cc LB |
3602 | } |
3603 | ||
1a4d82fc JJ |
3604 | pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'tcx> { |
3605 | mk_param(cx, def.space, def.index, def.name) | |
223e47cc LB |
3606 | } |
3607 | ||
1a4d82fc JJ |
3608 | impl<'tcx> TyS<'tcx> { |
3609 | /// Iterator that walks `self` and any types reachable from | |
3610 | /// `self`, in depth-first order. Note that just walks the types | |
3611 | /// that appear in `self`, it does not descend into the fields of | |
3612 | /// structs or variants. For example: | |
3613 | /// | |
3614 | /// ```notrust | |
c34b1796 AL |
3615 | /// isize => { isize } |
3616 | /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize } | |
3617 | /// [isize] => { [isize], isize } | |
1a4d82fc JJ |
3618 | /// ``` |
3619 | pub fn walk(&'tcx self) -> TypeWalker<'tcx> { | |
3620 | TypeWalker::new(self) | |
970d7e83 | 3621 | } |
970d7e83 | 3622 | |
c34b1796 AL |
3623 | /// Iterator that walks the immediate children of `self`. Hence |
3624 | /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]` | |
3625 | /// (but not `i32`, like `walk`). | |
3626 | pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> { | |
3627 | ty_walk::walk_shallow(self) | |
223e47cc | 3628 | } |
85aaf69f SL |
3629 | |
3630 | pub fn as_opt_param_ty(&self) -> Option<ty::ParamTy> { | |
3631 | match self.sty { | |
62682a34 | 3632 | ty::TyParam(ref d) => Some(d.clone()), |
85aaf69f SL |
3633 | _ => None, |
3634 | } | |
3635 | } | |
c34b1796 AL |
3636 | |
3637 | pub fn is_param(&self, space: ParamSpace, index: u32) -> bool { | |
3638 | match self.sty { | |
62682a34 | 3639 | ty::TyParam(ref data) => data.space == space && data.idx == index, |
c34b1796 AL |
3640 | _ => false, |
3641 | } | |
3642 | } | |
223e47cc LB |
3643 | } |
3644 | ||
1a4d82fc JJ |
3645 | pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F) |
3646 | where F: FnMut(Ty<'tcx>), | |
3647 | { | |
3648 | for ty in ty_root.walk() { | |
3649 | f(ty); | |
223e47cc | 3650 | } |
223e47cc LB |
3651 | } |
3652 | ||
1a4d82fc JJ |
3653 | /// Walks `ty` and any types appearing within `ty`, invoking the |
3654 | /// callback `f` on each type. If the callback returns false, then the | |
3655 | /// children of the current type are ignored. | |
3656 | /// | |
3657 | /// Note: prefer `ty.walk()` where possible. | |
3658 | pub fn maybe_walk_ty<'tcx,F>(ty_root: Ty<'tcx>, mut f: F) | |
3659 | where F : FnMut(Ty<'tcx>) -> bool | |
3660 | { | |
3661 | let mut walker = ty_root.walk(); | |
3662 | while let Some(ty) = walker.next() { | |
3663 | if !f(ty) { | |
3664 | walker.skip_current_subtree(); | |
3665 | } | |
3666 | } | |
223e47cc LB |
3667 | } |
3668 | ||
1a4d82fc JJ |
3669 | // Folds types from the bottom up. |
3670 | pub fn fold_ty<'tcx, F>(cx: &ctxt<'tcx>, t0: Ty<'tcx>, | |
3671 | fldop: F) | |
3672 | -> Ty<'tcx> where | |
3673 | F: FnMut(Ty<'tcx>) -> Ty<'tcx>, | |
3674 | { | |
3675 | let mut f = ty_fold::BottomUpFolder {tcx: cx, fldop: fldop}; | |
3676 | f.fold_ty(t0) | |
3677 | } | |
223e47cc | 3678 | |
1a4d82fc JJ |
3679 | impl ParamTy { |
3680 | pub fn new(space: subst::ParamSpace, | |
3681 | index: u32, | |
3682 | name: ast::Name) | |
3683 | -> ParamTy { | |
3684 | ParamTy { space: space, idx: index, name: name } | |
3685 | } | |
223e47cc | 3686 | |
1a4d82fc JJ |
3687 | pub fn for_self() -> ParamTy { |
3688 | ParamTy::new(subst::SelfSpace, 0, special_idents::type_self.name) | |
3689 | } | |
223e47cc | 3690 | |
1a4d82fc JJ |
3691 | pub fn for_def(def: &TypeParameterDef) -> ParamTy { |
3692 | ParamTy::new(def.space, def.index, def.name) | |
3693 | } | |
223e47cc | 3694 | |
1a4d82fc JJ |
3695 | pub fn to_ty<'tcx>(self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> { |
3696 | ty::mk_param(tcx, self.space, self.idx, self.name) | |
223e47cc | 3697 | } |
223e47cc | 3698 | |
1a4d82fc JJ |
3699 | pub fn is_self(&self) -> bool { |
3700 | self.space == subst::SelfSpace && self.idx == 0 | |
223e47cc LB |
3701 | } |
3702 | } | |
3703 | ||
1a4d82fc JJ |
3704 | impl<'tcx> ItemSubsts<'tcx> { |
3705 | pub fn empty() -> ItemSubsts<'tcx> { | |
3706 | ItemSubsts { substs: Substs::empty() } | |
3707 | } | |
223e47cc | 3708 | |
1a4d82fc JJ |
3709 | pub fn is_noop(&self) -> bool { |
3710 | self.substs.is_noop() | |
223e47cc LB |
3711 | } |
3712 | } | |
3713 | ||
1a4d82fc JJ |
3714 | // Type utilities |
3715 | ||
3716 | pub fn type_is_nil(ty: Ty) -> bool { | |
3717 | match ty.sty { | |
62682a34 | 3718 | TyTuple(ref tys) => tys.is_empty(), |
1a4d82fc | 3719 | _ => false |
223e47cc LB |
3720 | } |
3721 | } | |
3722 | ||
1a4d82fc | 3723 | pub fn type_is_error(ty: Ty) -> bool { |
62682a34 | 3724 | ty.flags.get().intersects(TypeFlags::HAS_TY_ERR) |
1a4d82fc | 3725 | } |
970d7e83 | 3726 | |
1a4d82fc | 3727 | pub fn type_needs_subst(ty: Ty) -> bool { |
62682a34 | 3728 | ty.flags.get().intersects(TypeFlags::NEEDS_SUBST) |
1a4d82fc | 3729 | } |
970d7e83 | 3730 | |
1a4d82fc JJ |
3731 | pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool { |
3732 | tref.substs.types.any(|&ty| type_is_error(ty)) | |
3733 | } | |
970d7e83 | 3734 | |
1a4d82fc JJ |
3735 | pub fn type_is_ty_var(ty: Ty) -> bool { |
3736 | match ty.sty { | |
62682a34 | 3737 | TyInfer(TyVar(_)) => true, |
1a4d82fc | 3738 | _ => false |
223e47cc LB |
3739 | } |
3740 | } | |
3741 | ||
62682a34 | 3742 | pub fn type_is_bool(ty: Ty) -> bool { ty.sty == TyBool } |
1a4d82fc JJ |
3743 | |
3744 | pub fn type_is_self(ty: Ty) -> bool { | |
3745 | match ty.sty { | |
62682a34 | 3746 | TyParam(ref p) => p.space == subst::SelfSpace, |
1a4d82fc | 3747 | _ => false |
223e47cc LB |
3748 | } |
3749 | } | |
3750 | ||
1a4d82fc JJ |
3751 | fn type_is_slice(ty: Ty) -> bool { |
3752 | match ty.sty { | |
62682a34 SL |
3753 | TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty { |
3754 | TySlice(_) | TyStr => true, | |
1a4d82fc JJ |
3755 | _ => false, |
3756 | }, | |
3757 | _ => false | |
223e47cc LB |
3758 | } |
3759 | } | |
3760 | ||
1a4d82fc JJ |
3761 | pub fn type_is_structural(ty: Ty) -> bool { |
3762 | match ty.sty { | |
62682a34 SL |
3763 | TyStruct(..) | TyTuple(_) | TyEnum(..) | |
3764 | TyArray(..) | TyClosure(..) => true, | |
1a4d82fc | 3765 | _ => type_is_slice(ty) | type_is_trait(ty) |
223e47cc LB |
3766 | } |
3767 | } | |
3768 | ||
1a4d82fc JJ |
3769 | pub fn type_is_simd(cx: &ctxt, ty: Ty) -> bool { |
3770 | match ty.sty { | |
62682a34 | 3771 | TyStruct(did, _) => lookup_simd(cx, did), |
1a4d82fc JJ |
3772 | _ => false |
3773 | } | |
223e47cc LB |
3774 | } |
3775 | ||
1a4d82fc JJ |
3776 | pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { |
3777 | match ty.sty { | |
62682a34 SL |
3778 | TyArray(ty, _) | TySlice(ty) => ty, |
3779 | TyStr => mk_mach_uint(cx, ast::TyU8), | |
1a4d82fc | 3780 | _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}", |
62682a34 | 3781 | ty)), |
970d7e83 LB |
3782 | } |
3783 | } | |
3784 | ||
1a4d82fc JJ |
3785 | pub fn simd_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { |
3786 | match ty.sty { | |
62682a34 | 3787 | TyStruct(did, substs) => { |
1a4d82fc JJ |
3788 | let fields = lookup_struct_fields(cx, did); |
3789 | lookup_field_type(cx, did, fields[0].id, substs) | |
223e47cc | 3790 | } |
1a4d82fc | 3791 | _ => panic!("simd_type called on invalid type") |
223e47cc LB |
3792 | } |
3793 | } | |
3794 | ||
c34b1796 | 3795 | pub fn simd_size(cx: &ctxt, ty: Ty) -> usize { |
1a4d82fc | 3796 | match ty.sty { |
62682a34 | 3797 | TyStruct(did, _) => { |
1a4d82fc JJ |
3798 | let fields = lookup_struct_fields(cx, did); |
3799 | fields.len() | |
223e47cc | 3800 | } |
1a4d82fc | 3801 | _ => panic!("simd_size called on invalid type") |
223e47cc LB |
3802 | } |
3803 | } | |
3804 | ||
1a4d82fc JJ |
3805 | pub fn type_is_region_ptr(ty: Ty) -> bool { |
3806 | match ty.sty { | |
62682a34 | 3807 | TyRef(..) => true, |
1a4d82fc | 3808 | _ => false |
223e47cc LB |
3809 | } |
3810 | } | |
3811 | ||
1a4d82fc JJ |
3812 | pub fn type_is_unsafe_ptr(ty: Ty) -> bool { |
3813 | match ty.sty { | |
62682a34 | 3814 | TyRawPtr(_) => return true, |
1a4d82fc | 3815 | _ => return false |
223e47cc LB |
3816 | } |
3817 | } | |
3818 | ||
1a4d82fc JJ |
3819 | pub fn type_is_unique(ty: Ty) -> bool { |
3820 | match ty.sty { | |
62682a34 | 3821 | TyBox(_) => true, |
223e47cc LB |
3822 | _ => false |
3823 | } | |
3824 | } | |
3825 | ||
1a4d82fc JJ |
3826 | /* |
3827 | A scalar type is one that denotes an atomic datum, with no sub-components. | |
62682a34 | 3828 | (A TyRawPtr is scalar because it represents a non-managed pointer, so its |
1a4d82fc JJ |
3829 | contents are abstract to rustc.) |
3830 | */ | |
3831 | pub fn type_is_scalar(ty: Ty) -> bool { | |
3832 | match ty.sty { | |
62682a34 SL |
3833 | TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) | |
3834 | TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) | | |
3835 | TyBareFn(..) | TyRawPtr(_) => true, | |
1a4d82fc | 3836 | _ => false |
223e47cc LB |
3837 | } |
3838 | } | |
3839 | ||
1a4d82fc JJ |
3840 | /// Returns true if this type is a floating point type and false otherwise. |
3841 | pub fn type_is_floating_point(ty: Ty) -> bool { | |
3842 | match ty.sty { | |
62682a34 SL |
3843 | TyFloat(_) | |
3844 | TyInfer(FloatVar(_)) => | |
c34b1796 AL |
3845 | true, |
3846 | ||
3847 | _ => | |
3848 | false, | |
223e47cc LB |
3849 | } |
3850 | } | |
3851 | ||
1a4d82fc JJ |
3852 | /// Type contents is how the type checker reasons about kinds. |
3853 | /// They track what kinds of things are found within a type. You can | |
3854 | /// think of them as kind of an "anti-kind". They track the kinds of values | |
3855 | /// and thinks that are contained in types. Having a larger contents for | |
3856 | /// a type tends to rule that type *out* from various kinds. For example, | |
3857 | /// a type that contains a reference is not sendable. | |
3858 | /// | |
3859 | /// The reason we compute type contents and not kinds is that it is | |
3860 | /// easier for me (nmatsakis) to think about what is contained within | |
3861 | /// a type than to think about what is *not* contained within a type. | |
3862 | #[derive(Clone, Copy)] | |
3863 | pub struct TypeContents { | |
3864 | pub bits: u64 | |
3865 | } | |
3866 | ||
3867 | macro_rules! def_type_content_sets { | |
3868 | (mod $mname:ident { $($name:ident = $bits:expr),+ }) => { | |
3869 | #[allow(non_snake_case)] | |
3870 | mod $mname { | |
3871 | use middle::ty::TypeContents; | |
3872 | $( | |
3873 | #[allow(non_upper_case_globals)] | |
3874 | pub const $name: TypeContents = TypeContents { bits: $bits }; | |
3875 | )+ | |
970d7e83 LB |
3876 | } |
3877 | } | |
3878 | } | |
3879 | ||
1a4d82fc JJ |
3880 | def_type_content_sets! { |
3881 | mod TC { | |
3882 | None = 0b0000_0000__0000_0000__0000, | |
223e47cc | 3883 | |
1a4d82fc JJ |
3884 | // Things that are interior to the value (first nibble): |
3885 | InteriorUnsized = 0b0000_0000__0000_0000__0001, | |
3886 | InteriorUnsafe = 0b0000_0000__0000_0000__0010, | |
3887 | InteriorParam = 0b0000_0000__0000_0000__0100, | |
3888 | // InteriorAll = 0b00000000__00000000__1111, | |
223e47cc | 3889 | |
1a4d82fc JJ |
3890 | // Things that are owned by the value (second and third nibbles): |
3891 | OwnsOwned = 0b0000_0000__0000_0001__0000, | |
3892 | OwnsDtor = 0b0000_0000__0000_0010__0000, | |
1a4d82fc | 3893 | OwnsAll = 0b0000_0000__1111_1111__0000, |
223e47cc | 3894 | |
1a4d82fc JJ |
3895 | // Things that are reachable by the value in any way (fourth nibble): |
3896 | ReachesBorrowed = 0b0000_0010__0000_0000__0000, | |
1a4d82fc JJ |
3897 | ReachesMutable = 0b0000_1000__0000_0000__0000, |
3898 | ReachesFfiUnsafe = 0b0010_0000__0000_0000__0000, | |
3899 | ReachesAll = 0b0011_1111__0000_0000__0000, | |
223e47cc | 3900 | |
1a4d82fc JJ |
3901 | // Things that mean drop glue is necessary |
3902 | NeedsDrop = 0b0000_0000__0000_0111__0000, | |
223e47cc | 3903 | |
1a4d82fc JJ |
3904 | // Things that prevent values from being considered sized |
3905 | Nonsized = 0b0000_0000__0000_0000__0001, | |
223e47cc | 3906 | |
1a4d82fc JJ |
3907 | // All bits |
3908 | All = 0b1111_1111__1111_1111__1111 | |
3909 | } | |
223e47cc LB |
3910 | } |
3911 | ||
1a4d82fc JJ |
3912 | impl TypeContents { |
3913 | pub fn when(&self, cond: bool) -> TypeContents { | |
3914 | if cond {*self} else {TC::None} | |
3915 | } | |
223e47cc | 3916 | |
1a4d82fc JJ |
3917 | pub fn intersects(&self, tc: TypeContents) -> bool { |
3918 | (self.bits & tc.bits) != 0 | |
3919 | } | |
223e47cc | 3920 | |
1a4d82fc JJ |
3921 | pub fn owns_owned(&self) -> bool { |
3922 | self.intersects(TC::OwnsOwned) | |
3923 | } | |
223e47cc | 3924 | |
1a4d82fc JJ |
3925 | pub fn is_sized(&self, _: &ctxt) -> bool { |
3926 | !self.intersects(TC::Nonsized) | |
3927 | } | |
223e47cc | 3928 | |
1a4d82fc JJ |
3929 | pub fn interior_param(&self) -> bool { |
3930 | self.intersects(TC::InteriorParam) | |
3931 | } | |
223e47cc | 3932 | |
1a4d82fc JJ |
3933 | pub fn interior_unsafe(&self) -> bool { |
3934 | self.intersects(TC::InteriorUnsafe) | |
3935 | } | |
223e47cc | 3936 | |
1a4d82fc JJ |
3937 | pub fn interior_unsized(&self) -> bool { |
3938 | self.intersects(TC::InteriorUnsized) | |
3939 | } | |
223e47cc | 3940 | |
1a4d82fc JJ |
3941 | pub fn needs_drop(&self, _: &ctxt) -> bool { |
3942 | self.intersects(TC::NeedsDrop) | |
3943 | } | |
223e47cc | 3944 | |
1a4d82fc JJ |
3945 | /// Includes only those bits that still apply when indirected through a `Box` pointer |
3946 | pub fn owned_pointer(&self) -> TypeContents { | |
3947 | TC::OwnsOwned | ( | |
3948 | *self & (TC::OwnsAll | TC::ReachesAll)) | |
3949 | } | |
970d7e83 | 3950 | |
1a4d82fc JJ |
3951 | /// Includes only those bits that still apply when indirected through a reference (`&`) |
3952 | pub fn reference(&self, bits: TypeContents) -> TypeContents { | |
3953 | bits | ( | |
3954 | *self & TC::ReachesAll) | |
3955 | } | |
223e47cc | 3956 | |
62682a34 | 3957 | /// Includes only those bits that still apply when indirected through a raw pointer (`*`) |
1a4d82fc JJ |
3958 | pub fn unsafe_pointer(&self) -> TypeContents { |
3959 | *self & TC::ReachesAll | |
3960 | } | |
223e47cc | 3961 | |
1a4d82fc JJ |
3962 | pub fn union<T, F>(v: &[T], mut f: F) -> TypeContents where |
3963 | F: FnMut(&T) -> TypeContents, | |
3964 | { | |
3965 | v.iter().fold(TC::None, |tc, ty| tc | f(ty)) | |
223e47cc LB |
3966 | } |
3967 | ||
1a4d82fc JJ |
3968 | pub fn has_dtor(&self) -> bool { |
3969 | self.intersects(TC::OwnsDtor) | |
3970 | } | |
3971 | } | |
223e47cc | 3972 | |
1a4d82fc JJ |
3973 | impl ops::BitOr for TypeContents { |
3974 | type Output = TypeContents; | |
3975 | ||
3976 | fn bitor(self, other: TypeContents) -> TypeContents { | |
3977 | TypeContents {bits: self.bits | other.bits} | |
223e47cc LB |
3978 | } |
3979 | } | |
3980 | ||
1a4d82fc JJ |
3981 | impl ops::BitAnd for TypeContents { |
3982 | type Output = TypeContents; | |
3983 | ||
3984 | fn bitand(self, other: TypeContents) -> TypeContents { | |
3985 | TypeContents {bits: self.bits & other.bits} | |
970d7e83 LB |
3986 | } |
3987 | } | |
3988 | ||
1a4d82fc JJ |
3989 | impl ops::Sub for TypeContents { |
3990 | type Output = TypeContents; | |
3991 | ||
3992 | fn sub(self, other: TypeContents) -> TypeContents { | |
3993 | TypeContents {bits: self.bits & !other.bits} | |
3994 | } | |
223e47cc LB |
3995 | } |
3996 | ||
85aaf69f | 3997 | impl fmt::Debug for TypeContents { |
1a4d82fc JJ |
3998 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
3999 | write!(f, "TypeContents({:b})", self.bits) | |
223e47cc LB |
4000 | } |
4001 | } | |
4002 | ||
1a4d82fc JJ |
4003 | pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents { |
4004 | return memoized(&cx.tc_cache, ty, |ty| { | |
85aaf69f | 4005 | tc_ty(cx, ty, &mut FnvHashMap()) |
1a4d82fc JJ |
4006 | }); |
4007 | ||
4008 | fn tc_ty<'tcx>(cx: &ctxt<'tcx>, | |
4009 | ty: Ty<'tcx>, | |
4010 | cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents | |
4011 | { | |
4012 | // Subtle: Note that we are *not* using cx.tc_cache here but rather a | |
4013 | // private cache for this walk. This is needed in the case of cyclic | |
4014 | // types like: | |
4015 | // | |
4016 | // struct List { next: Box<Option<List>>, ... } | |
4017 | // | |
4018 | // When computing the type contents of such a type, we wind up deeply | |
4019 | // recursing as we go. So when we encounter the recursive reference | |
4020 | // to List, we temporarily use TC::None as its contents. Later we'll | |
4021 | // patch up the cache with the correct value, once we've computed it | |
4022 | // (this is basically a co-inductive process, if that helps). So in | |
4023 | // the end we'll compute TC::OwnsOwned, in this case. | |
4024 | // | |
4025 | // The problem is, as we are doing the computation, we will also | |
4026 | // compute an *intermediate* contents for, e.g., Option<List> of | |
4027 | // TC::None. This is ok during the computation of List itself, but if | |
4028 | // we stored this intermediate value into cx.tc_cache, then later | |
4029 | // requests for the contents of Option<List> would also yield TC::None | |
4030 | // which is incorrect. This value was computed based on the crutch | |
4031 | // value for the type contents of list. The correct value is | |
4032 | // TC::OwnsOwned. This manifested as issue #4821. | |
4033 | match cache.get(&ty) { | |
4034 | Some(tc) => { return *tc; } | |
4035 | None => {} | |
4036 | } | |
4037 | match cx.tc_cache.borrow().get(&ty) { // Must check both caches! | |
4038 | Some(tc) => { return *tc; } | |
4039 | None => {} | |
4040 | } | |
4041 | cache.insert(ty, TC::None); | |
4042 | ||
4043 | let result = match ty.sty { | |
c34b1796 | 4044 | // usize and isize are ffi-unsafe |
62682a34 | 4045 | TyUint(ast::TyUs) | TyInt(ast::TyIs) => { |
1a4d82fc JJ |
4046 | TC::ReachesFfiUnsafe |
4047 | } | |
4048 | ||
4049 | // Scalar and unique types are sendable, and durable | |
62682a34 SL |
4050 | TyInfer(ty::FreshIntTy(_)) | TyInfer(ty::FreshFloatTy(_)) | |
4051 | TyBool | TyInt(_) | TyUint(_) | TyFloat(_) | | |
4052 | TyBareFn(..) | ty::TyChar => { | |
1a4d82fc JJ |
4053 | TC::None |
4054 | } | |
4055 | ||
62682a34 | 4056 | TyBox(typ) => { |
1a4d82fc | 4057 | TC::ReachesFfiUnsafe | match typ.sty { |
62682a34 | 4058 | TyStr => TC::OwnsOwned, |
1a4d82fc JJ |
4059 | _ => tc_ty(cx, typ, cache).owned_pointer(), |
4060 | } | |
4061 | } | |
4062 | ||
62682a34 | 4063 | TyTrait(box TraitTy { ref bounds, .. }) => { |
1a4d82fc JJ |
4064 | object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized |
4065 | } | |
4066 | ||
62682a34 | 4067 | TyRawPtr(ref mt) => { |
1a4d82fc JJ |
4068 | tc_ty(cx, mt.ty, cache).unsafe_pointer() |
4069 | } | |
4070 | ||
62682a34 | 4071 | TyRef(r, ref mt) => { |
1a4d82fc | 4072 | TC::ReachesFfiUnsafe | match mt.ty.sty { |
62682a34 SL |
4073 | TyStr => borrowed_contents(*r, ast::MutImmutable), |
4074 | TyArray(..) | | |
4075 | TySlice(_) => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r, | |
1a4d82fc JJ |
4076 | mt.mutbl)), |
4077 | _ => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r, mt.mutbl)), | |
4078 | } | |
4079 | } | |
4080 | ||
62682a34 | 4081 | TyArray(ty, _) => { |
1a4d82fc JJ |
4082 | tc_ty(cx, ty, cache) |
4083 | } | |
4084 | ||
62682a34 | 4085 | TySlice(ty) => { |
1a4d82fc JJ |
4086 | tc_ty(cx, ty, cache) | TC::Nonsized |
4087 | } | |
62682a34 | 4088 | TyStr => TC::Nonsized, |
1a4d82fc | 4089 | |
62682a34 | 4090 | TyStruct(did, substs) => { |
1a4d82fc JJ |
4091 | let flds = struct_fields(cx, did, substs); |
4092 | let mut res = | |
85aaf69f | 4093 | TypeContents::union(&flds[..], |
1a4d82fc JJ |
4094 | |f| tc_mt(cx, f.mt, cache)); |
4095 | ||
4096 | if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) { | |
4097 | res = res | TC::ReachesFfiUnsafe; | |
4098 | } | |
4099 | ||
4100 | if ty::has_dtor(cx, did) { | |
4101 | res = res | TC::OwnsDtor; | |
4102 | } | |
4103 | apply_lang_items(cx, did, res) | |
4104 | } | |
4105 | ||
62682a34 | 4106 | TyClosure(did, substs) => { |
85aaf69f | 4107 | // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure. |
1a4d82fc | 4108 | let param_env = ty::empty_parameter_environment(cx); |
85aaf69f | 4109 | let upvars = closure_upvars(¶m_env, did, substs).unwrap(); |
c34b1796 | 4110 | TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache)) |
1a4d82fc JJ |
4111 | } |
4112 | ||
62682a34 | 4113 | TyTuple(ref tys) => { |
85aaf69f | 4114 | TypeContents::union(&tys[..], |
1a4d82fc JJ |
4115 | |ty| tc_ty(cx, *ty, cache)) |
4116 | } | |
4117 | ||
62682a34 | 4118 | TyEnum(did, substs) => { |
1a4d82fc JJ |
4119 | let variants = substd_enum_variants(cx, did, substs); |
4120 | let mut res = | |
85aaf69f | 4121 | TypeContents::union(&variants[..], |variant| { |
c34b1796 | 4122 | TypeContents::union(&variant.args, |
1a4d82fc JJ |
4123 | |arg_ty| { |
4124 | tc_ty(cx, *arg_ty, cache) | |
4125 | }) | |
4126 | }); | |
4127 | ||
4128 | if ty::has_dtor(cx, did) { | |
4129 | res = res | TC::OwnsDtor; | |
4130 | } | |
4131 | ||
9346a6ac | 4132 | if !variants.is_empty() { |
1a4d82fc JJ |
4133 | let repr_hints = lookup_repr_hints(cx, did); |
4134 | if repr_hints.len() > 1 { | |
4135 | // this is an error later on, but this type isn't safe | |
4136 | res = res | TC::ReachesFfiUnsafe; | |
4137 | } | |
4138 | ||
4139 | match repr_hints.get(0) { | |
4140 | Some(h) => if !h.is_ffi_safe() { | |
4141 | res = res | TC::ReachesFfiUnsafe; | |
4142 | }, | |
4143 | // ReprAny | |
4144 | None => { | |
4145 | res = res | TC::ReachesFfiUnsafe; | |
4146 | ||
4147 | // We allow ReprAny enums if they are eligible for | |
4148 | // the nullable pointer optimization and the | |
4149 | // contained type is an `extern fn` | |
4150 | ||
4151 | if variants.len() == 2 { | |
4152 | let mut data_idx = 0; | |
4153 | ||
9346a6ac | 4154 | if variants[0].args.is_empty() { |
1a4d82fc JJ |
4155 | data_idx = 1; |
4156 | } | |
4157 | ||
4158 | if variants[data_idx].args.len() == 1 { | |
4159 | match variants[data_idx].args[0].sty { | |
62682a34 | 4160 | TyBareFn(..) => { res = res - TC::ReachesFfiUnsafe; } |
1a4d82fc JJ |
4161 | _ => { } |
4162 | } | |
4163 | } | |
4164 | } | |
4165 | } | |
4166 | } | |
4167 | } | |
4168 | ||
4169 | ||
4170 | apply_lang_items(cx, did, res) | |
4171 | } | |
4172 | ||
62682a34 SL |
4173 | TyProjection(..) | |
4174 | TyParam(_) => { | |
1a4d82fc JJ |
4175 | TC::All |
4176 | } | |
4177 | ||
62682a34 SL |
4178 | TyInfer(_) | |
4179 | TyError => { | |
1a4d82fc JJ |
4180 | cx.sess.bug("asked to compute contents of error type"); |
4181 | } | |
4182 | }; | |
4183 | ||
4184 | cache.insert(ty, result); | |
4185 | result | |
4186 | } | |
4187 | ||
4188 | fn tc_mt<'tcx>(cx: &ctxt<'tcx>, | |
4189 | mt: mt<'tcx>, | |
4190 | cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents | |
4191 | { | |
4192 | let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable); | |
4193 | mc | tc_ty(cx, mt.ty, cache) | |
4194 | } | |
4195 | ||
4196 | fn apply_lang_items(cx: &ctxt, did: ast::DefId, tc: TypeContents) | |
4197 | -> TypeContents { | |
d9579d0f | 4198 | if Some(did) == cx.lang_items.unsafe_cell_type() { |
1a4d82fc JJ |
4199 | tc | TC::InteriorUnsafe |
4200 | } else { | |
4201 | tc | |
4202 | } | |
4203 | } | |
4204 | ||
4205 | /// Type contents due to containing a reference with the region `region` and borrow kind `bk` | |
4206 | fn borrowed_contents(region: ty::Region, | |
4207 | mutbl: ast::Mutability) | |
4208 | -> TypeContents { | |
4209 | let b = match mutbl { | |
4210 | ast::MutMutable => TC::ReachesMutable, | |
4211 | ast::MutImmutable => TC::None, | |
4212 | }; | |
4213 | b | (TC::ReachesBorrowed).when(region != ty::ReStatic) | |
4214 | } | |
4215 | ||
4216 | fn object_contents(bounds: &ExistentialBounds) -> TypeContents { | |
4217 | // These are the type contents of the (opaque) interior. We | |
4218 | // make no assumptions (other than that it cannot have an | |
4219 | // in-scope type parameter within, which makes no sense). | |
4220 | let mut tc = TC::All - TC::InteriorParam; | |
85aaf69f | 4221 | for bound in &bounds.builtin_bounds { |
1a4d82fc JJ |
4222 | tc = tc - match bound { |
4223 | BoundSync | BoundSend | BoundCopy => TC::None, | |
4224 | BoundSized => TC::Nonsized, | |
4225 | }; | |
4226 | } | |
4227 | return tc; | |
4228 | } | |
4229 | } | |
4230 | ||
62682a34 SL |
4231 | fn type_impls_bound<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>, |
4232 | tcx: &ty::ctxt<'tcx>, | |
1a4d82fc JJ |
4233 | ty: Ty<'tcx>, |
4234 | bound: ty::BuiltinBound, | |
4235 | span: Span) | |
4236 | -> bool | |
4237 | { | |
62682a34 SL |
4238 | let pe; |
4239 | let param_env = match param_env { | |
4240 | Some(e) => e, | |
4241 | None => { | |
4242 | pe = empty_parameter_environment(tcx); | |
4243 | &pe | |
1a4d82fc | 4244 | } |
62682a34 SL |
4245 | }; |
4246 | let infcx = infer::new_infer_ctxt(tcx); | |
1a4d82fc JJ |
4247 | |
4248 | let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound, span); | |
4249 | ||
62682a34 SL |
4250 | debug!("type_impls_bound({:?}, {:?}) = {:?}", |
4251 | ty, | |
1a4d82fc JJ |
4252 | bound, |
4253 | is_impld); | |
4254 | ||
1a4d82fc JJ |
4255 | is_impld |
4256 | } | |
4257 | ||
4258 | pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>, | |
4259 | span: Span, | |
4260 | ty: Ty<'tcx>) | |
4261 | -> bool | |
4262 | { | |
62682a34 SL |
4263 | if ty.flags.get().intersects(TypeFlags::MOVENESS_CACHED) { |
4264 | return ty.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT); | |
4265 | } | |
4266 | ||
4267 | assert!(!ty::type_needs_infer(ty)); | |
4268 | ||
4269 | // Fast-path for primitive types | |
4270 | let result = match ty.sty { | |
4271 | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | | |
4272 | TyRawPtr(..) | TyBareFn(..) | TyRef(_, mt { | |
4273 | mutbl: ast::MutImmutable, .. | |
4274 | }) => Some(false), | |
4275 | ||
4276 | TyStr | TyBox(..) | TyRef(_, mt { | |
4277 | mutbl: ast::MutMutable, .. | |
4278 | }) => Some(true), | |
4279 | ||
4280 | TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) | | |
4281 | TyClosure(..) | TyEnum(..) | TyStruct(..) | | |
4282 | TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None | |
4283 | }.unwrap_or_else(|| !type_impls_bound(Some(param_env), | |
4284 | param_env.tcx, | |
4285 | ty, | |
4286 | ty::BoundCopy, | |
4287 | span)); | |
4288 | ||
4289 | if !type_has_params(ty) && !type_has_self(ty) { | |
4290 | ty.flags.set(ty.flags.get() | if result { | |
4291 | TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT | |
4292 | } else { | |
4293 | TypeFlags::MOVENESS_CACHED | |
4294 | }); | |
4295 | } | |
4296 | ||
4297 | result | |
1a4d82fc JJ |
4298 | } |
4299 | ||
62682a34 SL |
4300 | #[inline] |
4301 | pub fn type_is_sized<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>, | |
4302 | tcx: &ty::ctxt<'tcx>, | |
1a4d82fc JJ |
4303 | span: Span, |
4304 | ty: Ty<'tcx>) | |
4305 | -> bool | |
4306 | { | |
62682a34 SL |
4307 | if ty.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) { |
4308 | let result = ty.flags.get().intersects(TypeFlags::IS_SIZED); | |
4309 | return result; | |
4310 | } | |
4311 | ||
4312 | type_is_sized_uncached(param_env, tcx, span, ty) | |
4313 | } | |
4314 | ||
4315 | fn type_is_sized_uncached<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>, | |
4316 | tcx: &ty::ctxt<'tcx>, | |
4317 | span: Span, | |
4318 | ty: Ty<'tcx>) -> bool { | |
4319 | assert!(!ty::type_needs_infer(ty)); | |
4320 | ||
4321 | // Fast-path for primitive types | |
4322 | let result = match ty.sty { | |
4323 | TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) | | |
4324 | TyBox(..) | TyRawPtr(..) | TyRef(..) | TyBareFn(..) | | |
4325 | TyArray(..) | TyTuple(..) | TyClosure(..) => Some(true), | |
4326 | ||
4327 | TyStr | TyTrait(..) | TySlice(_) => Some(false), | |
4328 | ||
4329 | TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) | | |
4330 | TyInfer(..) | TyError => None | |
4331 | }.unwrap_or_else(|| type_impls_bound(param_env, tcx, ty, ty::BoundSized, span)); | |
4332 | ||
4333 | if !type_has_params(ty) && !type_has_self(ty) { | |
4334 | ty.flags.set(ty.flags.get() | if result { | |
4335 | TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED | |
4336 | } else { | |
4337 | TypeFlags::SIZEDNESS_CACHED | |
4338 | }); | |
4339 | } | |
4340 | ||
4341 | result | |
1a4d82fc JJ |
4342 | } |
4343 | ||
4344 | pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool { | |
4345 | !type_contents(cx, ty).intersects(TC::ReachesFfiUnsafe) | |
4346 | } | |
4347 | ||
4348 | // True if instantiating an instance of `r_ty` requires an instance of `r_ty`. | |
4349 | pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool { | |
4350 | fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>, | |
4351 | r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool { | |
4352 | debug!("type_requires({:?}, {:?})?", | |
62682a34 | 4353 | r_ty, ty); |
1a4d82fc JJ |
4354 | |
4355 | let r = r_ty == ty || subtypes_require(cx, seen, r_ty, ty); | |
4356 | ||
4357 | debug!("type_requires({:?}, {:?})? {:?}", | |
62682a34 | 4358 | r_ty, ty, r); |
1a4d82fc JJ |
4359 | return r; |
4360 | } | |
4361 | ||
4362 | fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>, | |
4363 | r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool { | |
4364 | debug!("subtypes_require({:?}, {:?})?", | |
62682a34 | 4365 | r_ty, ty); |
1a4d82fc JJ |
4366 | |
4367 | let r = match ty.sty { | |
4368 | // fixed length vectors need special treatment compared to | |
4369 | // normal vectors, since they don't necessarily have the | |
4370 | // possibility to have length zero. | |
62682a34 SL |
4371 | TyArray(_, 0) => false, // don't need no contents |
4372 | TyArray(ty, _) => type_requires(cx, seen, r_ty, ty), | |
4373 | ||
4374 | TyBool | | |
4375 | TyChar | | |
4376 | TyInt(_) | | |
4377 | TyUint(_) | | |
4378 | TyFloat(_) | | |
4379 | TyStr | | |
4380 | TyBareFn(..) | | |
4381 | TyParam(_) | | |
4382 | TyProjection(_) | | |
4383 | TySlice(_) => { | |
1a4d82fc JJ |
4384 | false |
4385 | } | |
62682a34 | 4386 | TyBox(typ) => { |
1a4d82fc JJ |
4387 | type_requires(cx, seen, r_ty, typ) |
4388 | } | |
62682a34 | 4389 | TyRef(_, ref mt) => { |
1a4d82fc JJ |
4390 | type_requires(cx, seen, r_ty, mt.ty) |
4391 | } | |
4392 | ||
62682a34 | 4393 | TyRawPtr(..) => { |
1a4d82fc JJ |
4394 | false // unsafe ptrs can always be NULL |
4395 | } | |
4396 | ||
62682a34 | 4397 | TyTrait(..) => { |
1a4d82fc JJ |
4398 | false |
4399 | } | |
4400 | ||
62682a34 | 4401 | TyStruct(ref did, _) if seen.contains(did) => { |
1a4d82fc JJ |
4402 | false |
4403 | } | |
4404 | ||
62682a34 | 4405 | TyStruct(did, substs) => { |
1a4d82fc JJ |
4406 | seen.push(did); |
4407 | let fields = struct_fields(cx, did, substs); | |
4408 | let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty)); | |
4409 | seen.pop().unwrap(); | |
4410 | r | |
4411 | } | |
4412 | ||
62682a34 SL |
4413 | TyError | |
4414 | TyInfer(_) | | |
4415 | TyClosure(..) => { | |
1a4d82fc | 4416 | // this check is run on type definitions, so we don't expect to see |
85aaf69f SL |
4417 | // inference by-products or closure types |
4418 | cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty)) | |
1a4d82fc JJ |
4419 | } |
4420 | ||
62682a34 | 4421 | TyTuple(ref ts) => { |
1a4d82fc JJ |
4422 | ts.iter().any(|ty| type_requires(cx, seen, r_ty, *ty)) |
4423 | } | |
4424 | ||
62682a34 | 4425 | TyEnum(ref did, _) if seen.contains(did) => { |
1a4d82fc JJ |
4426 | false |
4427 | } | |
4428 | ||
62682a34 | 4429 | TyEnum(did, substs) => { |
1a4d82fc JJ |
4430 | seen.push(did); |
4431 | let vs = enum_variants(cx, did); | |
4432 | let r = !vs.is_empty() && vs.iter().all(|variant| { | |
4433 | variant.args.iter().any(|aty| { | |
4434 | let sty = aty.subst(cx, substs); | |
4435 | type_requires(cx, seen, r_ty, sty) | |
4436 | }) | |
4437 | }); | |
4438 | seen.pop().unwrap(); | |
4439 | r | |
4440 | } | |
4441 | }; | |
4442 | ||
4443 | debug!("subtypes_require({:?}, {:?})? {:?}", | |
62682a34 | 4444 | r_ty, ty, r); |
1a4d82fc JJ |
4445 | |
4446 | return r; | |
4447 | } | |
4448 | ||
4449 | let mut seen = Vec::new(); | |
4450 | !subtypes_require(cx, &mut seen, r_ty, r_ty) | |
4451 | } | |
4452 | ||
4453 | /// Describes whether a type is representable. For types that are not | |
4454 | /// representable, 'SelfRecursive' and 'ContainsRecursive' are used to | |
4455 | /// distinguish between types that are recursive with themselves and types that | |
4456 | /// contain a different recursive type. These cases can therefore be treated | |
4457 | /// differently when reporting errors. | |
4458 | /// | |
4459 | /// The ordering of the cases is significant. They are sorted so that cmp::max | |
4460 | /// will keep the "more erroneous" of two values. | |
c34b1796 | 4461 | #[derive(Copy, Clone, PartialOrd, Ord, Eq, PartialEq, Debug)] |
1a4d82fc JJ |
4462 | pub enum Representability { |
4463 | Representable, | |
4464 | ContainsRecursive, | |
4465 | SelfRecursive, | |
4466 | } | |
4467 | ||
4468 | /// Check whether a type is representable. This means it cannot contain unboxed | |
4469 | /// structural recursion. This check is needed for structs and enums. | |
4470 | pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>) | |
4471 | -> Representability { | |
4472 | ||
4473 | // Iterate until something non-representable is found | |
4474 | fn find_nonrepresentable<'tcx, It: Iterator<Item=Ty<'tcx>>>(cx: &ctxt<'tcx>, sp: Span, | |
4475 | seen: &mut Vec<Ty<'tcx>>, | |
4476 | iter: It) | |
4477 | -> Representability { | |
4478 | iter.fold(Representable, | |
4479 | |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty))) | |
4480 | } | |
4481 | ||
4482 | fn are_inner_types_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span, | |
4483 | seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>) | |
4484 | -> Representability { | |
4485 | match ty.sty { | |
62682a34 | 4486 | TyTuple(ref ts) => { |
85aaf69f | 4487 | find_nonrepresentable(cx, sp, seen, ts.iter().cloned()) |
1a4d82fc JJ |
4488 | } |
4489 | // Fixed-length vectors. | |
4490 | // FIXME(#11924) Behavior undecided for zero-length vectors. | |
62682a34 | 4491 | TyArray(ty, _) => { |
1a4d82fc JJ |
4492 | is_type_structurally_recursive(cx, sp, seen, ty) |
4493 | } | |
62682a34 | 4494 | TyStruct(did, substs) => { |
1a4d82fc JJ |
4495 | let fields = struct_fields(cx, did, substs); |
4496 | find_nonrepresentable(cx, sp, seen, fields.iter().map(|f| f.mt.ty)) | |
4497 | } | |
62682a34 | 4498 | TyEnum(did, substs) => { |
1a4d82fc JJ |
4499 | let vs = enum_variants(cx, did); |
4500 | let iter = vs.iter() | |
62682a34 | 4501 | .flat_map(|variant| &variant.args) |
1a4d82fc JJ |
4502 | .map(|aty| { aty.subst_spanned(cx, substs, Some(sp)) }); |
4503 | ||
4504 | find_nonrepresentable(cx, sp, seen, iter) | |
4505 | } | |
62682a34 | 4506 | TyClosure(..) => { |
85aaf69f SL |
4507 | // this check is run on type definitions, so we don't expect |
4508 | // to see closure types | |
4509 | cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty)) | |
1a4d82fc JJ |
4510 | } |
4511 | _ => Representable, | |
4512 | } | |
4513 | } | |
4514 | ||
4515 | fn same_struct_or_enum_def_id(ty: Ty, did: DefId) -> bool { | |
4516 | match ty.sty { | |
62682a34 | 4517 | TyStruct(ty_did, _) | TyEnum(ty_did, _) => { |
1a4d82fc JJ |
4518 | ty_did == did |
4519 | } | |
4520 | _ => false | |
4521 | } | |
4522 | } | |
4523 | ||
4524 | fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool { | |
4525 | match (&a.sty, &b.sty) { | |
62682a34 SL |
4526 | (&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) | |
4527 | (&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => { | |
1a4d82fc JJ |
4528 | if did_a != did_b { |
4529 | return false; | |
4530 | } | |
4531 | ||
4532 | let types_a = substs_a.types.get_slice(subst::TypeSpace); | |
4533 | let types_b = substs_b.types.get_slice(subst::TypeSpace); | |
4534 | ||
62682a34 | 4535 | let mut pairs = types_a.iter().zip(types_b); |
1a4d82fc JJ |
4536 | |
4537 | pairs.all(|(&a, &b)| same_type(a, b)) | |
4538 | } | |
4539 | _ => { | |
4540 | a == b | |
4541 | } | |
4542 | } | |
4543 | } | |
4544 | ||
4545 | // Does the type `ty` directly (without indirection through a pointer) | |
4546 | // contain any types on stack `seen`? | |
4547 | fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span, | |
4548 | seen: &mut Vec<Ty<'tcx>>, | |
4549 | ty: Ty<'tcx>) -> Representability { | |
62682a34 | 4550 | debug!("is_type_structurally_recursive: {:?}", ty); |
1a4d82fc JJ |
4551 | |
4552 | match ty.sty { | |
62682a34 | 4553 | TyStruct(did, _) | TyEnum(did, _) => { |
1a4d82fc JJ |
4554 | { |
4555 | // Iterate through stack of previously seen types. | |
4556 | let mut iter = seen.iter(); | |
4557 | ||
4558 | // The first item in `seen` is the type we are actually curious about. | |
4559 | // We want to return SelfRecursive if this type contains itself. | |
4560 | // It is important that we DON'T take generic parameters into account | |
4561 | // for this check, so that Bar<T> in this example counts as SelfRecursive: | |
4562 | // | |
4563 | // struct Foo; | |
4564 | // struct Bar<T> { x: Bar<Foo> } | |
4565 | ||
4566 | match iter.next() { | |
4567 | Some(&seen_type) => { | |
4568 | if same_struct_or_enum_def_id(seen_type, did) { | |
4569 | debug!("SelfRecursive: {:?} contains {:?}", | |
62682a34 SL |
4570 | seen_type, |
4571 | ty); | |
1a4d82fc JJ |
4572 | return SelfRecursive; |
4573 | } | |
4574 | } | |
4575 | None => {} | |
4576 | } | |
4577 | ||
4578 | // We also need to know whether the first item contains other types that | |
4579 | // are structurally recursive. If we don't catch this case, we will recurse | |
4580 | // infinitely for some inputs. | |
4581 | // | |
4582 | // It is important that we DO take generic parameters into account here, | |
4583 | // so that code like this is considered SelfRecursive, not ContainsRecursive: | |
4584 | // | |
4585 | // struct Foo { Option<Option<Foo>> } | |
4586 | ||
4587 | for &seen_type in iter { | |
4588 | if same_type(ty, seen_type) { | |
4589 | debug!("ContainsRecursive: {:?} contains {:?}", | |
62682a34 SL |
4590 | seen_type, |
4591 | ty); | |
1a4d82fc JJ |
4592 | return ContainsRecursive; |
4593 | } | |
4594 | } | |
4595 | } | |
4596 | ||
4597 | // For structs and enums, track all previously seen types by pushing them | |
4598 | // onto the 'seen' stack. | |
4599 | seen.push(ty); | |
4600 | let out = are_inner_types_recursive(cx, sp, seen, ty); | |
4601 | seen.pop(); | |
4602 | out | |
4603 | } | |
4604 | _ => { | |
4605 | // No need to push in other cases. | |
4606 | are_inner_types_recursive(cx, sp, seen, ty) | |
4607 | } | |
4608 | } | |
4609 | } | |
4610 | ||
62682a34 | 4611 | debug!("is_type_representable: {:?}", ty); |
1a4d82fc JJ |
4612 | |
4613 | // To avoid a stack overflow when checking an enum variant or struct that | |
4614 | // contains a different, structurally recursive type, maintain a stack | |
4615 | // of seen types and check recursion for each of them (issues #3008, #3779). | |
4616 | let mut seen: Vec<Ty> = Vec::new(); | |
4617 | let r = is_type_structurally_recursive(cx, sp, &mut seen, ty); | |
62682a34 | 4618 | debug!("is_type_representable: {:?} is {:?}", ty, r); |
1a4d82fc JJ |
4619 | r |
4620 | } | |
4621 | ||
4622 | pub fn type_is_trait(ty: Ty) -> bool { | |
1a4d82fc | 4623 | match ty.sty { |
62682a34 SL |
4624 | TyTrait(..) => true, |
4625 | _ => false | |
1a4d82fc JJ |
4626 | } |
4627 | } | |
4628 | ||
4629 | pub fn type_is_integral(ty: Ty) -> bool { | |
4630 | match ty.sty { | |
62682a34 | 4631 | TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true, |
1a4d82fc JJ |
4632 | _ => false |
4633 | } | |
4634 | } | |
4635 | ||
4636 | pub fn type_is_fresh(ty: Ty) -> bool { | |
4637 | match ty.sty { | |
62682a34 SL |
4638 | TyInfer(FreshTy(_)) => true, |
4639 | TyInfer(FreshIntTy(_)) => true, | |
4640 | TyInfer(FreshFloatTy(_)) => true, | |
1a4d82fc JJ |
4641 | _ => false |
4642 | } | |
4643 | } | |
4644 | ||
4645 | pub fn type_is_uint(ty: Ty) -> bool { | |
4646 | match ty.sty { | |
62682a34 | 4647 | TyInfer(IntVar(_)) | TyUint(ast::TyUs) => true, |
1a4d82fc JJ |
4648 | _ => false |
4649 | } | |
4650 | } | |
4651 | ||
4652 | pub fn type_is_char(ty: Ty) -> bool { | |
4653 | match ty.sty { | |
62682a34 | 4654 | TyChar => true, |
1a4d82fc JJ |
4655 | _ => false |
4656 | } | |
4657 | } | |
4658 | ||
4659 | pub fn type_is_bare_fn(ty: Ty) -> bool { | |
4660 | match ty.sty { | |
62682a34 | 4661 | TyBareFn(..) => true, |
1a4d82fc JJ |
4662 | _ => false |
4663 | } | |
4664 | } | |
4665 | ||
4666 | pub fn type_is_bare_fn_item(ty: Ty) -> bool { | |
4667 | match ty.sty { | |
62682a34 | 4668 | TyBareFn(Some(_), _) => true, |
1a4d82fc JJ |
4669 | _ => false |
4670 | } | |
4671 | } | |
4672 | ||
4673 | pub fn type_is_fp(ty: Ty) -> bool { | |
4674 | match ty.sty { | |
62682a34 | 4675 | TyInfer(FloatVar(_)) | TyFloat(_) => true, |
1a4d82fc JJ |
4676 | _ => false |
4677 | } | |
4678 | } | |
4679 | ||
4680 | pub fn type_is_numeric(ty: Ty) -> bool { | |
4681 | return type_is_integral(ty) || type_is_fp(ty); | |
4682 | } | |
4683 | ||
4684 | pub fn type_is_signed(ty: Ty) -> bool { | |
4685 | match ty.sty { | |
62682a34 | 4686 | TyInt(_) => true, |
1a4d82fc JJ |
4687 | _ => false |
4688 | } | |
4689 | } | |
4690 | ||
4691 | pub fn type_is_machine(ty: Ty) -> bool { | |
4692 | match ty.sty { | |
62682a34 SL |
4693 | TyInt(ast::TyIs) | TyUint(ast::TyUs) => false, |
4694 | TyInt(..) | TyUint(..) | TyFloat(..) => true, | |
1a4d82fc JJ |
4695 | _ => false |
4696 | } | |
4697 | } | |
4698 | ||
4699 | // Whether a type is enum like, that is an enum type with only nullary | |
4700 | // constructors | |
4701 | pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool { | |
4702 | match ty.sty { | |
62682a34 | 4703 | TyEnum(did, _) => { |
1a4d82fc | 4704 | let variants = enum_variants(cx, did); |
9346a6ac | 4705 | if variants.is_empty() { |
1a4d82fc JJ |
4706 | false |
4707 | } else { | |
9346a6ac | 4708 | variants.iter().all(|v| v.args.is_empty()) |
1a4d82fc JJ |
4709 | } |
4710 | } | |
4711 | _ => false | |
4712 | } | |
4713 | } | |
4714 | ||
4715 | // Returns the type and mutability of *ty. | |
4716 | // | |
4717 | // The parameter `explicit` indicates if this is an *explicit* dereference. | |
4718 | // Some types---notably unsafe ptrs---can only be dereferenced explicitly. | |
4719 | pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> { | |
4720 | match ty.sty { | |
62682a34 | 4721 | TyBox(ty) => { |
1a4d82fc JJ |
4722 | Some(mt { |
4723 | ty: ty, | |
4724 | mutbl: ast::MutImmutable, | |
4725 | }) | |
4726 | }, | |
62682a34 SL |
4727 | TyRef(_, mt) => Some(mt), |
4728 | TyRawPtr(mt) if explicit => Some(mt), | |
1a4d82fc JJ |
4729 | _ => None |
4730 | } | |
4731 | } | |
4732 | ||
1a4d82fc JJ |
4733 | pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> { |
4734 | match ty.sty { | |
62682a34 SL |
4735 | TyBox(ty) => ty, |
4736 | TyRef(_, mt) | TyRawPtr(mt) => mt.ty, | |
1a4d82fc JJ |
4737 | _ => ty |
4738 | } | |
4739 | } | |
4740 | ||
1a4d82fc JJ |
4741 | // Returns the type of ty[i] |
4742 | pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> { | |
4743 | match ty.sty { | |
62682a34 | 4744 | TyArray(ty, _) | TySlice(ty) => Some(ty), |
1a4d82fc JJ |
4745 | _ => None |
4746 | } | |
4747 | } | |
4748 | ||
4749 | // Returns the type of elements contained within an 'array-like' type. | |
4750 | // This is exactly the same as the above, except it supports strings, | |
4751 | // which can't actually be indexed. | |
4752 | pub fn array_element_ty<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> { | |
4753 | match ty.sty { | |
62682a34 SL |
4754 | TyArray(ty, _) | TySlice(ty) => Some(ty), |
4755 | TyStr => Some(tcx.types.u8), | |
1a4d82fc JJ |
4756 | _ => None |
4757 | } | |
4758 | } | |
4759 | ||
4760 | /// Returns the type of element at index `i` in tuple or tuple-like type `t`. | |
4761 | /// For an enum `t`, `variant` is None only if `t` is a univariant enum. | |
4762 | pub fn positional_element_ty<'tcx>(cx: &ctxt<'tcx>, | |
4763 | ty: Ty<'tcx>, | |
c34b1796 | 4764 | i: usize, |
1a4d82fc JJ |
4765 | variant: Option<ast::DefId>) -> Option<Ty<'tcx>> { |
4766 | ||
4767 | match (&ty.sty, variant) { | |
62682a34 | 4768 | (&TyTuple(ref v), None) => v.get(i).cloned(), |
1a4d82fc JJ |
4769 | |
4770 | ||
62682a34 | 4771 | (&TyStruct(def_id, substs), None) => lookup_struct_fields(cx, def_id) |
1a4d82fc JJ |
4772 | .get(i) |
4773 | .map(|&t|lookup_item_type(cx, t.id).ty.subst(cx, substs)), | |
4774 | ||
62682a34 | 4775 | (&TyEnum(def_id, substs), Some(variant_def_id)) => { |
1a4d82fc JJ |
4776 | let variant_info = enum_variant_with_id(cx, def_id, variant_def_id); |
4777 | variant_info.args.get(i).map(|t|t.subst(cx, substs)) | |
4778 | } | |
4779 | ||
62682a34 | 4780 | (&TyEnum(def_id, substs), None) => { |
1a4d82fc JJ |
4781 | assert!(enum_is_univariant(cx, def_id)); |
4782 | let enum_variants = enum_variants(cx, def_id); | |
4783 | let variant_info = &(*enum_variants)[0]; | |
4784 | variant_info.args.get(i).map(|t|t.subst(cx, substs)) | |
4785 | } | |
4786 | ||
4787 | _ => None | |
4788 | } | |
4789 | } | |
4790 | ||
4791 | /// Returns the type of element at field `n` in struct or struct-like type `t`. | |
4792 | /// For an enum `t`, `variant` must be some def id. | |
4793 | pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>, | |
4794 | ty: Ty<'tcx>, | |
4795 | n: ast::Name, | |
4796 | variant: Option<ast::DefId>) -> Option<Ty<'tcx>> { | |
4797 | ||
4798 | match (&ty.sty, variant) { | |
62682a34 | 4799 | (&TyStruct(def_id, substs), None) => { |
1a4d82fc JJ |
4800 | let r = lookup_struct_fields(cx, def_id); |
4801 | r.iter().find(|f| f.name == n) | |
4802 | .map(|&f| lookup_field_type(cx, def_id, f.id, substs)) | |
4803 | } | |
62682a34 | 4804 | (&TyEnum(def_id, substs), Some(variant_def_id)) => { |
1a4d82fc JJ |
4805 | let variant_info = enum_variant_with_id(cx, def_id, variant_def_id); |
4806 | variant_info.arg_names.as_ref() | |
4807 | .expect("must have struct enum variant if accessing a named fields") | |
62682a34 | 4808 | .iter().zip(&variant_info.args) |
9346a6ac AL |
4809 | .find(|&(&name, _)| name == n) |
4810 | .map(|(_name, arg_t)| arg_t.subst(cx, substs)) | |
1a4d82fc JJ |
4811 | } |
4812 | _ => None | |
4813 | } | |
4814 | } | |
4815 | ||
1a4d82fc | 4816 | pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> { |
85aaf69f | 4817 | match node_id_to_type_opt(cx, id) { |
1a4d82fc JJ |
4818 | Some(ty) => ty, |
4819 | None => cx.sess.bug( | |
4820 | &format!("node_id_to_type: no type for node `{}`", | |
c34b1796 | 4821 | cx.map.node_to_string(id))) |
1a4d82fc JJ |
4822 | } |
4823 | } | |
4824 | ||
4825 | pub fn node_id_to_type_opt<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Option<Ty<'tcx>> { | |
4826 | match cx.node_types.borrow().get(&id) { | |
4827 | Some(&ty) => Some(ty), | |
4828 | None => None | |
4829 | } | |
4830 | } | |
4831 | ||
4832 | pub fn node_id_item_substs<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> ItemSubsts<'tcx> { | |
4833 | match cx.item_substs.borrow().get(&id) { | |
4834 | None => ItemSubsts::empty(), | |
4835 | Some(ts) => ts.clone(), | |
4836 | } | |
4837 | } | |
4838 | ||
4839 | pub fn fn_is_variadic(fty: Ty) -> bool { | |
4840 | match fty.sty { | |
62682a34 | 4841 | TyBareFn(_, ref f) => f.sig.0.variadic, |
1a4d82fc JJ |
4842 | ref s => { |
4843 | panic!("fn_is_variadic() called on non-fn type: {:?}", s) | |
4844 | } | |
4845 | } | |
4846 | } | |
4847 | ||
4848 | pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> { | |
4849 | match fty.sty { | |
62682a34 | 4850 | TyBareFn(_, ref f) => &f.sig, |
1a4d82fc JJ |
4851 | ref s => { |
4852 | panic!("ty_fn_sig() called on non-fn type: {:?}", s) | |
4853 | } | |
4854 | } | |
4855 | } | |
4856 | ||
4857 | /// Returns the ABI of the given function. | |
4858 | pub fn ty_fn_abi(fty: Ty) -> abi::Abi { | |
4859 | match fty.sty { | |
62682a34 | 4860 | TyBareFn(_, ref f) => f.abi, |
1a4d82fc JJ |
4861 | _ => panic!("ty_fn_abi() called on non-fn type"), |
4862 | } | |
4863 | } | |
4864 | ||
4865 | // Type accessors for substructures of types | |
4866 | pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> ty::Binder<Vec<Ty<'tcx>>> { | |
4867 | ty_fn_sig(fty).inputs() | |
4868 | } | |
4869 | ||
1a4d82fc JJ |
4870 | pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> Binder<FnOutput<'tcx>> { |
4871 | match fty.sty { | |
62682a34 | 4872 | TyBareFn(_, ref f) => f.sig.output(), |
1a4d82fc JJ |
4873 | ref s => { |
4874 | panic!("ty_fn_ret() called on non-fn type: {:?}", s) | |
4875 | } | |
4876 | } | |
4877 | } | |
4878 | ||
4879 | pub fn is_fn_ty(fty: Ty) -> bool { | |
4880 | match fty.sty { | |
62682a34 | 4881 | TyBareFn(..) => true, |
1a4d82fc JJ |
4882 | _ => false |
4883 | } | |
4884 | } | |
4885 | ||
4886 | pub fn ty_region(tcx: &ctxt, | |
4887 | span: Span, | |
4888 | ty: Ty) -> Region { | |
4889 | match ty.sty { | |
62682a34 | 4890 | TyRef(r, _) => *r, |
1a4d82fc JJ |
4891 | ref s => { |
4892 | tcx.sess.span_bug( | |
4893 | span, | |
4894 | &format!("ty_region() invoked on an inappropriate ty: {:?}", | |
c34b1796 | 4895 | s)); |
1a4d82fc JJ |
4896 | } |
4897 | } | |
4898 | } | |
4899 | ||
85aaf69f SL |
4900 | pub fn free_region_from_def(outlives_extent: region::DestructionScopeData, |
4901 | def: &RegionParameterDef) | |
1a4d82fc JJ |
4902 | -> ty::Region |
4903 | { | |
85aaf69f SL |
4904 | let ret = |
4905 | ty::ReFree(ty::FreeRegion { scope: outlives_extent, | |
4906 | bound_region: ty::BrNamed(def.def_id, | |
4907 | def.name) }); | |
4908 | debug!("free_region_from_def returns {:?}", ret); | |
4909 | ret | |
1a4d82fc JJ |
4910 | } |
4911 | ||
4912 | // Returns the type of a pattern as a monotype. Like @expr_ty, this function | |
4913 | // doesn't provide type parameter substitutions. | |
4914 | pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> { | |
4915 | return node_id_to_type(cx, pat.id); | |
4916 | } | |
c34b1796 AL |
4917 | pub fn pat_ty_opt<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Option<Ty<'tcx>> { |
4918 | return node_id_to_type_opt(cx, pat.id); | |
4919 | } | |
1a4d82fc JJ |
4920 | |
4921 | ||
4922 | // Returns the type of an expression as a monotype. | |
4923 | // | |
4924 | // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in | |
4925 | // some cases, we insert `AutoAdjustment` annotations such as auto-deref or | |
4926 | // auto-ref. The type returned by this function does not consider such | |
4927 | // adjustments. See `expr_ty_adjusted()` instead. | |
4928 | // | |
4929 | // NB (2): This type doesn't provide type parameter substitutions; e.g. if you | |
c34b1796 AL |
4930 | // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" |
4931 | // instead of "fn(ty) -> T with T = isize". | |
1a4d82fc JJ |
4932 | pub fn expr_ty<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> { |
4933 | return node_id_to_type(cx, expr.id); | |
4934 | } | |
4935 | ||
4936 | pub fn expr_ty_opt<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Option<Ty<'tcx>> { | |
4937 | return node_id_to_type_opt(cx, expr.id); | |
4938 | } | |
4939 | ||
4940 | /// Returns the type of `expr`, considering any `AutoAdjustment` | |
4941 | /// entry recorded for that expression. | |
4942 | /// | |
4943 | /// It would almost certainly be better to store the adjusted ty in with | |
4944 | /// the `AutoAdjustment`, but I opted not to do this because it would | |
4945 | /// require serializing and deserializing the type and, although that's not | |
4946 | /// hard to do, I just hate that code so much I didn't want to touch it | |
4947 | /// unless it was to fix it properly, which seemed a distraction from the | |
bd371182 | 4948 | /// thread at hand! -nmatsakis |
1a4d82fc JJ |
4949 | pub fn expr_ty_adjusted<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> { |
4950 | adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr), | |
4951 | cx.adjustments.borrow().get(&expr.id), | |
4952 | |method_call| cx.method_map.borrow().get(&method_call).map(|method| method.ty)) | |
4953 | } | |
4954 | ||
4955 | pub fn expr_span(cx: &ctxt, id: NodeId) -> Span { | |
4956 | match cx.map.find(id) { | |
4957 | Some(ast_map::NodeExpr(e)) => { | |
4958 | e.span | |
4959 | } | |
4960 | Some(f) => { | |
4961 | cx.sess.bug(&format!("Node id {} is not an expr: {:?}", | |
4962 | id, | |
c34b1796 | 4963 | f)); |
1a4d82fc JJ |
4964 | } |
4965 | None => { | |
4966 | cx.sess.bug(&format!("Node id {} is not present \ | |
c34b1796 | 4967 | in the node map", id)); |
1a4d82fc JJ |
4968 | } |
4969 | } | |
4970 | } | |
4971 | ||
4972 | pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString { | |
4973 | match cx.map.find(id) { | |
4974 | Some(ast_map::NodeLocal(pat)) => { | |
4975 | match pat.node { | |
4976 | ast::PatIdent(_, ref path1, _) => { | |
4977 | token::get_ident(path1.node) | |
4978 | } | |
4979 | _ => { | |
4980 | cx.sess.bug( | |
4981 | &format!("Variable id {} maps to {:?}, not local", | |
4982 | id, | |
c34b1796 | 4983 | pat)); |
1a4d82fc JJ |
4984 | } |
4985 | } | |
4986 | } | |
4987 | r => { | |
4988 | cx.sess.bug(&format!("Variable id {} maps to {:?}, not local", | |
4989 | id, | |
c34b1796 | 4990 | r)); |
1a4d82fc JJ |
4991 | } |
4992 | } | |
4993 | } | |
4994 | ||
4995 | /// See `expr_ty_adjusted` | |
4996 | pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>, | |
4997 | span: Span, | |
4998 | expr_id: ast::NodeId, | |
4999 | unadjusted_ty: Ty<'tcx>, | |
5000 | adjustment: Option<&AutoAdjustment<'tcx>>, | |
5001 | mut method_type: F) | |
5002 | -> Ty<'tcx> where | |
5003 | F: FnMut(MethodCall) -> Option<Ty<'tcx>>, | |
5004 | { | |
62682a34 | 5005 | if let TyError = unadjusted_ty.sty { |
1a4d82fc JJ |
5006 | return unadjusted_ty; |
5007 | } | |
5008 | ||
5009 | return match adjustment { | |
5010 | Some(adjustment) => { | |
5011 | match *adjustment { | |
9346a6ac | 5012 | AdjustReifyFnPointer => { |
1a4d82fc | 5013 | match unadjusted_ty.sty { |
62682a34 | 5014 | ty::TyBareFn(Some(_), b) => { |
1a4d82fc JJ |
5015 | ty::mk_bare_fn(cx, None, b) |
5016 | } | |
9346a6ac | 5017 | _ => { |
1a4d82fc JJ |
5018 | cx.sess.bug( |
5019 | &format!("AdjustReifyFnPointer adjustment on non-fn-item: \ | |
62682a34 | 5020 | {:?}", unadjusted_ty)); |
1a4d82fc JJ |
5021 | } |
5022 | } | |
5023 | } | |
5024 | ||
c34b1796 AL |
5025 | AdjustUnsafeFnPointer => { |
5026 | match unadjusted_ty.sty { | |
62682a34 | 5027 | ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b), |
c34b1796 AL |
5028 | ref b => { |
5029 | cx.sess.bug( | |
5030 | &format!("AdjustReifyFnPointer adjustment on non-fn-item: \ | |
5031 | {:?}", | |
5032 | b)); | |
5033 | } | |
5034 | } | |
5035 | } | |
5036 | ||
1a4d82fc JJ |
5037 | AdjustDerefRef(ref adj) => { |
5038 | let mut adjusted_ty = unadjusted_ty; | |
5039 | ||
5040 | if !ty::type_is_error(adjusted_ty) { | |
85aaf69f | 5041 | for i in 0..adj.autoderefs { |
9346a6ac | 5042 | let method_call = MethodCall::autoderef(expr_id, i as u32); |
1a4d82fc JJ |
5043 | match method_type(method_call) { |
5044 | Some(method_ty) => { | |
9346a6ac AL |
5045 | // Overloaded deref operators have all late-bound |
5046 | // regions fully instantiated and coverge. | |
1a4d82fc | 5047 | let fn_ret = |
85aaf69f SL |
5048 | ty::no_late_bound_regions(cx, |
5049 | &ty_fn_ret(method_ty)).unwrap(); | |
1a4d82fc JJ |
5050 | adjusted_ty = fn_ret.unwrap(); |
5051 | } | |
5052 | None => {} | |
5053 | } | |
5054 | match deref(adjusted_ty, true) { | |
5055 | Some(mt) => { adjusted_ty = mt.ty; } | |
5056 | None => { | |
5057 | cx.sess.span_bug( | |
5058 | span, | |
9346a6ac | 5059 | &format!("the {}th autoderef failed: {}", |
1a4d82fc | 5060 | i, |
62682a34 | 5061 | adjusted_ty) |
c34b1796 | 5062 | ); |
1a4d82fc JJ |
5063 | } |
5064 | } | |
5065 | } | |
5066 | } | |
5067 | ||
9346a6ac AL |
5068 | if let Some(target) = adj.unsize { |
5069 | target | |
5070 | } else { | |
5071 | adjust_ty_for_autoref(cx, adjusted_ty, adj.autoref) | |
5072 | } | |
1a4d82fc JJ |
5073 | } |
5074 | } | |
5075 | } | |
5076 | None => unadjusted_ty | |
5077 | }; | |
5078 | } | |
5079 | ||
5080 | pub fn adjust_ty_for_autoref<'tcx>(cx: &ctxt<'tcx>, | |
1a4d82fc | 5081 | ty: Ty<'tcx>, |
9346a6ac AL |
5082 | autoref: Option<AutoRef<'tcx>>) |
5083 | -> Ty<'tcx> { | |
1a4d82fc JJ |
5084 | match autoref { |
5085 | None => ty, | |
9346a6ac AL |
5086 | Some(AutoPtr(r, m)) => { |
5087 | mk_rptr(cx, r, mt { ty: ty, mutbl: m }) | |
1a4d82fc | 5088 | } |
9346a6ac AL |
5089 | Some(AutoUnsafe(m)) => { |
5090 | mk_ptr(cx, mt { ty: ty, mutbl: m }) | |
c34b1796 | 5091 | } |
1a4d82fc JJ |
5092 | } |
5093 | } | |
5094 | ||
5095 | pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def { | |
5096 | match tcx.def_map.borrow().get(&expr.id) { | |
c34b1796 | 5097 | Some(def) => def.full_def(), |
223e47cc | 5098 | None => { |
1a4d82fc | 5099 | tcx.sess.span_bug(expr.span, &format!( |
c34b1796 | 5100 | "no def-map entry for expr {}", expr.id)); |
1a4d82fc JJ |
5101 | } |
5102 | } | |
5103 | } | |
5104 | ||
62682a34 SL |
5105 | pub fn expr_is_lval(tcx: &ctxt, expr: &ast::Expr) -> bool { |
5106 | match expr.node { | |
c34b1796 | 5107 | ast::ExprPath(..) => { |
62682a34 SL |
5108 | // We can't use resolve_expr here, as this needs to run on broken |
5109 | // programs. We don't need to through - associated items are all | |
5110 | // rvalues. | |
5111 | match tcx.def_map.borrow().get(&expr.id) { | |
5112 | Some(&def::PathResolution { | |
5113 | base_def: def::DefStatic(..), .. | |
5114 | }) | Some(&def::PathResolution { | |
5115 | base_def: def::DefUpvar(..), .. | |
5116 | }) | Some(&def::PathResolution { | |
5117 | base_def: def::DefLocal(..), .. | |
5118 | }) => { | |
5119 | true | |
1a4d82fc JJ |
5120 | } |
5121 | ||
62682a34 | 5122 | Some(..) => false, |
1a4d82fc | 5123 | |
62682a34 SL |
5124 | None => tcx.sess.span_bug(expr.span, &format!( |
5125 | "no def for path {}", expr.id)) | |
1a4d82fc JJ |
5126 | } |
5127 | } | |
5128 | ||
5129 | ast::ExprUnary(ast::UnDeref, _) | | |
5130 | ast::ExprField(..) | | |
5131 | ast::ExprTupField(..) | | |
5132 | ast::ExprIndex(..) => { | |
62682a34 | 5133 | true |
1a4d82fc JJ |
5134 | } |
5135 | ||
5136 | ast::ExprCall(..) | | |
5137 | ast::ExprMethodCall(..) | | |
5138 | ast::ExprStruct(..) | | |
5139 | ast::ExprRange(..) | | |
5140 | ast::ExprTup(..) | | |
5141 | ast::ExprIf(..) | | |
5142 | ast::ExprMatch(..) | | |
5143 | ast::ExprClosure(..) | | |
5144 | ast::ExprBlock(..) | | |
5145 | ast::ExprRepeat(..) | | |
62682a34 | 5146 | ast::ExprVec(..) | |
1a4d82fc JJ |
5147 | ast::ExprBreak(..) | |
5148 | ast::ExprAgain(..) | | |
5149 | ast::ExprRet(..) | | |
5150 | ast::ExprWhile(..) | | |
5151 | ast::ExprLoop(..) | | |
5152 | ast::ExprAssign(..) | | |
5153 | ast::ExprInlineAsm(..) | | |
62682a34 SL |
5154 | ast::ExprAssignOp(..) | |
5155 | ast::ExprLit(_) | | |
1a4d82fc | 5156 | ast::ExprUnary(..) | |
62682a34 | 5157 | ast::ExprBox(..) | |
1a4d82fc | 5158 | ast::ExprAddrOf(..) | |
c34b1796 AL |
5159 | ast::ExprBinary(..) | |
5160 | ast::ExprCast(..) => { | |
62682a34 | 5161 | false |
1a4d82fc JJ |
5162 | } |
5163 | ||
62682a34 | 5164 | ast::ExprParen(ref e) => expr_is_lval(tcx, e), |
1a4d82fc | 5165 | |
62682a34 SL |
5166 | ast::ExprIfLet(..) | |
5167 | ast::ExprWhileLet(..) | | |
5168 | ast::ExprForLoop(..) | | |
1a4d82fc JJ |
5169 | ast::ExprMac(..) => { |
5170 | tcx.sess.span_bug( | |
5171 | expr.span, | |
5172 | "macro expression remains after expansion"); | |
5173 | } | |
5174 | } | |
5175 | } | |
5176 | ||
5177 | pub fn stmt_node_id(s: &ast::Stmt) -> ast::NodeId { | |
5178 | match s.node { | |
5179 | ast::StmtDecl(_, id) | StmtExpr(_, id) | StmtSemi(_, id) => { | |
5180 | return id; | |
5181 | } | |
5182 | ast::StmtMac(..) => panic!("unexpanded macro in trans") | |
5183 | } | |
5184 | } | |
5185 | ||
5186 | pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field]) | |
c34b1796 | 5187 | -> usize { |
85aaf69f SL |
5188 | let mut i = 0; |
5189 | for f in fields { if f.name == name { return i; } i += 1; } | |
1a4d82fc JJ |
5190 | tcx.sess.bug(&format!( |
5191 | "no field named `{}` found in the list of fields `{:?}`", | |
5192 | token::get_name(name), | |
5193 | fields.iter() | |
85aaf69f | 5194 | .map(|f| token::get_name(f.name).to_string()) |
c34b1796 | 5195 | .collect::<Vec<String>>())); |
1a4d82fc JJ |
5196 | } |
5197 | ||
5198 | pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem]) | |
c34b1796 | 5199 | -> Option<usize> { |
1a4d82fc JJ |
5200 | trait_items.iter().position(|m| m.name() == id) |
5201 | } | |
5202 | ||
62682a34 | 5203 | pub fn ty_sort_string(cx: &ctxt, ty: Ty) -> String { |
1a4d82fc | 5204 | match ty.sty { |
62682a34 SL |
5205 | TyBool | TyChar | TyInt(_) | |
5206 | TyUint(_) | TyFloat(_) | TyStr => ty.to_string(), | |
5207 | TyTuple(ref tys) if tys.is_empty() => ty.to_string(), | |
5208 | ||
5209 | TyEnum(id, _) => format!("enum `{}`", item_path_str(cx, id)), | |
5210 | TyBox(_) => "box".to_string(), | |
5211 | TyArray(_, n) => format!("array of {} elements", n), | |
5212 | TySlice(_) => "slice".to_string(), | |
5213 | TyRawPtr(_) => "*-ptr".to_string(), | |
5214 | TyRef(_, _) => "&-ptr".to_string(), | |
5215 | TyBareFn(Some(_), _) => format!("fn item"), | |
5216 | TyBareFn(None, _) => "fn pointer".to_string(), | |
5217 | TyTrait(ref inner) => { | |
1a4d82fc JJ |
5218 | format!("trait {}", item_path_str(cx, inner.principal_def_id())) |
5219 | } | |
62682a34 | 5220 | TyStruct(id, _) => { |
85aaf69f | 5221 | format!("struct `{}`", item_path_str(cx, id)) |
1a4d82fc | 5222 | } |
62682a34 SL |
5223 | TyClosure(..) => "closure".to_string(), |
5224 | TyTuple(_) => "tuple".to_string(), | |
5225 | TyInfer(TyVar(_)) => "inferred type".to_string(), | |
5226 | TyInfer(IntVar(_)) => "integral variable".to_string(), | |
5227 | TyInfer(FloatVar(_)) => "floating-point variable".to_string(), | |
5228 | TyInfer(FreshTy(_)) => "skolemized type".to_string(), | |
5229 | TyInfer(FreshIntTy(_)) => "skolemized integral type".to_string(), | |
5230 | TyInfer(FreshFloatTy(_)) => "skolemized floating-point type".to_string(), | |
5231 | TyProjection(_) => "associated type".to_string(), | |
5232 | TyParam(ref p) => { | |
1a4d82fc JJ |
5233 | if p.space == subst::SelfSpace { |
5234 | "Self".to_string() | |
5235 | } else { | |
5236 | "type parameter".to_string() | |
5237 | } | |
5238 | } | |
62682a34 | 5239 | TyError => "type error".to_string(), |
1a4d82fc JJ |
5240 | } |
5241 | } | |
5242 | ||
5243 | /// Explains the source of a type err in a short, human readable way. This is meant to be placed | |
5244 | /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()` | |
5245 | /// afterwards to present additional details, particularly when it comes to lifetime-related | |
5246 | /// errors. | |
62682a34 SL |
5247 | impl<'tcx> fmt::Display for type_err<'tcx> { |
5248 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
5249 | match *self { | |
5250 | terr_cyclic_ty => write!(f, "cyclic type of infinite size"), | |
5251 | terr_mismatch => write!(f, "types differ"), | |
5252 | terr_unsafety_mismatch(values) => { | |
5253 | write!(f, "expected {} fn, found {} fn", | |
5254 | values.expected, | |
5255 | values.found) | |
5256 | } | |
5257 | terr_abi_mismatch(values) => { | |
5258 | write!(f, "expected {} fn, found {} fn", | |
5259 | values.expected, | |
5260 | values.found) | |
5261 | } | |
5262 | terr_mutability => write!(f, "values differ in mutability"), | |
5263 | terr_box_mutability => { | |
5264 | write!(f, "boxed values differ in mutability") | |
5265 | } | |
5266 | terr_vec_mutability => write!(f, "vectors differ in mutability"), | |
5267 | terr_ptr_mutability => write!(f, "pointers differ in mutability"), | |
5268 | terr_ref_mutability => write!(f, "references differ in mutability"), | |
5269 | terr_ty_param_size(values) => { | |
5270 | write!(f, "expected a type with {} type params, \ | |
5271 | found one with {} type params", | |
5272 | values.expected, | |
5273 | values.found) | |
5274 | } | |
5275 | terr_fixed_array_size(values) => { | |
5276 | write!(f, "expected an array with a fixed size of {} elements, \ | |
5277 | found one with {} elements", | |
5278 | values.expected, | |
5279 | values.found) | |
5280 | } | |
5281 | terr_tuple_size(values) => { | |
5282 | write!(f, "expected a tuple with {} elements, \ | |
5283 | found one with {} elements", | |
5284 | values.expected, | |
5285 | values.found) | |
5286 | } | |
5287 | terr_arg_count => { | |
5288 | write!(f, "incorrect number of function parameters") | |
5289 | } | |
5290 | terr_regions_does_not_outlive(..) => { | |
5291 | write!(f, "lifetime mismatch") | |
5292 | } | |
5293 | terr_regions_not_same(..) => { | |
5294 | write!(f, "lifetimes are not the same") | |
5295 | } | |
5296 | terr_regions_no_overlap(..) => { | |
5297 | write!(f, "lifetimes do not intersect") | |
5298 | } | |
5299 | terr_regions_insufficiently_polymorphic(br, _) => { | |
5300 | write!(f, "expected bound lifetime parameter {}, \ | |
5301 | found concrete lifetime", br) | |
5302 | } | |
5303 | terr_regions_overly_polymorphic(br, _) => { | |
5304 | write!(f, "expected concrete lifetime, \ | |
5305 | found bound lifetime parameter {}", br) | |
5306 | } | |
5307 | terr_sorts(values) => tls::with(|tcx| { | |
5308 | // A naive approach to making sure that we're not reporting silly errors such as: | |
5309 | // (expected closure, found closure). | |
5310 | let expected_str = ty_sort_string(tcx, values.expected); | |
5311 | let found_str = ty_sort_string(tcx, values.found); | |
5312 | if expected_str == found_str { | |
5313 | write!(f, "expected {}, found a different {}", expected_str, found_str) | |
5314 | } else { | |
5315 | write!(f, "expected {}, found {}", expected_str, found_str) | |
5316 | } | |
5317 | }), | |
5318 | terr_traits(values) => tls::with(|tcx| { | |
5319 | write!(f, "expected trait `{}`, found trait `{}`", | |
5320 | item_path_str(tcx, values.expected), | |
5321 | item_path_str(tcx, values.found)) | |
5322 | }), | |
5323 | terr_builtin_bounds(values) => { | |
5324 | if values.expected.is_empty() { | |
5325 | write!(f, "expected no bounds, found `{}`", | |
5326 | values.found) | |
5327 | } else if values.found.is_empty() { | |
5328 | write!(f, "expected bounds `{}`, found no bounds", | |
5329 | values.expected) | |
5330 | } else { | |
5331 | write!(f, "expected bounds `{}`, found bounds `{}`", | |
5332 | values.expected, | |
5333 | values.found) | |
5334 | } | |
1a4d82fc | 5335 | } |
62682a34 SL |
5336 | terr_integer_as_char => { |
5337 | write!(f, "expected an integral type, found `char`") | |
5338 | } | |
5339 | terr_int_mismatch(ref values) => { | |
5340 | write!(f, "expected `{:?}`, found `{:?}`", | |
5341 | values.expected, | |
5342 | values.found) | |
5343 | } | |
5344 | terr_float_mismatch(ref values) => { | |
5345 | write!(f, "expected `{:?}`, found `{:?}`", | |
5346 | values.expected, | |
5347 | values.found) | |
5348 | } | |
5349 | terr_variadic_mismatch(ref values) => { | |
5350 | write!(f, "expected {} fn, found {} function", | |
5351 | if values.expected { "variadic" } else { "non-variadic" }, | |
5352 | if values.found { "variadic" } else { "non-variadic" }) | |
5353 | } | |
5354 | terr_convergence_mismatch(ref values) => { | |
5355 | write!(f, "expected {} fn, found {} function", | |
5356 | if values.expected { "converging" } else { "diverging" }, | |
5357 | if values.found { "converging" } else { "diverging" }) | |
5358 | } | |
5359 | terr_projection_name_mismatched(ref values) => { | |
5360 | write!(f, "expected {}, found {}", | |
5361 | values.expected, | |
5362 | values.found) | |
5363 | } | |
5364 | terr_projection_bounds_length(ref values) => { | |
5365 | write!(f, "expected {} associated type bindings, found {}", | |
5366 | values.expected, | |
5367 | values.found) | |
1a4d82fc | 5368 | } |
1a4d82fc JJ |
5369 | } |
5370 | } | |
5371 | } | |
5372 | ||
9346a6ac | 5373 | pub fn note_and_explain_type_err<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>, sp: Span) { |
1a4d82fc JJ |
5374 | match *err { |
5375 | terr_regions_does_not_outlive(subregion, superregion) => { | |
5376 | note_and_explain_region(cx, "", subregion, "..."); | |
5377 | note_and_explain_region(cx, "...does not necessarily outlive ", | |
5378 | superregion, ""); | |
5379 | } | |
5380 | terr_regions_not_same(region1, region2) => { | |
5381 | note_and_explain_region(cx, "", region1, "..."); | |
5382 | note_and_explain_region(cx, "...is not the same lifetime as ", | |
5383 | region2, ""); | |
5384 | } | |
5385 | terr_regions_no_overlap(region1, region2) => { | |
5386 | note_and_explain_region(cx, "", region1, "..."); | |
5387 | note_and_explain_region(cx, "...does not overlap ", | |
5388 | region2, ""); | |
5389 | } | |
5390 | terr_regions_insufficiently_polymorphic(_, conc_region) => { | |
5391 | note_and_explain_region(cx, | |
5392 | "concrete lifetime that was found is ", | |
5393 | conc_region, ""); | |
5394 | } | |
5395 | terr_regions_overly_polymorphic(_, ty::ReInfer(ty::ReVar(_))) => { | |
5396 | // don't bother to print out the message below for | |
5397 | // inference variables, it's not very illuminating. | |
5398 | } | |
5399 | terr_regions_overly_polymorphic(_, conc_region) => { | |
5400 | note_and_explain_region(cx, | |
5401 | "expected concrete lifetime is ", | |
5402 | conc_region, ""); | |
5403 | } | |
9346a6ac AL |
5404 | terr_sorts(values) => { |
5405 | let expected_str = ty_sort_string(cx, values.expected); | |
5406 | let found_str = ty_sort_string(cx, values.found); | |
5407 | if expected_str == found_str && expected_str == "closure" { | |
5408 | cx.sess.span_note(sp, &format!("no two closures, even if identical, have the same \ | |
5409 | type")); | |
5410 | cx.sess.span_help(sp, &format!("consider boxing your closure and/or \ | |
5411 | using it as a trait object")); | |
5412 | } | |
5413 | } | |
1a4d82fc JJ |
5414 | _ => {} |
5415 | } | |
5416 | } | |
5417 | ||
5418 | pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> { | |
85aaf69f | 5419 | cx.provided_method_sources.borrow().get(&id).cloned() |
1a4d82fc JJ |
5420 | } |
5421 | ||
5422 | pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) | |
5423 | -> Vec<Rc<Method<'tcx>>> { | |
5424 | if is_local(id) { | |
c34b1796 AL |
5425 | if let ItemTrait(_, _, _, ref ms) = cx.map.expect_item(id.node).node { |
5426 | ms.iter().filter_map(|ti| { | |
5427 | if let ast::MethodTraitItem(_, Some(_)) = ti.node { | |
5428 | match impl_or_trait_item(cx, ast_util::local_def(ti.id)) { | |
5429 | MethodTraitItem(m) => Some(m), | |
d9579d0f | 5430 | _ => { |
c34b1796 | 5431 | cx.sess.bug("provided_trait_methods(): \ |
d9579d0f AL |
5432 | non-method item found from \ |
5433 | looking up provided method?!") | |
c34b1796 | 5434 | } |
1a4d82fc | 5435 | } |
c34b1796 AL |
5436 | } else { |
5437 | None | |
1a4d82fc | 5438 | } |
c34b1796 AL |
5439 | }).collect() |
5440 | } else { | |
5441 | cx.sess.bug(&format!("provided_trait_methods: `{:?}` is not a trait", id)) | |
1a4d82fc JJ |
5442 | } |
5443 | } else { | |
5444 | csearch::get_provided_trait_methods(cx, id) | |
5445 | } | |
5446 | } | |
5447 | ||
d9579d0f AL |
5448 | pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) |
5449 | -> Vec<Rc<AssociatedConst<'tcx>>> { | |
5450 | if is_local(id) { | |
5451 | match cx.map.expect_item(id.node).node { | |
5452 | ItemTrait(_, _, _, ref tis) => { | |
5453 | tis.iter().filter_map(|ti| { | |
5454 | if let ast::ConstTraitItem(_, _) = ti.node { | |
5455 | match impl_or_trait_item(cx, ast_util::local_def(ti.id)) { | |
5456 | ConstTraitItem(ac) => Some(ac), | |
5457 | _ => { | |
5458 | cx.sess.bug("associated_consts(): \ | |
5459 | non-const item found from \ | |
5460 | looking up a constant?!") | |
5461 | } | |
5462 | } | |
5463 | } else { | |
5464 | None | |
5465 | } | |
5466 | }).collect() | |
5467 | } | |
5468 | ItemImpl(_, _, _, _, _, ref iis) => { | |
5469 | iis.iter().filter_map(|ii| { | |
5470 | if let ast::ConstImplItem(_, _) = ii.node { | |
5471 | match impl_or_trait_item(cx, ast_util::local_def(ii.id)) { | |
5472 | ConstTraitItem(ac) => Some(ac), | |
5473 | _ => { | |
5474 | cx.sess.bug("associated_consts(): \ | |
5475 | non-const item found from \ | |
5476 | looking up a constant?!") | |
5477 | } | |
5478 | } | |
5479 | } else { | |
5480 | None | |
5481 | } | |
5482 | }).collect() | |
5483 | } | |
5484 | _ => { | |
5485 | cx.sess.bug(&format!("associated_consts: `{:?}` is not a trait \ | |
5486 | or impl", id)) | |
5487 | } | |
5488 | } | |
5489 | } else { | |
5490 | csearch::get_associated_consts(cx, id) | |
5491 | } | |
5492 | } | |
5493 | ||
1a4d82fc JJ |
5494 | /// Helper for looking things up in the various maps that are populated during |
5495 | /// typeck::collect (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of | |
5496 | /// these share the pattern that if the id is local, it should have been loaded | |
5497 | /// into the map by the `typeck::collect` phase. If the def-id is external, | |
5498 | /// then we have to go consult the crate loading code (and cache the result for | |
5499 | /// the future). | |
5500 | fn lookup_locally_or_in_crate_store<V, F>(descr: &str, | |
5501 | def_id: ast::DefId, | |
62682a34 | 5502 | map: &RefCell<DefIdMap<V>>, |
1a4d82fc JJ |
5503 | load_external: F) -> V where |
5504 | V: Clone, | |
5505 | F: FnOnce() -> V, | |
5506 | { | |
62682a34 | 5507 | match map.borrow().get(&def_id).cloned() { |
1a4d82fc JJ |
5508 | Some(v) => { return v; } |
5509 | None => { } | |
5510 | } | |
5511 | ||
5512 | if def_id.krate == ast::LOCAL_CRATE { | |
5513 | panic!("No def'n found for {:?} in tcx.{}", def_id, descr); | |
5514 | } | |
5515 | let v = load_external(); | |
62682a34 | 5516 | map.borrow_mut().insert(def_id, v.clone()); |
1a4d82fc JJ |
5517 | v |
5518 | } | |
5519 | ||
c34b1796 | 5520 | pub fn trait_item<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId, idx: usize) |
1a4d82fc JJ |
5521 | -> ImplOrTraitItem<'tcx> { |
5522 | let method_def_id = (*ty::trait_item_def_ids(cx, trait_did))[idx].def_id(); | |
5523 | impl_or_trait_item(cx, method_def_id) | |
5524 | } | |
5525 | ||
5526 | pub fn trait_items<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId) | |
5527 | -> Rc<Vec<ImplOrTraitItem<'tcx>>> { | |
5528 | let mut trait_items = cx.trait_items_cache.borrow_mut(); | |
5529 | match trait_items.get(&trait_did).cloned() { | |
5530 | Some(trait_items) => trait_items, | |
5531 | None => { | |
5532 | let def_ids = ty::trait_item_def_ids(cx, trait_did); | |
5533 | let items: Rc<Vec<ImplOrTraitItem>> = | |
5534 | Rc::new(def_ids.iter() | |
5535 | .map(|d| impl_or_trait_item(cx, d.def_id())) | |
5536 | .collect()); | |
5537 | trait_items.insert(trait_did, items.clone()); | |
5538 | items | |
5539 | } | |
5540 | } | |
5541 | } | |
5542 | ||
85aaf69f SL |
5543 | pub fn trait_impl_polarity<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) |
5544 | -> Option<ast::ImplPolarity> { | |
5545 | if id.krate == ast::LOCAL_CRATE { | |
5546 | match cx.map.find(id.node) { | |
5547 | Some(ast_map::NodeItem(item)) => { | |
5548 | match item.node { | |
5549 | ast::ItemImpl(_, polarity, _, _, _, _) => Some(polarity), | |
5550 | _ => None | |
5551 | } | |
5552 | } | |
5553 | _ => None | |
5554 | } | |
5555 | } else { | |
5556 | csearch::get_impl_polarity(cx, id) | |
5557 | } | |
5558 | } | |
5559 | ||
d9579d0f AL |
5560 | pub fn custom_coerce_unsized_kind<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) |
5561 | -> CustomCoerceUnsized { | |
5562 | memoized(&cx.custom_coerce_unsized_kinds, did, |did: DefId| { | |
5563 | let (kind, src) = if did.krate != ast::LOCAL_CRATE { | |
5564 | (csearch::get_custom_coerce_unsized_kind(cx, did), "external") | |
5565 | } else { | |
5566 | (None, "local") | |
5567 | }; | |
5568 | ||
5569 | match kind { | |
5570 | Some(kind) => kind, | |
5571 | None => { | |
5572 | cx.sess.bug(&format!("custom_coerce_unsized_kind: \ | |
5573 | {} impl `{}` is missing its kind", | |
5574 | src, item_path_str(cx, did))); | |
5575 | } | |
5576 | } | |
5577 | }) | |
5578 | } | |
5579 | ||
1a4d82fc JJ |
5580 | pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) |
5581 | -> ImplOrTraitItem<'tcx> { | |
62682a34 SL |
5582 | lookup_locally_or_in_crate_store( |
5583 | "impl_or_trait_items", id, &cx.impl_or_trait_items, | |
5584 | || csearch::get_impl_or_trait_item(cx, id)) | |
1a4d82fc JJ |
5585 | } |
5586 | ||
5587 | /// Returns the parameter index that the given associated type corresponds to. | |
5588 | pub fn associated_type_parameter_index(cx: &ctxt, | |
5589 | trait_def: &TraitDef, | |
5590 | associated_type_id: ast::DefId) | |
c34b1796 | 5591 | -> usize { |
62682a34 | 5592 | for type_parameter_def in &trait_def.generics.types { |
1a4d82fc | 5593 | if type_parameter_def.def_id == associated_type_id { |
c34b1796 | 5594 | return type_parameter_def.index as usize |
1a4d82fc JJ |
5595 | } |
5596 | } | |
5597 | cx.sess.bug("couldn't find associated type parameter index") | |
5598 | } | |
5599 | ||
1a4d82fc JJ |
5600 | pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId) |
5601 | -> Rc<Vec<ImplOrTraitItemId>> { | |
62682a34 SL |
5602 | lookup_locally_or_in_crate_store( |
5603 | "trait_item_def_ids", id, &cx.trait_item_def_ids, | |
5604 | || Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))) | |
1a4d82fc JJ |
5605 | } |
5606 | ||
62682a34 SL |
5607 | /// Returns the trait-ref corresponding to a given impl, or None if it is |
5608 | /// an inherent impl. | |
1a4d82fc | 5609 | pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) |
62682a34 SL |
5610 | -> Option<TraitRef<'tcx>> |
5611 | { | |
5612 | lookup_locally_or_in_crate_store( | |
5613 | "impl_trait_refs", id, &cx.impl_trait_refs, | |
5614 | || csearch::get_impl_trait(cx, id)) | |
5615 | } | |
5616 | ||
5617 | /// Returns whether this DefId refers to an impl | |
5618 | pub fn is_impl<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) -> bool { | |
5619 | if id.krate == ast::LOCAL_CRATE { | |
5620 | if let Some(ast_map::NodeItem( | |
5621 | &ast::Item { node: ast::ItemImpl(..), .. })) = cx.map.find(id.node) { | |
5622 | true | |
1a4d82fc | 5623 | } else { |
62682a34 | 5624 | false |
1a4d82fc | 5625 | } |
62682a34 SL |
5626 | } else { |
5627 | csearch::is_impl(&cx.sess.cstore, id) | |
5628 | } | |
1a4d82fc JJ |
5629 | } |
5630 | ||
5631 | pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId { | |
c34b1796 | 5632 | tcx.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id() |
1a4d82fc JJ |
5633 | } |
5634 | ||
5635 | pub fn try_add_builtin_trait( | |
5636 | tcx: &ctxt, | |
5637 | trait_def_id: ast::DefId, | |
5638 | builtin_bounds: &mut EnumSet<BuiltinBound>) | |
5639 | -> bool | |
5640 | { | |
5641 | //! Checks whether `trait_ref` refers to one of the builtin | |
5642 | //! traits, like `Send`, and adds the corresponding | |
5643 | //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref` | |
5644 | //! is a builtin trait. | |
5645 | ||
5646 | match tcx.lang_items.to_builtin_kind(trait_def_id) { | |
5647 | Some(bound) => { builtin_bounds.insert(bound); true } | |
5648 | None => false | |
5649 | } | |
5650 | } | |
5651 | ||
5652 | pub fn ty_to_def_id(ty: Ty) -> Option<ast::DefId> { | |
5653 | match ty.sty { | |
62682a34 | 5654 | TyTrait(ref tt) => |
1a4d82fc | 5655 | Some(tt.principal_def_id()), |
62682a34 SL |
5656 | TyStruct(id, _) | |
5657 | TyEnum(id, _) | | |
5658 | TyClosure(id, _) => | |
1a4d82fc JJ |
5659 | Some(id), |
5660 | _ => | |
5661 | None | |
5662 | } | |
5663 | } | |
5664 | ||
5665 | // Enum information | |
5666 | #[derive(Clone)] | |
5667 | pub struct VariantInfo<'tcx> { | |
5668 | pub args: Vec<Ty<'tcx>>, | |
9346a6ac | 5669 | pub arg_names: Option<Vec<ast::Name>>, |
1a4d82fc JJ |
5670 | pub ctor_ty: Option<Ty<'tcx>>, |
5671 | pub name: ast::Name, | |
5672 | pub id: ast::DefId, | |
5673 | pub disr_val: Disr, | |
5674 | pub vis: Visibility | |
5675 | } | |
5676 | ||
5677 | impl<'tcx> VariantInfo<'tcx> { | |
5678 | ||
5679 | /// Creates a new VariantInfo from the corresponding ast representation. | |
5680 | /// | |
5681 | /// Does not do any caching of the value in the type context. | |
5682 | pub fn from_ast_variant(cx: &ctxt<'tcx>, | |
5683 | ast_variant: &ast::Variant, | |
5684 | discriminant: Disr) -> VariantInfo<'tcx> { | |
5685 | let ctor_ty = node_id_to_type(cx, ast_variant.node.id); | |
5686 | ||
5687 | match ast_variant.node.kind { | |
5688 | ast::TupleVariantKind(ref args) => { | |
9346a6ac | 5689 | let arg_tys = if !args.is_empty() { |
1a4d82fc JJ |
5690 | // the regions in the argument types come from the |
5691 | // enum def'n, and hence will all be early bound | |
85aaf69f | 5692 | ty::no_late_bound_regions(cx, &ty_fn_args(ctor_ty)).unwrap() |
1a4d82fc JJ |
5693 | } else { |
5694 | Vec::new() | |
5695 | }; | |
5696 | ||
5697 | return VariantInfo { | |
5698 | args: arg_tys, | |
5699 | arg_names: None, | |
5700 | ctor_ty: Some(ctor_ty), | |
5701 | name: ast_variant.node.name.name, | |
5702 | id: ast_util::local_def(ast_variant.node.id), | |
5703 | disr_val: discriminant, | |
5704 | vis: ast_variant.node.vis | |
5705 | }; | |
5706 | }, | |
5707 | ast::StructVariantKind(ref struct_def) => { | |
c34b1796 | 5708 | let fields: &[StructField] = &struct_def.fields; |
1a4d82fc | 5709 | |
9346a6ac | 5710 | assert!(!fields.is_empty()); |
1a4d82fc JJ |
5711 | |
5712 | let arg_tys = struct_def.fields.iter() | |
5713 | .map(|field| node_id_to_type(cx, field.node.id)).collect(); | |
5714 | let arg_names = fields.iter().map(|field| { | |
5715 | match field.node.kind { | |
9346a6ac | 5716 | NamedField(ident, _) => ident.name, |
1a4d82fc JJ |
5717 | UnnamedField(..) => cx.sess.bug( |
5718 | "enum_variants: all fields in struct must have a name") | |
5719 | } | |
5720 | }).collect(); | |
5721 | ||
5722 | return VariantInfo { | |
5723 | args: arg_tys, | |
5724 | arg_names: Some(arg_names), | |
5725 | ctor_ty: None, | |
5726 | name: ast_variant.node.name.name, | |
5727 | id: ast_util::local_def(ast_variant.node.id), | |
5728 | disr_val: discriminant, | |
5729 | vis: ast_variant.node.vis | |
5730 | }; | |
5731 | } | |
5732 | } | |
5733 | } | |
5734 | } | |
5735 | ||
5736 | pub fn substd_enum_variants<'tcx>(cx: &ctxt<'tcx>, | |
5737 | id: ast::DefId, | |
5738 | substs: &Substs<'tcx>) | |
5739 | -> Vec<Rc<VariantInfo<'tcx>>> { | |
5740 | enum_variants(cx, id).iter().map(|variant_info| { | |
5741 | let substd_args = variant_info.args.iter() | |
5742 | .map(|aty| aty.subst(cx, substs)).collect::<Vec<_>>(); | |
5743 | ||
5744 | let substd_ctor_ty = variant_info.ctor_ty.subst(cx, substs); | |
5745 | ||
5746 | Rc::new(VariantInfo { | |
5747 | args: substd_args, | |
5748 | ctor_ty: substd_ctor_ty, | |
5749 | ..(**variant_info).clone() | |
5750 | }) | |
5751 | }).collect() | |
5752 | } | |
5753 | ||
5754 | pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String { | |
5755 | with_path(cx, id, |path| ast_map::path_to_string(path)).to_string() | |
5756 | } | |
5757 | ||
c34b1796 | 5758 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
5759 | pub enum DtorKind { |
5760 | NoDtor, | |
5761 | TraitDtor(DefId, bool) | |
5762 | } | |
5763 | ||
5764 | impl DtorKind { | |
5765 | pub fn is_present(&self) -> bool { | |
5766 | match *self { | |
5767 | TraitDtor(..) => true, | |
5768 | _ => false | |
5769 | } | |
5770 | } | |
5771 | ||
5772 | pub fn has_drop_flag(&self) -> bool { | |
5773 | match self { | |
5774 | &NoDtor => false, | |
5775 | &TraitDtor(_, flag) => flag | |
5776 | } | |
5777 | } | |
5778 | } | |
5779 | ||
d9579d0f | 5780 | /* If struct_id names a struct with a dtor. */ |
1a4d82fc JJ |
5781 | pub fn ty_dtor(cx: &ctxt, struct_id: DefId) -> DtorKind { |
5782 | match cx.destructor_for_type.borrow().get(&struct_id) { | |
5783 | Some(&method_def_id) => { | |
5784 | let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag"); | |
5785 | ||
5786 | TraitDtor(method_def_id, flag) | |
5787 | } | |
5788 | None => NoDtor, | |
5789 | } | |
5790 | } | |
5791 | ||
5792 | pub fn has_dtor(cx: &ctxt, struct_id: DefId) -> bool { | |
5793 | cx.destructor_for_type.borrow().contains_key(&struct_id) | |
5794 | } | |
5795 | ||
5796 | pub fn with_path<T, F>(cx: &ctxt, id: ast::DefId, f: F) -> T where | |
5797 | F: FnOnce(ast_map::PathElems) -> T, | |
5798 | { | |
5799 | if id.krate == ast::LOCAL_CRATE { | |
5800 | cx.map.with_path(id.node, f) | |
5801 | } else { | |
c34b1796 | 5802 | f(csearch::get_item_path(cx, id).iter().cloned().chain(LinkedPath::empty())) |
1a4d82fc JJ |
5803 | } |
5804 | } | |
5805 | ||
5806 | pub fn enum_is_univariant(cx: &ctxt, id: ast::DefId) -> bool { | |
5807 | enum_variants(cx, id).len() == 1 | |
5808 | } | |
5809 | ||
5810 | pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool { | |
5811 | match ty.sty { | |
62682a34 | 5812 | TyEnum(did, _) => (*enum_variants(cx, did)).is_empty(), |
1a4d82fc JJ |
5813 | _ => false |
5814 | } | |
5815 | } | |
5816 | ||
c34b1796 AL |
5817 | trait IntTypeExt { |
5818 | fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>; | |
5819 | fn i64_to_disr(&self, val: i64) -> Option<Disr>; | |
5820 | fn u64_to_disr(&self, val: u64) -> Option<Disr>; | |
5821 | fn disr_incr(&self, val: Disr) -> Option<Disr>; | |
5822 | fn disr_string(&self, val: Disr) -> String; | |
5823 | fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr; | |
5824 | } | |
5825 | ||
5826 | impl IntTypeExt for attr::IntType { | |
5827 | fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> { | |
5828 | match *self { | |
5829 | SignedInt(ast::TyI8) => cx.types.i8, | |
5830 | SignedInt(ast::TyI16) => cx.types.i16, | |
5831 | SignedInt(ast::TyI32) => cx.types.i32, | |
5832 | SignedInt(ast::TyI64) => cx.types.i64, | |
5833 | SignedInt(ast::TyIs) => cx.types.isize, | |
5834 | UnsignedInt(ast::TyU8) => cx.types.u8, | |
5835 | UnsignedInt(ast::TyU16) => cx.types.u16, | |
5836 | UnsignedInt(ast::TyU32) => cx.types.u32, | |
5837 | UnsignedInt(ast::TyU64) => cx.types.u64, | |
5838 | UnsignedInt(ast::TyUs) => cx.types.usize, | |
5839 | } | |
5840 | } | |
5841 | ||
5842 | fn i64_to_disr(&self, val: i64) -> Option<Disr> { | |
5843 | match *self { | |
5844 | SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr), | |
5845 | SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr), | |
5846 | SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr), | |
5847 | SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr), | |
5848 | UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr), | |
5849 | UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr), | |
5850 | UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr), | |
5851 | UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr), | |
5852 | ||
5853 | UnsignedInt(ast::TyUs) | | |
5854 | SignedInt(ast::TyIs) => unreachable!(), | |
5855 | } | |
5856 | } | |
5857 | ||
5858 | fn u64_to_disr(&self, val: u64) -> Option<Disr> { | |
5859 | match *self { | |
5860 | SignedInt(ast::TyI8) => val.to_i8() .map(|v| v as Disr), | |
5861 | SignedInt(ast::TyI16) => val.to_i16() .map(|v| v as Disr), | |
5862 | SignedInt(ast::TyI32) => val.to_i32() .map(|v| v as Disr), | |
5863 | SignedInt(ast::TyI64) => val.to_i64() .map(|v| v as Disr), | |
5864 | UnsignedInt(ast::TyU8) => val.to_u8() .map(|v| v as Disr), | |
5865 | UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr), | |
5866 | UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr), | |
5867 | UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr), | |
5868 | ||
5869 | UnsignedInt(ast::TyUs) | | |
5870 | SignedInt(ast::TyIs) => unreachable!(), | |
5871 | } | |
5872 | } | |
5873 | ||
5874 | fn disr_incr(&self, val: Disr) -> Option<Disr> { | |
5875 | macro_rules! add1 { | |
5876 | ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) } | |
5877 | } | |
5878 | match *self { | |
5879 | // SignedInt repr means we *want* to reinterpret the bits | |
5880 | // treating the highest bit of Disr as a sign-bit, so | |
5881 | // cast to i64 before range-checking. | |
5882 | SignedInt(ast::TyI8) => add1!((val as i64).to_i8()), | |
5883 | SignedInt(ast::TyI16) => add1!((val as i64).to_i16()), | |
5884 | SignedInt(ast::TyI32) => add1!((val as i64).to_i32()), | |
5885 | SignedInt(ast::TyI64) => add1!(Some(val as i64)), | |
5886 | ||
5887 | UnsignedInt(ast::TyU8) => add1!(val.to_u8()), | |
5888 | UnsignedInt(ast::TyU16) => add1!(val.to_u16()), | |
5889 | UnsignedInt(ast::TyU32) => add1!(val.to_u32()), | |
5890 | UnsignedInt(ast::TyU64) => add1!(Some(val)), | |
5891 | ||
5892 | UnsignedInt(ast::TyUs) | | |
5893 | SignedInt(ast::TyIs) => unreachable!(), | |
5894 | } | |
5895 | } | |
5896 | ||
5897 | // This returns a String because (1.) it is only used for | |
5898 | // rendering an error message and (2.) a string can represent the | |
5899 | // full range from `i64::MIN` through `u64::MAX`. | |
5900 | fn disr_string(&self, val: Disr) -> String { | |
5901 | match *self { | |
5902 | SignedInt(ast::TyI8) => format!("{}", val as i8 ), | |
5903 | SignedInt(ast::TyI16) => format!("{}", val as i16), | |
5904 | SignedInt(ast::TyI32) => format!("{}", val as i32), | |
5905 | SignedInt(ast::TyI64) => format!("{}", val as i64), | |
5906 | UnsignedInt(ast::TyU8) => format!("{}", val as u8 ), | |
5907 | UnsignedInt(ast::TyU16) => format!("{}", val as u16), | |
5908 | UnsignedInt(ast::TyU32) => format!("{}", val as u32), | |
5909 | UnsignedInt(ast::TyU64) => format!("{}", val as u64), | |
5910 | ||
5911 | UnsignedInt(ast::TyUs) | | |
5912 | SignedInt(ast::TyIs) => unreachable!(), | |
5913 | } | |
5914 | } | |
5915 | ||
5916 | fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr { | |
5917 | macro_rules! add1 { | |
5918 | ($e:expr) => { ($e).wrapping_add(1) as Disr } | |
5919 | } | |
5920 | let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE); | |
5921 | match *self { | |
5922 | SignedInt(ast::TyI8) => add1!(val as i8 ), | |
5923 | SignedInt(ast::TyI16) => add1!(val as i16), | |
5924 | SignedInt(ast::TyI32) => add1!(val as i32), | |
5925 | SignedInt(ast::TyI64) => add1!(val as i64), | |
5926 | UnsignedInt(ast::TyU8) => add1!(val as u8 ), | |
5927 | UnsignedInt(ast::TyU16) => add1!(val as u16), | |
5928 | UnsignedInt(ast::TyU32) => add1!(val as u32), | |
5929 | UnsignedInt(ast::TyU64) => add1!(val as u64), | |
5930 | ||
5931 | UnsignedInt(ast::TyUs) | | |
5932 | SignedInt(ast::TyIs) => unreachable!(), | |
5933 | } | |
5934 | } | |
5935 | } | |
5936 | ||
5937 | /// Returns `(normalized_type, ty)`, where `normalized_type` is the | |
5938 | /// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8}, | |
5939 | /// and `ty` is the original type (i.e. may include `isize` or | |
5940 | /// `usize`). | |
5941 | pub fn enum_repr_type<'tcx>(cx: &ctxt<'tcx>, | |
5942 | opt_hint: Option<&attr::ReprAttr>) | |
5943 | -> (attr::IntType, Ty<'tcx>) | |
5944 | { | |
5945 | let repr_type = match opt_hint { | |
5946 | // Feed in the given type | |
5947 | Some(&attr::ReprInt(_, int_t)) => int_t, | |
5948 | // ... but provide sensible default if none provided | |
5949 | // | |
5950 | // NB. Historically `fn enum_variants` generate i64 here, while | |
5951 | // rustc_typeck::check would generate isize. | |
5952 | _ => SignedInt(ast::TyIs), | |
5953 | }; | |
5954 | ||
5955 | let repr_type_ty = repr_type.to_ty(cx); | |
5956 | let repr_type = match repr_type { | |
5957 | SignedInt(ast::TyIs) => | |
5958 | SignedInt(cx.sess.target.int_type), | |
5959 | UnsignedInt(ast::TyUs) => | |
5960 | UnsignedInt(cx.sess.target.uint_type), | |
5961 | other => other | |
5962 | }; | |
5963 | ||
5964 | (repr_type, repr_type_ty) | |
5965 | } | |
5966 | ||
5967 | fn report_discrim_overflow(cx: &ctxt, | |
5968 | variant_span: Span, | |
5969 | variant_name: &str, | |
5970 | repr_type: attr::IntType, | |
5971 | prev_val: Disr) { | |
5972 | let computed_value = repr_type.disr_wrap_incr(Some(prev_val)); | |
5973 | let computed_value = repr_type.disr_string(computed_value); | |
5974 | let prev_val = repr_type.disr_string(prev_val); | |
62682a34 | 5975 | let repr_type = repr_type.to_ty(cx); |
c34b1796 AL |
5976 | span_err!(cx.sess, variant_span, E0370, |
5977 | "enum discriminant overflowed on value after {}: {}; \ | |
5978 | set explicitly via {} = {} if that is desired outcome", | |
5979 | prev_val, repr_type, variant_name, computed_value); | |
5980 | } | |
5981 | ||
5982 | // This computes the discriminant values for the sequence of Variants | |
5983 | // attached to a particular enum, taking into account the #[repr] (if | |
5984 | // any) provided via the `opt_hint`. | |
5985 | fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>, | |
5986 | vs: &'tcx [P<ast::Variant>], | |
5987 | opt_hint: Option<&attr::ReprAttr>) | |
5988 | -> Vec<Rc<ty::VariantInfo<'tcx>>> { | |
5989 | let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new(); | |
5990 | let mut prev_disr_val: Option<ty::Disr> = None; | |
5991 | ||
5992 | let (repr_type, repr_type_ty) = ty::enum_repr_type(cx, opt_hint); | |
5993 | ||
5994 | for v in vs { | |
5995 | // If the discriminant value is specified explicitly in the | |
5996 | // enum, check whether the initialization expression is valid, | |
5997 | // otherwise use the last value plus one. | |
5998 | let current_disr_val; | |
5999 | ||
6000 | // This closure marks cases where, when an error occurs during | |
6001 | // the computation, attempt to assign a (hopefully) fresh | |
6002 | // value to avoid spurious error reports downstream. | |
6003 | let attempt_fresh_value = move || -> Disr { | |
6004 | repr_type.disr_wrap_incr(prev_disr_val) | |
6005 | }; | |
6006 | ||
6007 | match v.node.disr_expr { | |
6008 | Some(ref e) => { | |
6009 | debug!("disr expr, checking {}", pprust::expr_to_string(&**e)); | |
6010 | ||
6011 | // check_expr (from check_const pass) doesn't guarantee | |
6012 | // that the expression is in a form that eval_const_expr can | |
6013 | // handle, so we may still get an internal compiler error | |
6014 | // | |
6015 | // pnkfelix: The above comment was transcribed from | |
6016 | // the version of this code taken from rustc_typeck. | |
6017 | // Presumably the implication is that we need to deal | |
6018 | // with such ICE's as they arise. | |
6019 | // | |
6020 | // Since this can be called from `ty::enum_variants` | |
6021 | // anyway, best thing is to make `eval_const_expr` | |
6022 | // more robust (on case-by-case basis). | |
6023 | ||
6024 | match const_eval::eval_const_expr_partial(cx, &**e, Some(repr_type_ty)) { | |
62682a34 SL |
6025 | Ok(ConstVal::Int(val)) => current_disr_val = val as Disr, |
6026 | Ok(ConstVal::Uint(val)) => current_disr_val = val as Disr, | |
c34b1796 | 6027 | Ok(_) => { |
d9579d0f | 6028 | let sign_desc = if repr_type.is_signed() { "signed" } else { "unsigned" }; |
c34b1796 | 6029 | span_err!(cx.sess, e.span, E0079, |
d9579d0f AL |
6030 | "expected {} integer constant", |
6031 | sign_desc); | |
c34b1796 AL |
6032 | current_disr_val = attempt_fresh_value(); |
6033 | } | |
6034 | Err(ref err) => { | |
6035 | span_err!(cx.sess, err.span, E0080, | |
6036 | "constant evaluation error: {}", | |
6037 | err.description()); | |
6038 | current_disr_val = attempt_fresh_value(); | |
6039 | } | |
6040 | } | |
6041 | }, | |
6042 | None => { | |
6043 | current_disr_val = match prev_disr_val { | |
6044 | Some(prev_disr_val) => { | |
6045 | if let Some(v) = repr_type.disr_incr(prev_disr_val) { | |
6046 | v | |
6047 | } else { | |
6048 | report_discrim_overflow(cx, v.span, v.node.name.as_str(), | |
6049 | repr_type, prev_disr_val); | |
6050 | attempt_fresh_value() | |
6051 | } | |
6052 | } | |
6053 | None => ty::INITIAL_DISCRIMINANT_VALUE | |
6054 | } | |
6055 | } | |
6056 | } | |
6057 | ||
6058 | let variant_info = Rc::new(VariantInfo::from_ast_variant(cx, &**v, current_disr_val)); | |
6059 | prev_disr_val = Some(current_disr_val); | |
6060 | ||
6061 | variants.push(variant_info); | |
6062 | } | |
6063 | ||
6064 | return variants; | |
6065 | } | |
6066 | ||
1a4d82fc JJ |
6067 | pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) |
6068 | -> Rc<Vec<Rc<VariantInfo<'tcx>>>> { | |
6069 | memoized(&cx.enum_var_cache, id, |id: ast::DefId| { | |
6070 | if ast::LOCAL_CRATE != id.krate { | |
6071 | Rc::new(csearch::get_enum_variants(cx, id)) | |
6072 | } else { | |
1a4d82fc JJ |
6073 | match cx.map.get(id.node) { |
6074 | ast_map::NodeItem(ref item) => { | |
6075 | match item.node { | |
6076 | ast::ItemEnum(ref enum_definition, _) => { | |
c34b1796 AL |
6077 | Rc::new(compute_enum_variants( |
6078 | cx, | |
6079 | &enum_definition.variants, | |
6080 | lookup_repr_hints(cx, id).get(0))) | |
1a4d82fc JJ |
6081 | } |
6082 | _ => { | |
6083 | cx.sess.bug("enum_variants: id not bound to an enum") | |
6084 | } | |
6085 | } | |
6086 | } | |
6087 | _ => cx.sess.bug("enum_variants: id not bound to an enum") | |
6088 | } | |
6089 | } | |
6090 | }) | |
6091 | } | |
6092 | ||
6093 | // Returns information about the enum variant with the given ID: | |
6094 | pub fn enum_variant_with_id<'tcx>(cx: &ctxt<'tcx>, | |
6095 | enum_id: ast::DefId, | |
6096 | variant_id: ast::DefId) | |
6097 | -> Rc<VariantInfo<'tcx>> { | |
6098 | enum_variants(cx, enum_id).iter() | |
6099 | .find(|variant| variant.id == variant_id) | |
6100 | .expect("enum_variant_with_id(): no variant exists with that ID") | |
6101 | .clone() | |
6102 | } | |
6103 | ||
6104 | ||
6105 | // If the given item is in an external crate, looks up its type and adds it to | |
6106 | // the type cache. Returns the type parameters and type. | |
6107 | pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>, | |
6108 | did: ast::DefId) | |
6109 | -> TypeScheme<'tcx> { | |
6110 | lookup_locally_or_in_crate_store( | |
62682a34 | 6111 | "tcache", did, &cx.tcache, |
1a4d82fc JJ |
6112 | || csearch::get_type(cx, did)) |
6113 | } | |
6114 | ||
6115 | /// Given the did of a trait, returns its canonical trait ref. | |
6116 | pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) | |
d9579d0f | 6117 | -> &'tcx TraitDef<'tcx> { |
62682a34 SL |
6118 | lookup_locally_or_in_crate_store( |
6119 | "trait_defs", did, &cx.trait_defs, | |
6120 | || cx.arenas.trait_defs.alloc(csearch::get_trait_def(cx, did)) | |
6121 | ) | |
1a4d82fc JJ |
6122 | } |
6123 | ||
c34b1796 | 6124 | /// Given the did of an item, returns its full set of predicates. |
85aaf69f SL |
6125 | pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) |
6126 | -> GenericPredicates<'tcx> | |
6127 | { | |
62682a34 SL |
6128 | lookup_locally_or_in_crate_store( |
6129 | "predicates", did, &cx.predicates, | |
6130 | || csearch::get_predicates(cx, did)) | |
85aaf69f SL |
6131 | } |
6132 | ||
c34b1796 AL |
6133 | /// Given the did of a trait, returns its superpredicates. |
6134 | pub fn lookup_super_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) | |
6135 | -> GenericPredicates<'tcx> | |
1a4d82fc | 6136 | { |
62682a34 SL |
6137 | lookup_locally_or_in_crate_store( |
6138 | "super_predicates", did, &cx.super_predicates, | |
6139 | || csearch::get_super_predicates(cx, did)) | |
1a4d82fc JJ |
6140 | } |
6141 | ||
85aaf69f SL |
6142 | /// Get the attributes of a definition. |
6143 | pub fn get_attrs<'tcx>(tcx: &'tcx ctxt, did: DefId) | |
c34b1796 | 6144 | -> Cow<'tcx, [ast::Attribute]> { |
1a4d82fc | 6145 | if is_local(did) { |
c34b1796 | 6146 | Cow::Borrowed(tcx.map.attrs(did.node)) |
1a4d82fc | 6147 | } else { |
85aaf69f | 6148 | Cow::Owned(csearch::get_item_attrs(&tcx.sess.cstore, did)) |
1a4d82fc JJ |
6149 | } |
6150 | } | |
6151 | ||
6152 | /// Determine whether an item is annotated with an attribute | |
6153 | pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool { | |
85aaf69f | 6154 | get_attrs(tcx, did).iter().any(|item| item.check_name(attr)) |
1a4d82fc JJ |
6155 | } |
6156 | ||
6157 | /// Determine whether an item is annotated with `#[repr(packed)]` | |
6158 | pub fn lookup_packed(tcx: &ctxt, did: DefId) -> bool { | |
6159 | lookup_repr_hints(tcx, did).contains(&attr::ReprPacked) | |
6160 | } | |
6161 | ||
6162 | /// Determine whether an item is annotated with `#[simd]` | |
6163 | pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool { | |
6164 | has_attr(tcx, did, "simd") | |
6165 | } | |
6166 | ||
6167 | /// Obtain the representation annotation for a struct definition. | |
6168 | pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> { | |
6169 | memoized(&tcx.repr_hint_cache, did, |did: DefId| { | |
6170 | Rc::new(if did.krate == LOCAL_CRATE { | |
85aaf69f SL |
6171 | get_attrs(tcx, did).iter().flat_map(|meta| { |
6172 | attr::find_repr_attrs(tcx.sess.diagnostic(), meta).into_iter() | |
6173 | }).collect() | |
1a4d82fc JJ |
6174 | } else { |
6175 | csearch::get_repr_attrs(&tcx.sess.cstore, did) | |
6176 | }) | |
6177 | }) | |
6178 | } | |
6179 | ||
d9579d0f AL |
6180 | // Look up a field ID, whether or not it's local |
6181 | pub fn lookup_field_type_unsubstituted<'tcx>(tcx: &ctxt<'tcx>, | |
6182 | struct_id: DefId, | |
6183 | id: DefId) | |
6184 | -> Ty<'tcx> { | |
6185 | if id.krate == ast::LOCAL_CRATE { | |
6186 | node_id_to_type(tcx, id.node) | |
6187 | } else { | |
6188 | let mut tcache = tcx.tcache.borrow_mut(); | |
6189 | tcache.entry(id).or_insert_with(|| csearch::get_field_type(tcx, struct_id, id)).ty | |
6190 | } | |
6191 | } | |
6192 | ||
6193 | ||
1a4d82fc JJ |
6194 | // Look up a field ID, whether or not it's local |
6195 | // Takes a list of type substs in case the struct is generic | |
6196 | pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>, | |
6197 | struct_id: DefId, | |
6198 | id: DefId, | |
6199 | substs: &Substs<'tcx>) | |
6200 | -> Ty<'tcx> { | |
d9579d0f | 6201 | lookup_field_type_unsubstituted(tcx, struct_id, id).subst(tcx, substs) |
1a4d82fc JJ |
6202 | } |
6203 | ||
6204 | // Look up the list of field names and IDs for a given struct. | |
6205 | // Panics if the id is not bound to a struct. | |
6206 | pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> { | |
6207 | if did.krate == ast::LOCAL_CRATE { | |
6208 | let struct_fields = cx.struct_fields.borrow(); | |
6209 | match struct_fields.get(&did) { | |
6210 | Some(fields) => (**fields).clone(), | |
6211 | _ => { | |
6212 | cx.sess.bug( | |
6213 | &format!("ID not mapped to struct fields: {}", | |
c34b1796 | 6214 | cx.map.node_to_string(did.node))); |
1a4d82fc JJ |
6215 | } |
6216 | } | |
6217 | } else { | |
6218 | csearch::get_struct_fields(&cx.sess.cstore, did) | |
6219 | } | |
6220 | } | |
6221 | ||
6222 | pub fn is_tuple_struct(cx: &ctxt, did: ast::DefId) -> bool { | |
6223 | let fields = lookup_struct_fields(cx, did); | |
6224 | !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field) | |
6225 | } | |
6226 | ||
6227 | // Returns a list of fields corresponding to the struct's items. trans uses | |
6228 | // this. Takes a list of substs with which to instantiate field types. | |
6229 | pub fn struct_fields<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &Substs<'tcx>) | |
6230 | -> Vec<field<'tcx>> { | |
6231 | lookup_struct_fields(cx, did).iter().map(|f| { | |
6232 | field { | |
6233 | name: f.name, | |
6234 | mt: mt { | |
6235 | ty: lookup_field_type(cx, did, f.id, substs), | |
6236 | mutbl: MutImmutable | |
6237 | } | |
6238 | } | |
6239 | }).collect() | |
6240 | } | |
6241 | ||
6242 | // Returns a list of fields corresponding to the tuple's items. trans uses | |
6243 | // this. | |
6244 | pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> { | |
6245 | v.iter().enumerate().map(|(i, &f)| { | |
6246 | field { | |
c34b1796 | 6247 | name: token::intern(&i.to_string()), |
1a4d82fc JJ |
6248 | mt: mt { |
6249 | ty: f, | |
6250 | mutbl: MutImmutable | |
6251 | } | |
6252 | } | |
6253 | }).collect() | |
6254 | } | |
6255 | ||
9346a6ac AL |
6256 | /// Returns the deeply last field of nested structures, or the same type, |
6257 | /// if not a structure at all. Corresponds to the only possible unsized | |
6258 | /// field, and its type can be used to determine unsizing strategy. | |
6259 | pub fn struct_tail<'tcx>(cx: &ctxt<'tcx>, mut ty: Ty<'tcx>) -> Ty<'tcx> { | |
62682a34 | 6260 | while let TyStruct(def_id, substs) = ty.sty { |
9346a6ac AL |
6261 | match struct_fields(cx, def_id, substs).last() { |
6262 | Some(f) => ty = f.mt.ty, | |
6263 | None => break | |
6264 | } | |
6265 | } | |
6266 | ty | |
6267 | } | |
6268 | ||
6269 | /// Same as applying struct_tail on `source` and `target`, but only | |
6270 | /// keeps going as long as the two types are instances of the same | |
6271 | /// structure definitions. | |
6272 | /// For `(Foo<Foo<T>>, Foo<Trait>)`, the result will be `(Foo<T>, Trait)`, | |
6273 | /// whereas struct_tail produces `T`, and `Trait`, respectively. | |
6274 | pub fn struct_lockstep_tails<'tcx>(cx: &ctxt<'tcx>, | |
6275 | source: Ty<'tcx>, | |
6276 | target: Ty<'tcx>) | |
6277 | -> (Ty<'tcx>, Ty<'tcx>) { | |
6278 | let (mut a, mut b) = (source, target); | |
62682a34 | 6279 | while let (&TyStruct(a_did, a_substs), &TyStruct(b_did, b_substs)) = (&a.sty, &b.sty) { |
9346a6ac AL |
6280 | if a_did != b_did { |
6281 | continue; | |
6282 | } | |
6283 | if let Some(a_f) = struct_fields(cx, a_did, a_substs).last() { | |
6284 | if let Some(b_f) = struct_fields(cx, b_did, b_substs).last() { | |
6285 | a = a_f.mt.ty; | |
6286 | b = b_f.mt.ty; | |
6287 | } else { | |
6288 | break; | |
6289 | } | |
6290 | } else { | |
6291 | break; | |
6292 | } | |
6293 | } | |
6294 | (a, b) | |
6295 | } | |
6296 | ||
1a4d82fc | 6297 | #[derive(Copy, Clone)] |
85aaf69f | 6298 | pub struct ClosureUpvar<'tcx> { |
1a4d82fc JJ |
6299 | pub def: def::Def, |
6300 | pub span: Span, | |
6301 | pub ty: Ty<'tcx>, | |
6302 | } | |
6303 | ||
85aaf69f SL |
6304 | // Returns a list of `ClosureUpvar`s for each upvar. |
6305 | pub fn closure_upvars<'tcx>(typer: &mc::Typer<'tcx>, | |
6306 | closure_id: ast::DefId, | |
6307 | substs: &Substs<'tcx>) | |
6308 | -> Option<Vec<ClosureUpvar<'tcx>>> | |
1a4d82fc JJ |
6309 | { |
6310 | // Presently an unboxed closure type cannot "escape" out of a | |
6311 | // function, so we will only encounter ones that originated in the | |
6312 | // local crate or were inlined into it along with some function. | |
6313 | // This may change if abstract return types of some sort are | |
6314 | // implemented. | |
6315 | assert!(closure_id.krate == ast::LOCAL_CRATE); | |
6316 | let tcx = typer.tcx(); | |
1a4d82fc JJ |
6317 | match tcx.freevars.borrow().get(&closure_id.node) { |
6318 | None => Some(vec![]), | |
6319 | Some(ref freevars) => { | |
6320 | freevars.iter() | |
6321 | .map(|freevar| { | |
6322 | let freevar_def_id = freevar.def.def_id(); | |
6323 | let freevar_ty = match typer.node_ty(freevar_def_id.node) { | |
6324 | Ok(t) => { t } | |
6325 | Err(()) => { return None; } | |
6326 | }; | |
6327 | let freevar_ty = freevar_ty.subst(tcx, substs); | |
6328 | ||
85aaf69f SL |
6329 | let upvar_id = ty::UpvarId { |
6330 | var_id: freevar_def_id.node, | |
6331 | closure_expr_id: closure_id.node | |
6332 | }; | |
1a4d82fc | 6333 | |
85aaf69f SL |
6334 | typer.upvar_capture(upvar_id).map(|capture| { |
6335 | let freevar_ref_ty = match capture { | |
6336 | UpvarCapture::ByValue => { | |
6337 | freevar_ty | |
6338 | } | |
6339 | UpvarCapture::ByRef(borrow) => { | |
6340 | mk_rptr(tcx, | |
6341 | tcx.mk_region(borrow.region), | |
6342 | ty::mt { | |
6343 | ty: freevar_ty, | |
6344 | mutbl: borrow.kind.to_mutbl_lossy(), | |
6345 | }) | |
6346 | } | |
6347 | }; | |
1a4d82fc | 6348 | |
85aaf69f SL |
6349 | ClosureUpvar { |
6350 | def: freevar.def, | |
6351 | span: freevar.span, | |
6352 | ty: freevar_ref_ty, | |
1a4d82fc | 6353 | } |
85aaf69f | 6354 | }) |
1a4d82fc JJ |
6355 | }) |
6356 | .collect() | |
6357 | } | |
6358 | } | |
6359 | } | |
6360 | ||
1a4d82fc | 6361 | // Returns the repeat count for a repeating vector expression. |
c34b1796 AL |
6362 | pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize { |
6363 | match const_eval::eval_const_expr_partial(tcx, count_expr, Some(tcx.types.usize)) { | |
1a4d82fc JJ |
6364 | Ok(val) => { |
6365 | let found = match val { | |
62682a34 SL |
6366 | ConstVal::Uint(count) => return count as usize, |
6367 | ConstVal::Int(count) if count >= 0 => return count as usize, | |
6368 | ConstVal::Int(_) => "negative integer", | |
6369 | ConstVal::Float(_) => "float", | |
6370 | ConstVal::Str(_) => "string", | |
6371 | ConstVal::Bool(_) => "boolean", | |
6372 | ConstVal::Binary(_) => "binary array", | |
6373 | ConstVal::Struct(..) => "struct", | |
6374 | ConstVal::Tuple(_) => "tuple" | |
1a4d82fc | 6375 | }; |
85aaf69f | 6376 | span_err!(tcx.sess, count_expr.span, E0306, |
1a4d82fc | 6377 | "expected positive integer for repeat count, found {}", |
85aaf69f | 6378 | found); |
1a4d82fc | 6379 | } |
c34b1796 AL |
6380 | Err(err) => { |
6381 | let err_description = err.description(); | |
1a4d82fc | 6382 | let found = match count_expr.node { |
c34b1796 | 6383 | ast::ExprPath(None, ast::Path { |
1a4d82fc JJ |
6384 | global: false, |
6385 | ref segments, | |
6386 | .. | |
6387 | }) if segments.len() == 1 => | |
c34b1796 | 6388 | format!("{}", "found variable"), |
1a4d82fc | 6389 | _ => |
c34b1796 | 6390 | format!("but {}", err_description), |
1a4d82fc | 6391 | }; |
85aaf69f | 6392 | span_err!(tcx.sess, count_expr.span, E0307, |
c34b1796 | 6393 | "expected constant integer for repeat count, {}", |
85aaf69f | 6394 | found); |
1a4d82fc JJ |
6395 | } |
6396 | } | |
6397 | 0 | |
6398 | } | |
6399 | ||
6400 | // Iterate over a type parameter's bounded traits and any supertraits | |
6401 | // of those traits, ignoring kinds. | |
6402 | // Here, the supertraits are the transitive closure of the supertrait | |
6403 | // relation on the supertraits from each bounded trait's constraint | |
6404 | // list. | |
6405 | pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>, | |
6406 | bounds: &[PolyTraitRef<'tcx>], | |
6407 | mut f: F) | |
6408 | -> bool where | |
6409 | F: FnMut(PolyTraitRef<'tcx>) -> bool, | |
6410 | { | |
6411 | for bound_trait_ref in traits::transitive_bounds(tcx, bounds) { | |
6412 | if !f(bound_trait_ref) { | |
6413 | return false; | |
6414 | } | |
6415 | } | |
6416 | return true; | |
6417 | } | |
6418 | ||
1a4d82fc JJ |
6419 | /// Given a set of predicates that apply to an object type, returns |
6420 | /// the region bounds that the (erased) `Self` type must | |
6421 | /// outlive. Precisely *because* the `Self` type is erased, the | |
6422 | /// parameter `erased_self_ty` must be supplied to indicate what type | |
6423 | /// has been used to represent `Self` in the predicates | |
6424 | /// themselves. This should really be a unique type; `FreshTy(0)` is a | |
85aaf69f | 6425 | /// popular choice. |
1a4d82fc JJ |
6426 | /// |
6427 | /// Requires that trait definitions have been processed so that we can | |
6428 | /// elaborate predicates and walk supertraits. | |
6429 | pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>, | |
6430 | erased_self_ty: Ty<'tcx>, | |
6431 | predicates: Vec<ty::Predicate<'tcx>>) | |
6432 | -> Vec<ty::Region> | |
6433 | { | |
6434 | debug!("required_region_bounds(erased_self_ty={:?}, predicates={:?})", | |
62682a34 SL |
6435 | erased_self_ty, |
6436 | predicates); | |
1a4d82fc JJ |
6437 | |
6438 | assert!(!erased_self_ty.has_escaping_regions()); | |
6439 | ||
6440 | traits::elaborate_predicates(tcx, predicates) | |
6441 | .filter_map(|predicate| { | |
6442 | match predicate { | |
6443 | ty::Predicate::Projection(..) | | |
6444 | ty::Predicate::Trait(..) | | |
6445 | ty::Predicate::Equate(..) | | |
6446 | ty::Predicate::RegionOutlives(..) => { | |
6447 | None | |
6448 | } | |
6449 | ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => { | |
6450 | // Search for a bound of the form `erased_self_ty | |
6451 | // : 'a`, but be wary of something like `for<'a> | |
6452 | // erased_self_ty : 'a` (we interpret a | |
6453 | // higher-ranked bound like that as 'static, | |
6454 | // though at present the code in `fulfill.rs` | |
6455 | // considers such bounds to be unsatisfiable, so | |
6456 | // it's kind of a moot point since you could never | |
6457 | // construct such an object, but this seems | |
6458 | // correct even if that code changes). | |
6459 | if t == erased_self_ty && !r.has_escaping_regions() { | |
6460 | if r.has_escaping_regions() { | |
6461 | Some(ty::ReStatic) | |
6462 | } else { | |
6463 | Some(r) | |
6464 | } | |
6465 | } else { | |
6466 | None | |
6467 | } | |
6468 | } | |
6469 | } | |
6470 | }) | |
6471 | .collect() | |
6472 | } | |
6473 | ||
1a4d82fc JJ |
6474 | pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> { |
6475 | lookup_locally_or_in_crate_store( | |
62682a34 | 6476 | "item_variance_map", item_id, &tcx.item_variance_map, |
1a4d82fc JJ |
6477 | || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id))) |
6478 | } | |
6479 | ||
c34b1796 AL |
6480 | pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool { |
6481 | populate_implementations_for_trait_if_necessary(tcx, trait_def_id); | |
c34b1796 | 6482 | |
d9579d0f AL |
6483 | let def = lookup_trait_def(tcx, trait_def_id); |
6484 | def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL) | |
c34b1796 AL |
6485 | } |
6486 | ||
1a4d82fc | 6487 | /// Records a trait-to-implementation mapping. |
d9579d0f AL |
6488 | pub fn record_trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) { |
6489 | let def = lookup_trait_def(tcx, trait_def_id); | |
6490 | def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL) | |
1a4d82fc JJ |
6491 | } |
6492 | ||
c34b1796 | 6493 | /// Load primitive inherent implementations if necessary |
d9579d0f AL |
6494 | pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt, |
6495 | primitive_def_id: ast::DefId) { | |
6496 | if primitive_def_id.krate == LOCAL_CRATE { | |
c34b1796 AL |
6497 | return |
6498 | } | |
d9579d0f AL |
6499 | |
6500 | if tcx.populated_external_primitive_impls.borrow().contains(&primitive_def_id) { | |
c34b1796 AL |
6501 | return |
6502 | } | |
6503 | ||
d9579d0f AL |
6504 | debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", |
6505 | primitive_def_id); | |
c34b1796 | 6506 | |
d9579d0f | 6507 | let impl_items = csearch::get_impl_items(&tcx.sess.cstore, primitive_def_id); |
c34b1796 AL |
6508 | |
6509 | // Store the implementation info. | |
d9579d0f AL |
6510 | tcx.impl_items.borrow_mut().insert(primitive_def_id, impl_items); |
6511 | tcx.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id); | |
c34b1796 AL |
6512 | } |
6513 | ||
d9579d0f AL |
6514 | /// Populates the type context with all the inherent implementations for |
6515 | /// the given type if necessary. | |
6516 | pub fn populate_inherent_implementations_for_type_if_necessary(tcx: &ctxt, | |
6517 | type_id: ast::DefId) { | |
1a4d82fc JJ |
6518 | if type_id.krate == LOCAL_CRATE { |
6519 | return | |
6520 | } | |
d9579d0f | 6521 | |
1a4d82fc JJ |
6522 | if tcx.populated_external_types.borrow().contains(&type_id) { |
6523 | return | |
6524 | } | |
6525 | ||
d9579d0f | 6526 | debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}", type_id); |
1a4d82fc JJ |
6527 | |
6528 | let mut inherent_impls = Vec::new(); | |
d9579d0f AL |
6529 | csearch::each_inherent_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| { |
6530 | // Record the implementation. | |
6531 | inherent_impls.push(impl_def_id); | |
1a4d82fc JJ |
6532 | |
6533 | // Store the implementation info. | |
d9579d0f | 6534 | let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id); |
1a4d82fc | 6535 | tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items); |
1a4d82fc JJ |
6536 | }); |
6537 | ||
6538 | tcx.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls)); | |
6539 | tcx.populated_external_types.borrow_mut().insert(type_id); | |
6540 | } | |
6541 | ||
6542 | /// Populates the type context with all the implementations for the given | |
6543 | /// trait if necessary. | |
d9579d0f | 6544 | pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast::DefId) { |
1a4d82fc JJ |
6545 | if trait_id.krate == LOCAL_CRATE { |
6546 | return | |
6547 | } | |
c34b1796 | 6548 | |
d9579d0f AL |
6549 | let def = lookup_trait_def(tcx, trait_id); |
6550 | if def.flags.get().intersects(TraitFlags::IMPLS_VALID) { | |
6551 | return; | |
1a4d82fc JJ |
6552 | } |
6553 | ||
62682a34 | 6554 | debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def); |
d9579d0f | 6555 | |
c34b1796 AL |
6556 | if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) { |
6557 | record_trait_has_default_impl(tcx, trait_id); | |
6558 | } | |
6559 | ||
6560 | csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id, |implementation_def_id| { | |
1a4d82fc | 6561 | let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id); |
d9579d0f | 6562 | let trait_ref = impl_trait_ref(tcx, implementation_def_id).unwrap(); |
1a4d82fc | 6563 | // Record the trait->implementation mapping. |
d9579d0f | 6564 | def.record_impl(tcx, implementation_def_id, trait_ref); |
1a4d82fc JJ |
6565 | |
6566 | // For any methods that use a default implementation, add them to | |
6567 | // the map. This is a bit unfortunate. | |
85aaf69f | 6568 | for impl_item_def_id in &impl_items { |
1a4d82fc JJ |
6569 | let method_def_id = impl_item_def_id.def_id(); |
6570 | match impl_or_trait_item(tcx, method_def_id) { | |
6571 | MethodTraitItem(method) => { | |
85aaf69f | 6572 | if let Some(source) = method.provided_source { |
1a4d82fc | 6573 | tcx.provided_method_sources |
c34b1796 AL |
6574 | .borrow_mut() |
6575 | .insert(method_def_id, source); | |
1a4d82fc JJ |
6576 | } |
6577 | } | |
d9579d0f | 6578 | _ => {} |
1a4d82fc JJ |
6579 | } |
6580 | } | |
6581 | ||
6582 | // Store the implementation info. | |
6583 | tcx.impl_items.borrow_mut().insert(implementation_def_id, impl_items); | |
6584 | }); | |
6585 | ||
d9579d0f | 6586 | def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID); |
1a4d82fc JJ |
6587 | } |
6588 | ||
6589 | /// Given the def_id of an impl, return the def_id of the trait it implements. | |
6590 | /// If it implements no trait, return `None`. | |
6591 | pub fn trait_id_of_impl(tcx: &ctxt, | |
6592 | def_id: ast::DefId) | |
6593 | -> Option<ast::DefId> { | |
6594 | ty::impl_trait_ref(tcx, def_id).map(|tr| tr.def_id) | |
6595 | } | |
6596 | ||
6597 | /// If the given def ID describes a method belonging to an impl, return the | |
6598 | /// ID of the impl that the method belongs to. Otherwise, return `None`. | |
6599 | pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId) | |
6600 | -> Option<ast::DefId> { | |
6601 | if def_id.krate != LOCAL_CRATE { | |
6602 | return match csearch::get_impl_or_trait_item(tcx, | |
6603 | def_id).container() { | |
6604 | TraitContainer(_) => None, | |
6605 | ImplContainer(def_id) => Some(def_id), | |
6606 | }; | |
6607 | } | |
6608 | match tcx.impl_or_trait_items.borrow().get(&def_id).cloned() { | |
6609 | Some(trait_item) => { | |
6610 | match trait_item.container() { | |
6611 | TraitContainer(_) => None, | |
6612 | ImplContainer(def_id) => Some(def_id), | |
6613 | } | |
6614 | } | |
6615 | None => None | |
6616 | } | |
6617 | } | |
6618 | ||
6619 | /// If the given def ID describes an item belonging to a trait (either a | |
6620 | /// default method or an implementation of a trait method), return the ID of | |
6621 | /// the trait that the method belongs to. Otherwise, return `None`. | |
6622 | pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option<ast::DefId> { | |
6623 | if def_id.krate != LOCAL_CRATE { | |
6624 | return csearch::get_trait_of_item(&tcx.sess.cstore, def_id, tcx); | |
6625 | } | |
6626 | match tcx.impl_or_trait_items.borrow().get(&def_id).cloned() { | |
6627 | Some(impl_or_trait_item) => { | |
6628 | match impl_or_trait_item.container() { | |
6629 | TraitContainer(def_id) => Some(def_id), | |
6630 | ImplContainer(def_id) => trait_id_of_impl(tcx, def_id), | |
6631 | } | |
6632 | } | |
6633 | None => None | |
6634 | } | |
6635 | } | |
6636 | ||
6637 | /// If the given def ID describes an item belonging to a trait, (either a | |
6638 | /// default method or an implementation of a trait method), return the ID of | |
6639 | /// the method inside trait definition (this means that if the given def ID | |
6640 | /// is already that of the original trait method, then the return value is | |
6641 | /// the same). | |
6642 | /// Otherwise, return `None`. | |
6643 | pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId) | |
6644 | -> Option<ImplOrTraitItemId> { | |
6645 | let impl_item = match tcx.impl_or_trait_items.borrow().get(&def_id) { | |
6646 | Some(m) => m.clone(), | |
6647 | None => return None, | |
6648 | }; | |
6649 | let name = impl_item.name(); | |
6650 | match trait_of_item(tcx, def_id) { | |
6651 | Some(trait_did) => { | |
6652 | let trait_items = ty::trait_items(tcx, trait_did); | |
6653 | trait_items.iter() | |
6654 | .position(|m| m.name() == name) | |
6655 | .map(|idx| ty::trait_item(tcx, trait_did, idx).id()) | |
223e47cc | 6656 | } |
1a4d82fc JJ |
6657 | None => None |
6658 | } | |
6659 | } | |
6660 | ||
6661 | /// Creates a hash of the type `Ty` which will be the same no matter what crate | |
6662 | /// context it's calculated within. This is used by the `type_id` intrinsic. | |
6663 | pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -> u64 { | |
6664 | let mut state = SipHasher::new(); | |
6665 | helper(tcx, ty, svh, &mut state); | |
6666 | return state.finish(); | |
6667 | ||
6668 | fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh, | |
6669 | state: &mut SipHasher) { | |
6670 | macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } } | |
6671 | macro_rules! hash { ($e:expr) => { $e.hash(state) } } | |
6672 | ||
85aaf69f | 6673 | let region = |state: &mut SipHasher, r: Region| { |
1a4d82fc JJ |
6674 | match r { |
6675 | ReStatic => {} | |
6676 | ReLateBound(db, BrAnon(i)) => { | |
6677 | db.hash(state); | |
6678 | i.hash(state); | |
6679 | } | |
6680 | ReEmpty | | |
6681 | ReEarlyBound(..) | | |
6682 | ReLateBound(..) | | |
6683 | ReFree(..) | | |
6684 | ReScope(..) | | |
6685 | ReInfer(..) => { | |
6686 | tcx.sess.bug("unexpected region found when hashing a type") | |
6687 | } | |
6688 | } | |
6689 | }; | |
85aaf69f | 6690 | let did = |state: &mut SipHasher, did: DefId| { |
1a4d82fc JJ |
6691 | let h = if ast_util::is_local(did) { |
6692 | svh.clone() | |
6693 | } else { | |
6694 | tcx.sess.cstore.get_crate_hash(did.krate) | |
6695 | }; | |
6696 | h.as_str().hash(state); | |
6697 | did.node.hash(state); | |
6698 | }; | |
85aaf69f | 6699 | let mt = |state: &mut SipHasher, mt: mt| { |
1a4d82fc JJ |
6700 | mt.mutbl.hash(state); |
6701 | }; | |
85aaf69f | 6702 | let fn_sig = |state: &mut SipHasher, sig: &Binder<FnSig<'tcx>>| { |
1a4d82fc | 6703 | let sig = anonymize_late_bound_regions(tcx, sig).0; |
85aaf69f | 6704 | for a in &sig.inputs { helper(tcx, *a, svh, state); } |
1a4d82fc JJ |
6705 | if let ty::FnConverging(output) = sig.output { |
6706 | helper(tcx, output, svh, state); | |
6707 | } | |
6708 | }; | |
6709 | maybe_walk_ty(ty, |ty| { | |
6710 | match ty.sty { | |
62682a34 SL |
6711 | TyBool => byte!(2), |
6712 | TyChar => byte!(3), | |
6713 | TyInt(i) => { | |
1a4d82fc JJ |
6714 | byte!(4); |
6715 | hash!(i); | |
6716 | } | |
62682a34 | 6717 | TyUint(u) => { |
1a4d82fc JJ |
6718 | byte!(5); |
6719 | hash!(u); | |
6720 | } | |
62682a34 | 6721 | TyFloat(f) => { |
1a4d82fc JJ |
6722 | byte!(6); |
6723 | hash!(f); | |
6724 | } | |
62682a34 | 6725 | TyStr => { |
1a4d82fc JJ |
6726 | byte!(7); |
6727 | } | |
62682a34 | 6728 | TyEnum(d, _) => { |
1a4d82fc JJ |
6729 | byte!(8); |
6730 | did(state, d); | |
6731 | } | |
62682a34 | 6732 | TyBox(_) => { |
1a4d82fc JJ |
6733 | byte!(9); |
6734 | } | |
62682a34 | 6735 | TyArray(_, n) => { |
1a4d82fc JJ |
6736 | byte!(10); |
6737 | n.hash(state); | |
6738 | } | |
62682a34 | 6739 | TySlice(_) => { |
1a4d82fc JJ |
6740 | byte!(11); |
6741 | } | |
62682a34 | 6742 | TyRawPtr(m) => { |
1a4d82fc JJ |
6743 | byte!(12); |
6744 | mt(state, m); | |
6745 | } | |
62682a34 | 6746 | TyRef(r, m) => { |
1a4d82fc JJ |
6747 | byte!(13); |
6748 | region(state, *r); | |
6749 | mt(state, m); | |
6750 | } | |
62682a34 | 6751 | TyBareFn(opt_def_id, ref b) => { |
1a4d82fc JJ |
6752 | byte!(14); |
6753 | hash!(opt_def_id); | |
6754 | hash!(b.unsafety); | |
6755 | hash!(b.abi); | |
6756 | fn_sig(state, &b.sig); | |
6757 | return false; | |
6758 | } | |
62682a34 | 6759 | TyTrait(ref data) => { |
1a4d82fc JJ |
6760 | byte!(17); |
6761 | did(state, data.principal_def_id()); | |
6762 | hash!(data.bounds); | |
6763 | ||
6764 | let principal = anonymize_late_bound_regions(tcx, &data.principal).0; | |
62682a34 SL |
6765 | for subty in &principal.substs.types { |
6766 | helper(tcx, subty, svh, state); | |
1a4d82fc JJ |
6767 | } |
6768 | ||
6769 | return false; | |
6770 | } | |
62682a34 | 6771 | TyStruct(d, _) => { |
1a4d82fc JJ |
6772 | byte!(18); |
6773 | did(state, d); | |
6774 | } | |
62682a34 | 6775 | TyTuple(ref inner) => { |
1a4d82fc JJ |
6776 | byte!(19); |
6777 | hash!(inner.len()); | |
6778 | } | |
62682a34 | 6779 | TyParam(p) => { |
1a4d82fc JJ |
6780 | byte!(20); |
6781 | hash!(p.space); | |
6782 | hash!(p.idx); | |
6783 | hash!(token::get_name(p.name)); | |
6784 | } | |
62682a34 SL |
6785 | TyInfer(_) => unreachable!(), |
6786 | TyError => byte!(21), | |
6787 | TyClosure(d, _) => { | |
c34b1796 | 6788 | byte!(22); |
1a4d82fc | 6789 | did(state, d); |
1a4d82fc | 6790 | } |
62682a34 | 6791 | TyProjection(ref data) => { |
c34b1796 | 6792 | byte!(23); |
1a4d82fc JJ |
6793 | did(state, data.trait_ref.def_id); |
6794 | hash!(token::get_name(data.item_name)); | |
6795 | } | |
6796 | } | |
6797 | true | |
6798 | }); | |
223e47cc LB |
6799 | } |
6800 | } | |
6801 | ||
62682a34 SL |
6802 | impl fmt::Debug for Variance { |
6803 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
6804 | f.write_str(match *self { | |
1a4d82fc JJ |
6805 | Covariant => "+", |
6806 | Contravariant => "-", | |
6807 | Invariant => "o", | |
6808 | Bivariant => "*", | |
62682a34 | 6809 | }) |
223e47cc LB |
6810 | } |
6811 | } | |
6812 | ||
1a4d82fc JJ |
6813 | /// Construct a parameter environment suitable for static contexts or other contexts where there |
6814 | /// are no free type/lifetime parameters in scope. | |
6815 | pub fn empty_parameter_environment<'a,'tcx>(cx: &'a ctxt<'tcx>) -> ParameterEnvironment<'a,'tcx> { | |
6816 | ty::ParameterEnvironment { tcx: cx, | |
6817 | free_substs: Substs::empty(), | |
85aaf69f | 6818 | caller_bounds: Vec::new(), |
1a4d82fc JJ |
6819 | implicit_region_bound: ty::ReEmpty, |
6820 | selection_cache: traits::SelectionCache::new(), } | |
223e47cc LB |
6821 | } |
6822 | ||
85aaf69f SL |
6823 | /// Constructs and returns a substitution that can be applied to move from |
6824 | /// the "outer" view of a type or method to the "inner" view. | |
6825 | /// In general, this means converting from bound parameters to | |
6826 | /// free parameters. Since we currently represent bound/free type | |
6827 | /// parameters in the same way, this only has an effect on regions. | |
6828 | pub fn construct_free_substs<'a,'tcx>( | |
1a4d82fc | 6829 | tcx: &'a ctxt<'tcx>, |
85aaf69f | 6830 | generics: &Generics<'tcx>, |
1a4d82fc | 6831 | free_id: ast::NodeId) |
85aaf69f | 6832 | -> Substs<'tcx> |
1a4d82fc | 6833 | { |
1a4d82fc JJ |
6834 | // map T => T |
6835 | let mut types = VecPerParamSpace::empty(); | |
6836 | push_types_from_defs(tcx, &mut types, generics.types.as_slice()); | |
223e47cc | 6837 | |
85aaf69f SL |
6838 | let free_id_outlive = region::DestructionScopeData::new(free_id); |
6839 | ||
1a4d82fc JJ |
6840 | // map bound 'a => free 'a |
6841 | let mut regions = VecPerParamSpace::empty(); | |
85aaf69f | 6842 | push_region_params(&mut regions, free_id_outlive, generics.regions.as_slice()); |
223e47cc | 6843 | |
85aaf69f | 6844 | return Substs { |
1a4d82fc JJ |
6845 | types: types, |
6846 | regions: subst::NonerasedRegions(regions) | |
6847 | }; | |
223e47cc | 6848 | |
85aaf69f SL |
6849 | fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>, |
6850 | all_outlive_extent: region::DestructionScopeData, | |
6851 | region_params: &[RegionParameterDef]) | |
6852 | { | |
6853 | for r in region_params { | |
6854 | regions.push(r.space, ty::free_region_from_def(all_outlive_extent, r)); | |
6855 | } | |
6856 | } | |
6857 | ||
6858 | fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>, | |
6859 | types: &mut VecPerParamSpace<Ty<'tcx>>, | |
6860 | defs: &[TypeParameterDef<'tcx>]) { | |
6861 | for def in defs { | |
6862 | debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", | |
62682a34 | 6863 | def); |
85aaf69f SL |
6864 | let ty = ty::mk_param_from_def(tcx, def); |
6865 | types.push(def.space, ty); | |
6866 | } | |
6867 | } | |
6868 | } | |
6869 | ||
6870 | /// See `ParameterEnvironment` struct def'n for details | |
6871 | pub fn construct_parameter_environment<'a,'tcx>( | |
6872 | tcx: &'a ctxt<'tcx>, | |
6873 | span: Span, | |
6874 | generics: &ty::Generics<'tcx>, | |
6875 | generic_predicates: &ty::GenericPredicates<'tcx>, | |
6876 | free_id: ast::NodeId) | |
6877 | -> ParameterEnvironment<'a, 'tcx> | |
6878 | { | |
6879 | // | |
6880 | // Construct the free substs. | |
6881 | // | |
6882 | ||
6883 | let free_substs = construct_free_substs(tcx, generics, free_id); | |
6884 | let free_id_outlive = region::DestructionScopeData::new(free_id); | |
223e47cc | 6885 | |
1a4d82fc JJ |
6886 | // |
6887 | // Compute the bounds on Self and the type parameters. | |
6888 | // | |
6889 | ||
85aaf69f SL |
6890 | let bounds = generic_predicates.instantiate(tcx, &free_substs); |
6891 | let bounds = liberate_late_bound_regions(tcx, free_id_outlive, &ty::Binder(bounds)); | |
6892 | let predicates = bounds.predicates.into_vec(); | |
1a4d82fc | 6893 | |
85aaf69f | 6894 | debug!("construct_parameter_environment: free_id={:?} free_subst={:?} predicates={:?}", |
1a4d82fc | 6895 | free_id, |
62682a34 SL |
6896 | free_substs, |
6897 | predicates); | |
1a4d82fc | 6898 | |
85aaf69f SL |
6899 | // |
6900 | // Finally, we have to normalize the bounds in the environment, in | |
6901 | // case they contain any associated type projections. This process | |
6902 | // can yield errors if the put in illegal associated types, like | |
6903 | // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We | |
6904 | // report these errors right here; this doesn't actually feel | |
6905 | // right to me, because constructing the environment feels like a | |
6906 | // kind of a "idempotent" action, but I'm not sure where would be | |
6907 | // a better place. In practice, we construct environments for | |
6908 | // every fn once during type checking, and we'll abort if there | |
6909 | // are any errors at that point, so after type checking you can be | |
6910 | // sure that this will succeed without errors anyway. | |
6911 | // | |
6912 | ||
6913 | let unnormalized_env = ty::ParameterEnvironment { | |
1a4d82fc JJ |
6914 | tcx: tcx, |
6915 | free_substs: free_substs, | |
85aaf69f SL |
6916 | implicit_region_bound: ty::ReScope(free_id_outlive.to_code_extent()), |
6917 | caller_bounds: predicates, | |
1a4d82fc JJ |
6918 | selection_cache: traits::SelectionCache::new(), |
6919 | }; | |
6920 | ||
85aaf69f | 6921 | let cause = traits::ObligationCause::misc(span, free_id); |
bd371182 | 6922 | traits::normalize_param_env_or_error(unnormalized_env, cause) |
1a4d82fc | 6923 | } |
223e47cc | 6924 | |
1a4d82fc JJ |
6925 | impl BorrowKind { |
6926 | pub fn from_mutbl(m: ast::Mutability) -> BorrowKind { | |
6927 | match m { | |
6928 | ast::MutMutable => MutBorrow, | |
6929 | ast::MutImmutable => ImmBorrow, | |
223e47cc | 6930 | } |
1a4d82fc | 6931 | } |
223e47cc | 6932 | |
1a4d82fc JJ |
6933 | /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow |
6934 | /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a | |
6935 | /// mutability that is stronger than necessary so that it at least *would permit* the borrow in | |
6936 | /// question. | |
6937 | pub fn to_mutbl_lossy(self) -> ast::Mutability { | |
6938 | match self { | |
6939 | MutBorrow => ast::MutMutable, | |
6940 | ImmBorrow => ast::MutImmutable, | |
223e47cc | 6941 | |
1a4d82fc JJ |
6942 | // We have no type corresponding to a unique imm borrow, so |
6943 | // use `&mut`. It gives all the capabilities of an `&uniq` | |
6944 | // and hence is a safe "over approximation". | |
6945 | UniqueImmBorrow => ast::MutMutable, | |
6946 | } | |
6947 | } | |
223e47cc | 6948 | |
1a4d82fc JJ |
6949 | pub fn to_user_str(&self) -> &'static str { |
6950 | match *self { | |
6951 | MutBorrow => "mutable", | |
6952 | ImmBorrow => "immutable", | |
6953 | UniqueImmBorrow => "uniquely immutable", | |
223e47cc LB |
6954 | } |
6955 | } | |
6956 | } | |
6957 | ||
1a4d82fc | 6958 | impl<'tcx> ctxt<'tcx> { |
1a4d82fc JJ |
6959 | pub fn is_method_call(&self, expr_id: ast::NodeId) -> bool { |
6960 | self.method_map.borrow().contains_key(&MethodCall::expr(expr_id)) | |
6961 | } | |
223e47cc | 6962 | |
85aaf69f | 6963 | pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { |
c34b1796 | 6964 | Some(self.upvar_capture_map.borrow().get(&upvar_id).unwrap().clone()) |
1a4d82fc | 6965 | } |
85aaf69f | 6966 | } |
1a4d82fc | 6967 | |
85aaf69f | 6968 | impl<'a,'tcx> mc::Typer<'tcx> for ParameterEnvironment<'a,'tcx> { |
1a4d82fc JJ |
6969 | fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> { |
6970 | Ok(ty::node_id_to_type(self.tcx, id)) | |
223e47cc LB |
6971 | } |
6972 | ||
1a4d82fc JJ |
6973 | fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> { |
6974 | Ok(ty::expr_ty_adjusted(self.tcx, expr)) | |
6975 | } | |
6976 | ||
6977 | fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> { | |
6978 | self.tcx.method_map.borrow().get(&method_call).map(|method| method.ty) | |
6979 | } | |
6980 | ||
6981 | fn node_method_origin(&self, method_call: ty::MethodCall) | |
6982 | -> Option<ty::MethodOrigin<'tcx>> | |
6983 | { | |
6984 | self.tcx.method_map.borrow().get(&method_call).map(|method| method.origin.clone()) | |
6985 | } | |
6986 | ||
6987 | fn adjustments(&self) -> &RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> { | |
6988 | &self.tcx.adjustments | |
6989 | } | |
6990 | ||
6991 | fn is_method_call(&self, id: ast::NodeId) -> bool { | |
6992 | self.tcx.is_method_call(id) | |
6993 | } | |
6994 | ||
6995 | fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> { | |
6996 | self.tcx.region_maps.temporary_scope(rvalue_id) | |
6997 | } | |
6998 | ||
85aaf69f SL |
6999 | fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { |
7000 | self.tcx.upvar_capture(upvar_id) | |
1a4d82fc | 7001 | } |
223e47cc | 7002 | |
1a4d82fc JJ |
7003 | fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool { |
7004 | type_moves_by_default(self, span, ty) | |
223e47cc LB |
7005 | } |
7006 | } | |
7007 | ||
85aaf69f | 7008 | impl<'a,'tcx> ClosureTyper<'tcx> for ty::ParameterEnvironment<'a,'tcx> { |
1a4d82fc JJ |
7009 | fn param_env<'b>(&'b self) -> &'b ty::ParameterEnvironment<'b,'tcx> { |
7010 | self | |
7011 | } | |
223e47cc | 7012 | |
85aaf69f SL |
7013 | fn closure_kind(&self, |
7014 | def_id: ast::DefId) | |
7015 | -> Option<ty::ClosureKind> | |
1a4d82fc | 7016 | { |
85aaf69f | 7017 | Some(self.tcx.closure_kind(def_id)) |
223e47cc LB |
7018 | } |
7019 | ||
85aaf69f SL |
7020 | fn closure_type(&self, |
7021 | def_id: ast::DefId, | |
7022 | substs: &subst::Substs<'tcx>) | |
7023 | -> ty::ClosureTy<'tcx> | |
1a4d82fc | 7024 | { |
85aaf69f | 7025 | self.tcx.closure_type(def_id, substs) |
1a4d82fc JJ |
7026 | } |
7027 | ||
85aaf69f SL |
7028 | fn closure_upvars(&self, |
7029 | def_id: ast::DefId, | |
7030 | substs: &Substs<'tcx>) | |
7031 | -> Option<Vec<ClosureUpvar<'tcx>>> | |
1a4d82fc | 7032 | { |
85aaf69f | 7033 | closure_upvars(self, def_id, substs) |
1a4d82fc JJ |
7034 | } |
7035 | } | |
7036 | ||
7037 | ||
7038 | /// The category of explicit self. | |
85aaf69f | 7039 | #[derive(Clone, Copy, Eq, PartialEq, Debug)] |
1a4d82fc JJ |
7040 | pub enum ExplicitSelfCategory { |
7041 | StaticExplicitSelfCategory, | |
7042 | ByValueExplicitSelfCategory, | |
7043 | ByReferenceExplicitSelfCategory(Region, ast::Mutability), | |
7044 | ByBoxExplicitSelfCategory, | |
7045 | } | |
7046 | ||
7047 | /// Pushes all the lifetimes in the given type onto the given list. A | |
7048 | /// "lifetime in a type" is a lifetime specified by a reference or a lifetime | |
7049 | /// in a list of type substitutions. This does *not* traverse into nominal | |
7050 | /// types, nor does it resolve fictitious types. | |
7051 | pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>, | |
7052 | ty: Ty) { | |
7053 | walk_ty(ty, |ty| { | |
7054 | match ty.sty { | |
62682a34 | 7055 | TyRef(region, _) => { |
1a4d82fc JJ |
7056 | accumulator.push(*region) |
7057 | } | |
62682a34 | 7058 | TyTrait(ref t) => { |
1a4d82fc JJ |
7059 | accumulator.push_all(t.principal.0.substs.regions().as_slice()); |
7060 | } | |
62682a34 SL |
7061 | TyEnum(_, substs) | |
7062 | TyStruct(_, substs) => { | |
1a4d82fc JJ |
7063 | accum_substs(accumulator, substs); |
7064 | } | |
62682a34 | 7065 | TyClosure(_, substs) => { |
1a4d82fc JJ |
7066 | accum_substs(accumulator, substs); |
7067 | } | |
62682a34 SL |
7068 | TyBool | |
7069 | TyChar | | |
7070 | TyInt(_) | | |
7071 | TyUint(_) | | |
7072 | TyFloat(_) | | |
7073 | TyBox(_) | | |
7074 | TyStr | | |
7075 | TyArray(_, _) | | |
7076 | TySlice(_) | | |
7077 | TyRawPtr(_) | | |
7078 | TyBareFn(..) | | |
7079 | TyTuple(_) | | |
7080 | TyProjection(_) | | |
7081 | TyParam(_) | | |
7082 | TyInfer(_) | | |
7083 | TyError => { | |
970d7e83 | 7084 | } |
223e47cc | 7085 | } |
1a4d82fc JJ |
7086 | }); |
7087 | ||
7088 | fn accum_substs(accumulator: &mut Vec<Region>, substs: &Substs) { | |
7089 | match substs.regions { | |
7090 | subst::ErasedRegions => {} | |
7091 | subst::NonerasedRegions(ref regions) => { | |
62682a34 | 7092 | for region in regions { |
1a4d82fc JJ |
7093 | accumulator.push(*region) |
7094 | } | |
7095 | } | |
223e47cc LB |
7096 | } |
7097 | } | |
7098 | } | |
7099 | ||
1a4d82fc | 7100 | /// A free variable referred to in a function. |
85aaf69f | 7101 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] |
1a4d82fc JJ |
7102 | pub struct Freevar { |
7103 | /// The variable being accessed free. | |
7104 | pub def: def::Def, | |
7105 | ||
7106 | // First span where it is accessed (there can be multiple). | |
7107 | pub span: Span | |
7108 | } | |
7109 | ||
7110 | pub type FreevarMap = NodeMap<Vec<Freevar>>; | |
7111 | ||
7112 | pub type CaptureModeMap = NodeMap<ast::CaptureClause>; | |
7113 | ||
7114 | // Trait method resolution | |
7115 | pub type TraitMap = NodeMap<Vec<DefId>>; | |
7116 | ||
7117 | // Map from the NodeId of a glob import to a list of items which are actually | |
7118 | // imported. | |
7119 | pub type GlobMap = HashMap<NodeId, HashSet<Name>>; | |
7120 | ||
7121 | pub fn with_freevars<T, F>(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where | |
7122 | F: FnOnce(&[Freevar]) -> T, | |
7123 | { | |
7124 | match tcx.freevars.borrow().get(&fid) { | |
7125 | None => f(&[]), | |
85aaf69f | 7126 | Some(d) => f(&d[..]) |
1a4d82fc JJ |
7127 | } |
7128 | } | |
7129 | ||
7130 | impl<'tcx> AutoAdjustment<'tcx> { | |
7131 | pub fn is_identity(&self) -> bool { | |
7132 | match *self { | |
9346a6ac AL |
7133 | AdjustReifyFnPointer | |
7134 | AdjustUnsafeFnPointer => false, | |
1a4d82fc | 7135 | AdjustDerefRef(ref r) => r.is_identity(), |
223e47cc | 7136 | } |
1a4d82fc JJ |
7137 | } |
7138 | } | |
7139 | ||
7140 | impl<'tcx> AutoDerefRef<'tcx> { | |
7141 | pub fn is_identity(&self) -> bool { | |
9346a6ac | 7142 | self.autoderefs == 0 && self.unsize.is_none() && self.autoref.is_none() |
1a4d82fc JJ |
7143 | } |
7144 | } | |
7145 | ||
7146 | /// Replace any late-bound regions bound in `value` with free variants attached to scope-id | |
7147 | /// `scope_id`. | |
7148 | pub fn liberate_late_bound_regions<'tcx, T>( | |
7149 | tcx: &ty::ctxt<'tcx>, | |
85aaf69f | 7150 | all_outlive_scope: region::DestructionScopeData, |
1a4d82fc JJ |
7151 | value: &Binder<T>) |
7152 | -> T | |
62682a34 | 7153 | where T : TypeFoldable<'tcx> |
1a4d82fc | 7154 | { |
62682a34 | 7155 | ty_fold::replace_late_bound_regions( |
1a4d82fc | 7156 | tcx, value, |
85aaf69f | 7157 | |br| ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, bound_region: br})).0 |
1a4d82fc JJ |
7158 | } |
7159 | ||
7160 | pub fn count_late_bound_regions<'tcx, T>( | |
7161 | tcx: &ty::ctxt<'tcx>, | |
7162 | value: &Binder<T>) | |
c34b1796 | 7163 | -> usize |
62682a34 | 7164 | where T : TypeFoldable<'tcx> |
1a4d82fc | 7165 | { |
62682a34 | 7166 | let (_, skol_map) = ty_fold::replace_late_bound_regions(tcx, value, |_| ty::ReStatic); |
1a4d82fc JJ |
7167 | skol_map.len() |
7168 | } | |
7169 | ||
7170 | pub fn binds_late_bound_regions<'tcx, T>( | |
7171 | tcx: &ty::ctxt<'tcx>, | |
7172 | value: &Binder<T>) | |
7173 | -> bool | |
62682a34 | 7174 | where T : TypeFoldable<'tcx> |
1a4d82fc JJ |
7175 | { |
7176 | count_late_bound_regions(tcx, value) > 0 | |
7177 | } | |
7178 | ||
c34b1796 AL |
7179 | /// Flattens two binding levels into one. So `for<'a> for<'b> Foo` |
7180 | /// becomes `for<'a,'b> Foo`. | |
7181 | pub fn flatten_late_bound_regions<'tcx, T>( | |
7182 | tcx: &ty::ctxt<'tcx>, | |
7183 | bound2_value: &Binder<Binder<T>>) | |
7184 | -> Binder<T> | |
62682a34 | 7185 | where T: TypeFoldable<'tcx> |
c34b1796 AL |
7186 | { |
7187 | let bound0_value = bound2_value.skip_binder().skip_binder(); | |
7188 | let value = ty_fold::fold_regions(tcx, bound0_value, |region, current_depth| { | |
7189 | match region { | |
7190 | ty::ReLateBound(debruijn, br) if debruijn.depth >= current_depth => { | |
7191 | // should be true if no escaping regions from bound2_value | |
7192 | assert!(debruijn.depth - current_depth <= 1); | |
7193 | ty::ReLateBound(DebruijnIndex::new(current_depth), br) | |
7194 | } | |
7195 | _ => { | |
7196 | region | |
7197 | } | |
7198 | } | |
7199 | }); | |
7200 | Binder(value) | |
7201 | } | |
7202 | ||
85aaf69f | 7203 | pub fn no_late_bound_regions<'tcx, T>( |
1a4d82fc JJ |
7204 | tcx: &ty::ctxt<'tcx>, |
7205 | value: &Binder<T>) | |
85aaf69f | 7206 | -> Option<T> |
62682a34 | 7207 | where T : TypeFoldable<'tcx> |
1a4d82fc | 7208 | { |
85aaf69f SL |
7209 | if binds_late_bound_regions(tcx, value) { |
7210 | None | |
7211 | } else { | |
7212 | Some(value.0.clone()) | |
7213 | } | |
1a4d82fc JJ |
7214 | } |
7215 | ||
7216 | /// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also | |
7217 | /// method lookup and a few other places where precise region relationships are not required. | |
7218 | pub fn erase_late_bound_regions<'tcx, T>( | |
7219 | tcx: &ty::ctxt<'tcx>, | |
7220 | value: &Binder<T>) | |
7221 | -> T | |
62682a34 | 7222 | where T : TypeFoldable<'tcx> |
1a4d82fc | 7223 | { |
62682a34 | 7224 | ty_fold::replace_late_bound_regions(tcx, value, |_| ty::ReStatic).0 |
1a4d82fc JJ |
7225 | } |
7226 | ||
7227 | /// Rewrite any late-bound regions so that they are anonymous. Region numbers are | |
7228 | /// assigned starting at 1 and increasing monotonically in the order traversed | |
7229 | /// by the fold operation. | |
7230 | /// | |
7231 | /// The chief purpose of this function is to canonicalize regions so that two | |
7232 | /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become | |
c34b1796 AL |
7233 | /// structurally identical. For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and |
7234 | /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization. | |
1a4d82fc JJ |
7235 | pub fn anonymize_late_bound_regions<'tcx, T>( |
7236 | tcx: &ctxt<'tcx>, | |
7237 | sig: &Binder<T>) | |
7238 | -> Binder<T> | |
62682a34 | 7239 | where T : TypeFoldable<'tcx>, |
1a4d82fc JJ |
7240 | { |
7241 | let mut counter = 0; | |
62682a34 | 7242 | ty::Binder(ty_fold::replace_late_bound_regions(tcx, sig, |_| { |
1a4d82fc JJ |
7243 | counter += 1; |
7244 | ReLateBound(ty::DebruijnIndex::new(1), BrAnon(counter)) | |
7245 | }).0) | |
7246 | } | |
7247 | ||
1a4d82fc JJ |
7248 | impl DebruijnIndex { |
7249 | pub fn new(depth: u32) -> DebruijnIndex { | |
7250 | assert!(depth > 0); | |
7251 | DebruijnIndex { depth: depth } | |
7252 | } | |
7253 | ||
7254 | pub fn shifted(&self, amount: u32) -> DebruijnIndex { | |
7255 | DebruijnIndex { depth: self.depth + amount } | |
7256 | } | |
7257 | } | |
7258 | ||
62682a34 SL |
7259 | impl<'tcx> fmt::Debug for AutoAdjustment<'tcx> { |
7260 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
1a4d82fc | 7261 | match *self { |
9346a6ac | 7262 | AdjustReifyFnPointer => { |
62682a34 | 7263 | write!(f, "AdjustReifyFnPointer") |
1a4d82fc | 7264 | } |
c34b1796 | 7265 | AdjustUnsafeFnPointer => { |
62682a34 | 7266 | write!(f, "AdjustUnsafeFnPointer") |
c34b1796 | 7267 | } |
1a4d82fc | 7268 | AdjustDerefRef(ref data) => { |
62682a34 | 7269 | write!(f, "{:?}", data) |
1a4d82fc | 7270 | } |
223e47cc | 7271 | } |
1a4d82fc JJ |
7272 | } |
7273 | } | |
7274 | ||
62682a34 SL |
7275 | impl<'tcx> fmt::Debug for AutoDerefRef<'tcx> { |
7276 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7277 | write!(f, "AutoDerefRef({}, unsize={:?}, {:?})", | |
7278 | self.autoderefs, self.unsize, self.autoref) | |
223e47cc LB |
7279 | } |
7280 | } | |
7281 | ||
62682a34 SL |
7282 | impl<'tcx> fmt::Debug for TraitTy<'tcx> { |
7283 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7284 | write!(f, "TraitTy({:?},{:?})", | |
7285 | self.principal, | |
7286 | self.bounds) | |
223e47cc | 7287 | } |
1a4d82fc | 7288 | } |
223e47cc | 7289 | |
62682a34 SL |
7290 | impl<'tcx> fmt::Debug for ty::Predicate<'tcx> { |
7291 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
1a4d82fc | 7292 | match *self { |
62682a34 SL |
7293 | Predicate::Trait(ref a) => write!(f, "{:?}", a), |
7294 | Predicate::Equate(ref pair) => write!(f, "{:?}", pair), | |
7295 | Predicate::RegionOutlives(ref pair) => write!(f, "{:?}", pair), | |
7296 | Predicate::TypeOutlives(ref pair) => write!(f, "{:?}", pair), | |
7297 | Predicate::Projection(ref pair) => write!(f, "{:?}", pair), | |
1a4d82fc JJ |
7298 | } |
7299 | } | |
970d7e83 LB |
7300 | } |
7301 | ||
1a4d82fc JJ |
7302 | pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>, |
7303 | trait_ref: &ty::TraitRef<'tcx>, | |
7304 | method: &ty::Method<'tcx>) | |
7305 | -> subst::Substs<'tcx> | |
970d7e83 LB |
7306 | { |
7307 | /*! | |
1a4d82fc JJ |
7308 | * Substitutes the values for the receiver's type parameters |
7309 | * that are found in method, leaving the method's type parameters | |
7310 | * intact. | |
970d7e83 LB |
7311 | */ |
7312 | ||
1a4d82fc JJ |
7313 | let meth_tps: Vec<Ty> = |
7314 | method.generics.types.get_slice(subst::FnSpace) | |
7315 | .iter() | |
7316 | .map(|def| ty::mk_param_from_def(tcx, def)) | |
7317 | .collect(); | |
7318 | let meth_regions: Vec<ty::Region> = | |
7319 | method.generics.regions.get_slice(subst::FnSpace) | |
7320 | .iter() | |
9346a6ac | 7321 | .map(|def| def.to_early_bound_region()) |
1a4d82fc JJ |
7322 | .collect(); |
7323 | trait_ref.substs.clone().with_method(meth_tps, meth_regions) | |
7324 | } | |
7325 | ||
c34b1796 | 7326 | #[derive(Copy, Clone)] |
1a4d82fc JJ |
7327 | pub enum CopyImplementationError { |
7328 | FieldDoesNotImplementCopy(ast::Name), | |
7329 | VariantDoesNotImplementCopy(ast::Name), | |
7330 | TypeIsStructural, | |
7331 | TypeHasDestructor, | |
7332 | } | |
7333 | ||
7334 | pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tcx>, | |
7335 | span: Span, | |
7336 | self_type: Ty<'tcx>) | |
7337 | -> Result<(),CopyImplementationError> | |
7338 | { | |
7339 | let tcx = param_env.tcx; | |
7340 | ||
7341 | let did = match self_type.sty { | |
62682a34 | 7342 | ty::TyStruct(struct_did, substs) => { |
1a4d82fc | 7343 | let fields = ty::struct_fields(tcx, struct_did, substs); |
85aaf69f | 7344 | for field in &fields { |
1a4d82fc JJ |
7345 | if type_moves_by_default(param_env, span, field.mt.ty) { |
7346 | return Err(FieldDoesNotImplementCopy(field.name)) | |
7347 | } | |
7348 | } | |
7349 | struct_did | |
7350 | } | |
62682a34 | 7351 | ty::TyEnum(enum_did, substs) => { |
1a4d82fc | 7352 | let enum_variants = ty::enum_variants(tcx, enum_did); |
62682a34 | 7353 | for variant in enum_variants.iter() { |
85aaf69f | 7354 | for variant_arg_type in &variant.args { |
1a4d82fc JJ |
7355 | let substd_arg_type = |
7356 | variant_arg_type.subst(tcx, substs); | |
7357 | if type_moves_by_default(param_env, span, substd_arg_type) { | |
7358 | return Err(VariantDoesNotImplementCopy(variant.name)) | |
7359 | } | |
7360 | } | |
7361 | } | |
7362 | enum_did | |
7363 | } | |
7364 | _ => return Err(TypeIsStructural), | |
7365 | }; | |
223e47cc | 7366 | |
1a4d82fc JJ |
7367 | if ty::has_dtor(tcx, did) { |
7368 | return Err(TypeHasDestructor) | |
970d7e83 | 7369 | } |
223e47cc | 7370 | |
1a4d82fc | 7371 | Ok(()) |
970d7e83 | 7372 | } |
223e47cc | 7373 | |
1a4d82fc JJ |
7374 | // FIXME(#20298) -- all of these types basically walk various |
7375 | // structures to test whether types/regions are reachable with various | |
7376 | // properties. It should be possible to express them in terms of one | |
7377 | // common "walker" trait or something. | |
970d7e83 | 7378 | |
1a4d82fc JJ |
7379 | pub trait RegionEscape { |
7380 | fn has_escaping_regions(&self) -> bool { | |
7381 | self.has_regions_escaping_depth(0) | |
223e47cc | 7382 | } |
1a4d82fc JJ |
7383 | |
7384 | fn has_regions_escaping_depth(&self, depth: u32) -> bool; | |
223e47cc LB |
7385 | } |
7386 | ||
1a4d82fc JJ |
7387 | impl<'tcx> RegionEscape for Ty<'tcx> { |
7388 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7389 | ty::type_escapes_depth(*self, depth) | |
223e47cc | 7390 | } |
970d7e83 | 7391 | } |
223e47cc | 7392 | |
1a4d82fc JJ |
7393 | impl<'tcx> RegionEscape for Substs<'tcx> { |
7394 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7395 | self.types.has_regions_escaping_depth(depth) || | |
7396 | self.regions.has_regions_escaping_depth(depth) | |
7397 | } | |
970d7e83 LB |
7398 | } |
7399 | ||
1a4d82fc JJ |
7400 | impl<'tcx,T:RegionEscape> RegionEscape for VecPerParamSpace<T> { |
7401 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7402 | self.iter_enumerated().any(|(space, _, t)| { | |
7403 | if space == subst::FnSpace { | |
7404 | t.has_regions_escaping_depth(depth+1) | |
7405 | } else { | |
7406 | t.has_regions_escaping_depth(depth) | |
970d7e83 | 7407 | } |
1a4d82fc | 7408 | }) |
223e47cc LB |
7409 | } |
7410 | } | |
7411 | ||
1a4d82fc JJ |
7412 | impl<'tcx> RegionEscape for TypeScheme<'tcx> { |
7413 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
85aaf69f | 7414 | self.ty.has_regions_escaping_depth(depth) |
223e47cc LB |
7415 | } |
7416 | } | |
7417 | ||
1a4d82fc JJ |
7418 | impl RegionEscape for Region { |
7419 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7420 | self.escapes_depth(depth) | |
223e47cc LB |
7421 | } |
7422 | } | |
7423 | ||
85aaf69f | 7424 | impl<'tcx> RegionEscape for GenericPredicates<'tcx> { |
1a4d82fc JJ |
7425 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { |
7426 | self.predicates.has_regions_escaping_depth(depth) | |
7427 | } | |
223e47cc LB |
7428 | } |
7429 | ||
1a4d82fc JJ |
7430 | impl<'tcx> RegionEscape for Predicate<'tcx> { |
7431 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7432 | match *self { | |
7433 | Predicate::Trait(ref data) => data.has_regions_escaping_depth(depth), | |
7434 | Predicate::Equate(ref data) => data.has_regions_escaping_depth(depth), | |
7435 | Predicate::RegionOutlives(ref data) => data.has_regions_escaping_depth(depth), | |
7436 | Predicate::TypeOutlives(ref data) => data.has_regions_escaping_depth(depth), | |
7437 | Predicate::Projection(ref data) => data.has_regions_escaping_depth(depth), | |
7438 | } | |
7439 | } | |
223e47cc LB |
7440 | } |
7441 | ||
c34b1796 AL |
7442 | impl<'tcx,P:RegionEscape> RegionEscape for traits::Obligation<'tcx,P> { |
7443 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7444 | self.predicate.has_regions_escaping_depth(depth) | |
7445 | } | |
7446 | } | |
7447 | ||
1a4d82fc JJ |
7448 | impl<'tcx> RegionEscape for TraitRef<'tcx> { |
7449 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7450 | self.substs.types.iter().any(|t| t.has_regions_escaping_depth(depth)) || | |
7451 | self.substs.regions.has_regions_escaping_depth(depth) | |
7452 | } | |
223e47cc LB |
7453 | } |
7454 | ||
1a4d82fc JJ |
7455 | impl<'tcx> RegionEscape for subst::RegionSubsts { |
7456 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
223e47cc | 7457 | match *self { |
1a4d82fc JJ |
7458 | subst::ErasedRegions => false, |
7459 | subst::NonerasedRegions(ref r) => { | |
7460 | r.iter().any(|t| t.has_regions_escaping_depth(depth)) | |
7461 | } | |
223e47cc LB |
7462 | } |
7463 | } | |
1a4d82fc | 7464 | } |
970d7e83 | 7465 | |
1a4d82fc JJ |
7466 | impl<'tcx,T:RegionEscape> RegionEscape for Binder<T> { |
7467 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7468 | self.0.has_regions_escaping_depth(depth + 1) | |
223e47cc | 7469 | } |
1a4d82fc | 7470 | } |
970d7e83 | 7471 | |
1a4d82fc JJ |
7472 | impl<'tcx> RegionEscape for EquatePredicate<'tcx> { |
7473 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7474 | self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth) | |
970d7e83 | 7475 | } |
223e47cc LB |
7476 | } |
7477 | ||
1a4d82fc JJ |
7478 | impl<'tcx> RegionEscape for TraitPredicate<'tcx> { |
7479 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7480 | self.trait_ref.has_regions_escaping_depth(depth) | |
223e47cc LB |
7481 | } |
7482 | } | |
7483 | ||
1a4d82fc JJ |
7484 | impl<T:RegionEscape,U:RegionEscape> RegionEscape for OutlivesPredicate<T,U> { |
7485 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7486 | self.0.has_regions_escaping_depth(depth) || self.1.has_regions_escaping_depth(depth) | |
7487 | } | |
223e47cc LB |
7488 | } |
7489 | ||
1a4d82fc JJ |
7490 | impl<'tcx> RegionEscape for ProjectionPredicate<'tcx> { |
7491 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7492 | self.projection_ty.has_regions_escaping_depth(depth) || | |
7493 | self.ty.has_regions_escaping_depth(depth) | |
7494 | } | |
7495 | } | |
223e47cc | 7496 | |
1a4d82fc JJ |
7497 | impl<'tcx> RegionEscape for ProjectionTy<'tcx> { |
7498 | fn has_regions_escaping_depth(&self, depth: u32) -> bool { | |
7499 | self.trait_ref.has_regions_escaping_depth(depth) | |
223e47cc LB |
7500 | } |
7501 | } | |
7502 | ||
1a4d82fc JJ |
7503 | pub trait HasProjectionTypes { |
7504 | fn has_projection_types(&self) -> bool; | |
223e47cc LB |
7505 | } |
7506 | ||
1a4d82fc JJ |
7507 | impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for Vec<T> { |
7508 | fn has_projection_types(&self) -> bool { | |
7509 | self.iter().any(|p| p.has_projection_types()) | |
223e47cc | 7510 | } |
223e47cc LB |
7511 | } |
7512 | ||
1a4d82fc JJ |
7513 | impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for VecPerParamSpace<T> { |
7514 | fn has_projection_types(&self) -> bool { | |
7515 | self.iter().any(|p| p.has_projection_types()) | |
223e47cc | 7516 | } |
223e47cc LB |
7517 | } |
7518 | ||
1a4d82fc JJ |
7519 | impl<'tcx> HasProjectionTypes for ClosureTy<'tcx> { |
7520 | fn has_projection_types(&self) -> bool { | |
7521 | self.sig.has_projection_types() | |
7522 | } | |
7523 | } | |
223e47cc | 7524 | |
85aaf69f | 7525 | impl<'tcx> HasProjectionTypes for ClosureUpvar<'tcx> { |
1a4d82fc JJ |
7526 | fn has_projection_types(&self) -> bool { |
7527 | self.ty.has_projection_types() | |
7528 | } | |
970d7e83 LB |
7529 | } |
7530 | ||
85aaf69f | 7531 | impl<'tcx> HasProjectionTypes for ty::InstantiatedPredicates<'tcx> { |
1a4d82fc JJ |
7532 | fn has_projection_types(&self) -> bool { |
7533 | self.predicates.has_projection_types() | |
970d7e83 LB |
7534 | } |
7535 | } | |
7536 | ||
1a4d82fc JJ |
7537 | impl<'tcx> HasProjectionTypes for Predicate<'tcx> { |
7538 | fn has_projection_types(&self) -> bool { | |
7539 | match *self { | |
7540 | Predicate::Trait(ref data) => data.has_projection_types(), | |
7541 | Predicate::Equate(ref data) => data.has_projection_types(), | |
7542 | Predicate::RegionOutlives(ref data) => data.has_projection_types(), | |
7543 | Predicate::TypeOutlives(ref data) => data.has_projection_types(), | |
7544 | Predicate::Projection(ref data) => data.has_projection_types(), | |
970d7e83 | 7545 | } |
223e47cc LB |
7546 | } |
7547 | } | |
7548 | ||
1a4d82fc JJ |
7549 | impl<'tcx> HasProjectionTypes for TraitPredicate<'tcx> { |
7550 | fn has_projection_types(&self) -> bool { | |
7551 | self.trait_ref.has_projection_types() | |
7552 | } | |
970d7e83 LB |
7553 | } |
7554 | ||
1a4d82fc JJ |
7555 | impl<'tcx> HasProjectionTypes for EquatePredicate<'tcx> { |
7556 | fn has_projection_types(&self) -> bool { | |
7557 | self.0.has_projection_types() || self.1.has_projection_types() | |
7558 | } | |
970d7e83 LB |
7559 | } |
7560 | ||
1a4d82fc JJ |
7561 | impl HasProjectionTypes for Region { |
7562 | fn has_projection_types(&self) -> bool { | |
7563 | false | |
223e47cc LB |
7564 | } |
7565 | } | |
7566 | ||
1a4d82fc JJ |
7567 | impl<T:HasProjectionTypes,U:HasProjectionTypes> HasProjectionTypes for OutlivesPredicate<T,U> { |
7568 | fn has_projection_types(&self) -> bool { | |
7569 | self.0.has_projection_types() || self.1.has_projection_types() | |
223e47cc LB |
7570 | } |
7571 | } | |
7572 | ||
1a4d82fc JJ |
7573 | impl<'tcx> HasProjectionTypes for ProjectionPredicate<'tcx> { |
7574 | fn has_projection_types(&self) -> bool { | |
7575 | self.projection_ty.has_projection_types() || self.ty.has_projection_types() | |
223e47cc LB |
7576 | } |
7577 | } | |
7578 | ||
1a4d82fc JJ |
7579 | impl<'tcx> HasProjectionTypes for ProjectionTy<'tcx> { |
7580 | fn has_projection_types(&self) -> bool { | |
7581 | self.trait_ref.has_projection_types() | |
223e47cc LB |
7582 | } |
7583 | } | |
7584 | ||
1a4d82fc JJ |
7585 | impl<'tcx> HasProjectionTypes for Ty<'tcx> { |
7586 | fn has_projection_types(&self) -> bool { | |
7587 | ty::type_has_projection(*self) | |
7588 | } | |
7589 | } | |
223e47cc | 7590 | |
1a4d82fc JJ |
7591 | impl<'tcx> HasProjectionTypes for TraitRef<'tcx> { |
7592 | fn has_projection_types(&self) -> bool { | |
7593 | self.substs.has_projection_types() | |
223e47cc | 7594 | } |
1a4d82fc | 7595 | } |
223e47cc | 7596 | |
1a4d82fc JJ |
7597 | impl<'tcx> HasProjectionTypes for subst::Substs<'tcx> { |
7598 | fn has_projection_types(&self) -> bool { | |
7599 | self.types.iter().any(|t| t.has_projection_types()) | |
7600 | } | |
7601 | } | |
223e47cc | 7602 | |
1a4d82fc JJ |
7603 | impl<'tcx,T> HasProjectionTypes for Option<T> |
7604 | where T : HasProjectionTypes | |
7605 | { | |
7606 | fn has_projection_types(&self) -> bool { | |
7607 | self.iter().any(|t| t.has_projection_types()) | |
7608 | } | |
7609 | } | |
223e47cc | 7610 | |
1a4d82fc JJ |
7611 | impl<'tcx,T> HasProjectionTypes for Rc<T> |
7612 | where T : HasProjectionTypes | |
7613 | { | |
7614 | fn has_projection_types(&self) -> bool { | |
7615 | (**self).has_projection_types() | |
7616 | } | |
223e47cc LB |
7617 | } |
7618 | ||
1a4d82fc JJ |
7619 | impl<'tcx,T> HasProjectionTypes for Box<T> |
7620 | where T : HasProjectionTypes | |
7621 | { | |
7622 | fn has_projection_types(&self) -> bool { | |
7623 | (**self).has_projection_types() | |
7624 | } | |
223e47cc LB |
7625 | } |
7626 | ||
1a4d82fc JJ |
7627 | impl<T> HasProjectionTypes for Binder<T> |
7628 | where T : HasProjectionTypes | |
7629 | { | |
7630 | fn has_projection_types(&self) -> bool { | |
7631 | self.0.has_projection_types() | |
223e47cc | 7632 | } |
1a4d82fc JJ |
7633 | } |
7634 | ||
7635 | impl<'tcx> HasProjectionTypes for FnOutput<'tcx> { | |
7636 | fn has_projection_types(&self) -> bool { | |
7637 | match *self { | |
7638 | FnConverging(t) => t.has_projection_types(), | |
7639 | FnDiverging => false, | |
223e47cc LB |
7640 | } |
7641 | } | |
1a4d82fc | 7642 | } |
223e47cc | 7643 | |
1a4d82fc JJ |
7644 | impl<'tcx> HasProjectionTypes for FnSig<'tcx> { |
7645 | fn has_projection_types(&self) -> bool { | |
7646 | self.inputs.iter().any(|t| t.has_projection_types()) || | |
7647 | self.output.has_projection_types() | |
223e47cc | 7648 | } |
1a4d82fc | 7649 | } |
223e47cc | 7650 | |
1a4d82fc JJ |
7651 | impl<'tcx> HasProjectionTypes for field<'tcx> { |
7652 | fn has_projection_types(&self) -> bool { | |
7653 | self.mt.ty.has_projection_types() | |
7654 | } | |
7655 | } | |
223e47cc | 7656 | |
1a4d82fc JJ |
7657 | impl<'tcx> HasProjectionTypes for BareFnTy<'tcx> { |
7658 | fn has_projection_types(&self) -> bool { | |
7659 | self.sig.has_projection_types() | |
7660 | } | |
7661 | } | |
223e47cc | 7662 | |
1a4d82fc JJ |
7663 | pub trait ReferencesError { |
7664 | fn references_error(&self) -> bool; | |
7665 | } | |
223e47cc | 7666 | |
1a4d82fc JJ |
7667 | impl<T:ReferencesError> ReferencesError for Binder<T> { |
7668 | fn references_error(&self) -> bool { | |
7669 | self.0.references_error() | |
7670 | } | |
7671 | } | |
223e47cc | 7672 | |
1a4d82fc JJ |
7673 | impl<T:ReferencesError> ReferencesError for Rc<T> { |
7674 | fn references_error(&self) -> bool { | |
7675 | (&**self).references_error() | |
7676 | } | |
223e47cc LB |
7677 | } |
7678 | ||
1a4d82fc JJ |
7679 | impl<'tcx> ReferencesError for TraitPredicate<'tcx> { |
7680 | fn references_error(&self) -> bool { | |
7681 | self.trait_ref.references_error() | |
223e47cc LB |
7682 | } |
7683 | } | |
7684 | ||
1a4d82fc JJ |
7685 | impl<'tcx> ReferencesError for ProjectionPredicate<'tcx> { |
7686 | fn references_error(&self) -> bool { | |
7687 | self.projection_ty.trait_ref.references_error() || self.ty.references_error() | |
223e47cc LB |
7688 | } |
7689 | } | |
7690 | ||
1a4d82fc JJ |
7691 | impl<'tcx> ReferencesError for TraitRef<'tcx> { |
7692 | fn references_error(&self) -> bool { | |
7693 | self.input_types().iter().any(|t| t.references_error()) | |
7694 | } | |
7695 | } | |
223e47cc | 7696 | |
1a4d82fc JJ |
7697 | impl<'tcx> ReferencesError for Ty<'tcx> { |
7698 | fn references_error(&self) -> bool { | |
7699 | type_is_error(*self) | |
7700 | } | |
7701 | } | |
970d7e83 | 7702 | |
1a4d82fc JJ |
7703 | impl<'tcx> ReferencesError for Predicate<'tcx> { |
7704 | fn references_error(&self) -> bool { | |
7705 | match *self { | |
7706 | Predicate::Trait(ref data) => data.references_error(), | |
7707 | Predicate::Equate(ref data) => data.references_error(), | |
7708 | Predicate::RegionOutlives(ref data) => data.references_error(), | |
7709 | Predicate::TypeOutlives(ref data) => data.references_error(), | |
7710 | Predicate::Projection(ref data) => data.references_error(), | |
970d7e83 | 7711 | } |
223e47cc LB |
7712 | } |
7713 | } | |
7714 | ||
1a4d82fc JJ |
7715 | impl<A,B> ReferencesError for OutlivesPredicate<A,B> |
7716 | where A : ReferencesError, B : ReferencesError | |
7717 | { | |
7718 | fn references_error(&self) -> bool { | |
7719 | self.0.references_error() || self.1.references_error() | |
223e47cc | 7720 | } |
223e47cc LB |
7721 | } |
7722 | ||
1a4d82fc JJ |
7723 | impl<'tcx> ReferencesError for EquatePredicate<'tcx> |
7724 | { | |
7725 | fn references_error(&self) -> bool { | |
7726 | self.0.references_error() || self.1.references_error() | |
223e47cc LB |
7727 | } |
7728 | } | |
7729 | ||
1a4d82fc JJ |
7730 | impl ReferencesError for Region |
7731 | { | |
7732 | fn references_error(&self) -> bool { | |
7733 | false | |
7734 | } | |
970d7e83 LB |
7735 | } |
7736 | ||
62682a34 SL |
7737 | impl<'tcx> fmt::Debug for ClosureTy<'tcx> { |
7738 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7739 | write!(f, "ClosureTy({},{:?},{})", | |
7740 | self.unsafety, | |
7741 | self.sig, | |
7742 | self.abi) | |
1a4d82fc | 7743 | } |
970d7e83 LB |
7744 | } |
7745 | ||
62682a34 SL |
7746 | impl<'tcx> fmt::Debug for ClosureUpvar<'tcx> { |
7747 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7748 | write!(f, "ClosureUpvar({:?},{:?})", | |
7749 | self.def, | |
7750 | self.ty) | |
1a4d82fc JJ |
7751 | } |
7752 | } | |
7753 | ||
62682a34 SL |
7754 | impl<'tcx> fmt::Debug for field<'tcx> { |
7755 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7756 | write!(f, "field({},{})", self.name, self.mt) | |
1a4d82fc | 7757 | } |
970d7e83 | 7758 | } |
85aaf69f | 7759 | |
62682a34 SL |
7760 | impl<'a, 'tcx> fmt::Debug for ParameterEnvironment<'a, 'tcx> { |
7761 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
7762 | write!(f, "ParameterEnvironment(\ | |
7763 | free_substs={:?}, \ | |
7764 | implicit_region_bound={:?}, \ | |
7765 | caller_bounds={:?})", | |
7766 | self.free_substs, | |
7767 | self.implicit_region_bound, | |
7768 | self.caller_bounds) | |
85aaf69f SL |
7769 | } |
7770 | } | |
7771 | ||
62682a34 SL |
7772 | impl<'tcx> fmt::Debug for ObjectLifetimeDefault { |
7773 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | |
85aaf69f | 7774 | match *self { |
62682a34 SL |
7775 | ObjectLifetimeDefault::Ambiguous => write!(f, "Ambiguous"), |
7776 | ObjectLifetimeDefault::BaseDefault => write!(f, "BaseDefault"), | |
7777 | ObjectLifetimeDefault::Specific(ref r) => write!(f, "{:?}", r), | |
85aaf69f SL |
7778 | } |
7779 | } | |
7780 | } |