]>
Commit | Line | Data |
---|---|---|
e9174d1e SL |
1 | // Copyright 2012-2015 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | pub use self::ImplOrTraitItemId::*; | |
12 | pub use self::ClosureKind::*; | |
13 | pub use self::Variance::*; | |
14 | pub use self::DtorKind::*; | |
e9174d1e SL |
15 | pub use self::ImplOrTraitItemContainer::*; |
16 | pub use self::BorrowKind::*; | |
17 | pub use self::ImplOrTraitItem::*; | |
18 | pub use self::IntVarValue::*; | |
19 | pub use self::LvaluePreference::*; | |
9cc50fc6 | 20 | pub use self::fold::TypeFoldable; |
e9174d1e | 21 | |
9cc50fc6 | 22 | use dep_graph::{self, DepNode}; |
e9174d1e SL |
23 | use front::map as ast_map; |
24 | use front::map::LinkedPath; | |
e9174d1e | 25 | use middle; |
9cc50fc6 | 26 | use middle::cstore::{self, CrateStore, LOCAL_CRATE}; |
7453a54e | 27 | use middle::def::{self, Def, ExportMap}; |
b039eaaf | 28 | use middle::def_id::DefId; |
e9174d1e | 29 | use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; |
9cc50fc6 SL |
30 | use middle::region::{CodeExtent}; |
31 | use middle::subst::{self, Subst, Substs, VecPerParamSpace}; | |
e9174d1e SL |
32 | use middle::traits; |
33 | use middle::ty; | |
34 | use middle::ty::fold::TypeFolder; | |
35 | use middle::ty::walk::TypeWalker; | |
9cc50fc6 SL |
36 | use util::common::MemoizationMap; |
37 | use util::nodemap::{NodeMap, NodeSet}; | |
e9174d1e SL |
38 | use util::nodemap::FnvHashMap; |
39 | ||
9cc50fc6 | 40 | use serialize::{Encodable, Encoder, Decodable, Decoder}; |
e9174d1e | 41 | use std::borrow::{Borrow, Cow}; |
9cc50fc6 | 42 | use std::cell::Cell; |
e9174d1e SL |
43 | use std::hash::{Hash, Hasher}; |
44 | use std::iter; | |
45 | use std::rc::Rc; | |
46 | use std::slice; | |
47 | use std::vec::IntoIter; | |
48 | use std::collections::{HashMap, HashSet}; | |
49 | use syntax::ast::{self, CrateNum, Name, NodeId}; | |
b039eaaf | 50 | use syntax::attr::{self, AttrMetaMethods}; |
9cc50fc6 SL |
51 | use syntax::codemap::{DUMMY_SP, Span}; |
52 | use syntax::parse::token::InternedString; | |
e9174d1e SL |
53 | |
54 | use rustc_front::hir; | |
7453a54e | 55 | use rustc_front::hir::{ItemImpl, ItemTrait, PatKind}; |
9cc50fc6 | 56 | use rustc_front::intravisit::Visitor; |
e9174d1e SL |
57 | |
58 | pub use self::sty::{Binder, DebruijnIndex}; | |
59 | pub use self::sty::{BuiltinBound, BuiltinBounds, ExistentialBounds}; | |
60 | pub use self::sty::{BareFnTy, FnSig, PolyFnSig, FnOutput, PolyFnOutput}; | |
61 | pub use self::sty::{ClosureTy, InferTy, ParamTy, ProjectionTy, TraitTy}; | |
62 | pub use self::sty::{ClosureSubsts, TypeAndMut}; | |
63 | pub use self::sty::{TraitRef, TypeVariants, PolyTraitRef}; | |
64 | pub use self::sty::{BoundRegion, EarlyBoundRegion, FreeRegion, Region}; | |
65 | pub use self::sty::{TyVid, IntVid, FloatVid, RegionVid, SkolemizedRegionVid}; | |
66 | pub use self::sty::BoundRegion::*; | |
67 | pub use self::sty::FnOutput::*; | |
68 | pub use self::sty::InferTy::*; | |
69 | pub use self::sty::Region::*; | |
70 | pub use self::sty::TypeVariants::*; | |
71 | ||
72 | pub use self::sty::BuiltinBound::Send as BoundSend; | |
73 | pub use self::sty::BuiltinBound::Sized as BoundSized; | |
74 | pub use self::sty::BuiltinBound::Copy as BoundCopy; | |
75 | pub use self::sty::BuiltinBound::Sync as BoundSync; | |
76 | ||
77 | pub use self::contents::TypeContents; | |
78 | pub use self::context::{ctxt, tls}; | |
79 | pub use self::context::{CtxtArenas, Lift, Tables}; | |
80 | ||
9cc50fc6 SL |
81 | pub use self::trait_def::{TraitDef, TraitFlags}; |
82 | ||
e9174d1e SL |
83 | pub mod adjustment; |
84 | pub mod cast; | |
85 | pub mod error; | |
86 | pub mod fast_reject; | |
87 | pub mod fold; | |
88 | pub mod _match; | |
9cc50fc6 | 89 | pub mod maps; |
e9174d1e SL |
90 | pub mod outlives; |
91 | pub mod relate; | |
9cc50fc6 | 92 | pub mod trait_def; |
e9174d1e SL |
93 | pub mod walk; |
94 | pub mod wf; | |
95 | pub mod util; | |
96 | ||
97 | mod contents; | |
98 | mod context; | |
99 | mod flags; | |
100 | mod ivar; | |
101 | mod structural_impls; | |
102 | mod sty; | |
103 | ||
104 | pub type Disr = u64; | |
105 | pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0; | |
106 | ||
107 | // Data types | |
108 | ||
109 | /// The complete set of all analyses described in this module. This is | |
110 | /// produced by the driver and fed to trans and later passes. | |
b039eaaf | 111 | pub struct CrateAnalysis<'a> { |
e9174d1e | 112 | pub export_map: ExportMap, |
92a42be0 | 113 | pub access_levels: middle::privacy::AccessLevels, |
e9174d1e | 114 | pub reachable: NodeSet, |
b039eaaf | 115 | pub name: &'a str, |
e9174d1e SL |
116 | pub glob_map: Option<GlobMap>, |
117 | } | |
118 | ||
e9174d1e SL |
119 | #[derive(Copy, Clone)] |
120 | pub enum DtorKind { | |
121 | NoDtor, | |
122 | TraitDtor(bool) | |
123 | } | |
124 | ||
125 | impl DtorKind { | |
126 | pub fn is_present(&self) -> bool { | |
127 | match *self { | |
128 | TraitDtor(..) => true, | |
129 | _ => false | |
130 | } | |
131 | } | |
132 | ||
133 | pub fn has_drop_flag(&self) -> bool { | |
134 | match self { | |
135 | &NoDtor => false, | |
136 | &TraitDtor(flag) => flag | |
137 | } | |
138 | } | |
139 | } | |
140 | ||
141 | #[derive(Clone, Copy, PartialEq, Eq, Debug)] | |
142 | pub enum ImplOrTraitItemContainer { | |
143 | TraitContainer(DefId), | |
144 | ImplContainer(DefId), | |
145 | } | |
146 | ||
147 | impl ImplOrTraitItemContainer { | |
148 | pub fn id(&self) -> DefId { | |
149 | match *self { | |
150 | TraitContainer(id) => id, | |
151 | ImplContainer(id) => id, | |
152 | } | |
153 | } | |
154 | } | |
155 | ||
156 | #[derive(Clone)] | |
157 | pub enum ImplOrTraitItem<'tcx> { | |
158 | ConstTraitItem(Rc<AssociatedConst<'tcx>>), | |
159 | MethodTraitItem(Rc<Method<'tcx>>), | |
160 | TypeTraitItem(Rc<AssociatedType<'tcx>>), | |
161 | } | |
162 | ||
163 | impl<'tcx> ImplOrTraitItem<'tcx> { | |
164 | fn id(&self) -> ImplOrTraitItemId { | |
165 | match *self { | |
166 | ConstTraitItem(ref associated_const) => { | |
167 | ConstTraitItemId(associated_const.def_id) | |
168 | } | |
169 | MethodTraitItem(ref method) => MethodTraitItemId(method.def_id), | |
170 | TypeTraitItem(ref associated_type) => { | |
171 | TypeTraitItemId(associated_type.def_id) | |
172 | } | |
173 | } | |
174 | } | |
175 | ||
176 | pub fn def_id(&self) -> DefId { | |
177 | match *self { | |
178 | ConstTraitItem(ref associated_const) => associated_const.def_id, | |
179 | MethodTraitItem(ref method) => method.def_id, | |
180 | TypeTraitItem(ref associated_type) => associated_type.def_id, | |
181 | } | |
182 | } | |
183 | ||
184 | pub fn name(&self) -> Name { | |
185 | match *self { | |
186 | ConstTraitItem(ref associated_const) => associated_const.name, | |
187 | MethodTraitItem(ref method) => method.name, | |
188 | TypeTraitItem(ref associated_type) => associated_type.name, | |
189 | } | |
190 | } | |
191 | ||
192 | pub fn vis(&self) -> hir::Visibility { | |
193 | match *self { | |
194 | ConstTraitItem(ref associated_const) => associated_const.vis, | |
195 | MethodTraitItem(ref method) => method.vis, | |
196 | TypeTraitItem(ref associated_type) => associated_type.vis, | |
197 | } | |
198 | } | |
199 | ||
200 | pub fn container(&self) -> ImplOrTraitItemContainer { | |
201 | match *self { | |
202 | ConstTraitItem(ref associated_const) => associated_const.container, | |
203 | MethodTraitItem(ref method) => method.container, | |
204 | TypeTraitItem(ref associated_type) => associated_type.container, | |
205 | } | |
206 | } | |
207 | ||
208 | pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> { | |
209 | match *self { | |
210 | MethodTraitItem(ref m) => Some((*m).clone()), | |
211 | _ => None, | |
212 | } | |
213 | } | |
214 | } | |
215 | ||
216 | #[derive(Clone, Copy, Debug)] | |
217 | pub enum ImplOrTraitItemId { | |
218 | ConstTraitItemId(DefId), | |
219 | MethodTraitItemId(DefId), | |
220 | TypeTraitItemId(DefId), | |
221 | } | |
222 | ||
223 | impl ImplOrTraitItemId { | |
224 | pub fn def_id(&self) -> DefId { | |
225 | match *self { | |
226 | ConstTraitItemId(def_id) => def_id, | |
227 | MethodTraitItemId(def_id) => def_id, | |
228 | TypeTraitItemId(def_id) => def_id, | |
229 | } | |
230 | } | |
231 | } | |
232 | ||
233 | #[derive(Clone, Debug)] | |
234 | pub struct Method<'tcx> { | |
235 | pub name: Name, | |
236 | pub generics: Generics<'tcx>, | |
237 | pub predicates: GenericPredicates<'tcx>, | |
238 | pub fty: BareFnTy<'tcx>, | |
239 | pub explicit_self: ExplicitSelfCategory, | |
240 | pub vis: hir::Visibility, | |
241 | pub def_id: DefId, | |
242 | pub container: ImplOrTraitItemContainer, | |
e9174d1e SL |
243 | } |
244 | ||
245 | impl<'tcx> Method<'tcx> { | |
246 | pub fn new(name: Name, | |
247 | generics: ty::Generics<'tcx>, | |
248 | predicates: GenericPredicates<'tcx>, | |
249 | fty: BareFnTy<'tcx>, | |
250 | explicit_self: ExplicitSelfCategory, | |
251 | vis: hir::Visibility, | |
252 | def_id: DefId, | |
b039eaaf | 253 | container: ImplOrTraitItemContainer) |
e9174d1e SL |
254 | -> Method<'tcx> { |
255 | Method { | |
256 | name: name, | |
257 | generics: generics, | |
258 | predicates: predicates, | |
259 | fty: fty, | |
260 | explicit_self: explicit_self, | |
261 | vis: vis, | |
262 | def_id: def_id, | |
263 | container: container, | |
e9174d1e SL |
264 | } |
265 | } | |
266 | ||
267 | pub fn container_id(&self) -> DefId { | |
268 | match self.container { | |
269 | TraitContainer(id) => id, | |
270 | ImplContainer(id) => id, | |
271 | } | |
272 | } | |
273 | } | |
274 | ||
275 | impl<'tcx> PartialEq for Method<'tcx> { | |
276 | #[inline] | |
277 | fn eq(&self, other: &Self) -> bool { self.def_id == other.def_id } | |
278 | } | |
279 | ||
280 | impl<'tcx> Eq for Method<'tcx> {} | |
281 | ||
282 | impl<'tcx> Hash for Method<'tcx> { | |
283 | #[inline] | |
284 | fn hash<H: Hasher>(&self, s: &mut H) { | |
285 | self.def_id.hash(s) | |
286 | } | |
287 | } | |
288 | ||
289 | #[derive(Clone, Copy, Debug)] | |
290 | pub struct AssociatedConst<'tcx> { | |
291 | pub name: Name, | |
292 | pub ty: Ty<'tcx>, | |
293 | pub vis: hir::Visibility, | |
294 | pub def_id: DefId, | |
295 | pub container: ImplOrTraitItemContainer, | |
b039eaaf | 296 | pub has_value: bool |
e9174d1e SL |
297 | } |
298 | ||
299 | #[derive(Clone, Copy, Debug)] | |
300 | pub struct AssociatedType<'tcx> { | |
301 | pub name: Name, | |
302 | pub ty: Option<Ty<'tcx>>, | |
303 | pub vis: hir::Visibility, | |
304 | pub def_id: DefId, | |
305 | pub container: ImplOrTraitItemContainer, | |
306 | } | |
307 | ||
308 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable)] | |
309 | pub struct ItemVariances { | |
310 | pub types: VecPerParamSpace<Variance>, | |
311 | pub regions: VecPerParamSpace<Variance>, | |
312 | } | |
313 | ||
314 | #[derive(Clone, PartialEq, RustcDecodable, RustcEncodable, Copy)] | |
315 | pub enum Variance { | |
316 | Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type | |
317 | Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell | |
318 | Contravariant, // T<A> <: T<B> iff B <: A -- e.g., function param type | |
319 | Bivariant, // T<A> <: T<B> -- e.g., unused type parameter | |
320 | } | |
321 | ||
322 | #[derive(Clone, Copy, Debug)] | |
323 | pub struct MethodCallee<'tcx> { | |
324 | /// Impl method ID, for inherent methods, or trait method ID, otherwise. | |
325 | pub def_id: DefId, | |
326 | pub ty: Ty<'tcx>, | |
327 | pub substs: &'tcx subst::Substs<'tcx> | |
328 | } | |
329 | ||
330 | /// With method calls, we store some extra information in | |
331 | /// side tables (i.e method_map). We use | |
332 | /// MethodCall as a key to index into these tables instead of | |
333 | /// just directly using the expression's NodeId. The reason | |
334 | /// for this being that we may apply adjustments (coercions) | |
335 | /// with the resulting expression also needing to use the | |
336 | /// side tables. The problem with this is that we don't | |
337 | /// assign a separate NodeId to this new expression | |
338 | /// and so it would clash with the base expression if both | |
339 | /// needed to add to the side tables. Thus to disambiguate | |
340 | /// we also keep track of whether there's an adjustment in | |
341 | /// our key. | |
342 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] | |
343 | pub struct MethodCall { | |
344 | pub expr_id: NodeId, | |
345 | pub autoderef: u32 | |
346 | } | |
347 | ||
348 | impl MethodCall { | |
349 | pub fn expr(id: NodeId) -> MethodCall { | |
350 | MethodCall { | |
351 | expr_id: id, | |
352 | autoderef: 0 | |
353 | } | |
354 | } | |
355 | ||
356 | pub fn autoderef(expr_id: NodeId, autoderef: u32) -> MethodCall { | |
357 | MethodCall { | |
358 | expr_id: expr_id, | |
359 | autoderef: 1 + autoderef | |
360 | } | |
361 | } | |
362 | } | |
363 | ||
364 | // maps from an expression id that corresponds to a method call to the details | |
365 | // of the method to be invoked | |
366 | pub type MethodMap<'tcx> = FnvHashMap<MethodCall, MethodCallee<'tcx>>; | |
367 | ||
368 | // Contains information needed to resolve types and (in the future) look up | |
369 | // the types of AST nodes. | |
370 | #[derive(Copy, Clone, PartialEq, Eq, Hash)] | |
371 | pub struct CReaderCacheKey { | |
372 | pub cnum: CrateNum, | |
373 | pub pos: usize, | |
e9174d1e SL |
374 | } |
375 | ||
376 | /// A restriction that certain types must be the same size. The use of | |
377 | /// `transmute` gives rise to these restrictions. These generally | |
378 | /// cannot be checked until trans; therefore, each call to `transmute` | |
379 | /// will push one or more such restriction into the | |
380 | /// `transmute_restrictions` vector during `intrinsicck`. They are | |
381 | /// then checked during `trans` by the fn `check_intrinsics`. | |
382 | #[derive(Copy, Clone)] | |
383 | pub struct TransmuteRestriction<'tcx> { | |
384 | /// The span whence the restriction comes. | |
385 | pub span: Span, | |
386 | ||
387 | /// The type being transmuted from. | |
388 | pub original_from: Ty<'tcx>, | |
389 | ||
390 | /// The type being transmuted to. | |
391 | pub original_to: Ty<'tcx>, | |
392 | ||
393 | /// The type being transmuted from, with all type parameters | |
394 | /// substituted for an arbitrary representative. Not to be shown | |
395 | /// to the end user. | |
396 | pub substituted_from: Ty<'tcx>, | |
397 | ||
398 | /// The type being transmuted to, with all type parameters | |
399 | /// substituted for an arbitrary representative. Not to be shown | |
400 | /// to the end user. | |
401 | pub substituted_to: Ty<'tcx>, | |
402 | ||
403 | /// NodeId of the transmute intrinsic. | |
404 | pub id: NodeId, | |
405 | } | |
406 | ||
407 | /// Describes the fragment-state associated with a NodeId. | |
408 | /// | |
409 | /// Currently only unfragmented paths have entries in the table, | |
410 | /// but longer-term this enum is expected to expand to also | |
411 | /// include data for fragmented paths. | |
412 | #[derive(Copy, Clone, Debug)] | |
413 | pub enum FragmentInfo { | |
414 | Moved { var: NodeId, move_expr: NodeId }, | |
415 | Assigned { var: NodeId, assign_expr: NodeId, assignee_id: NodeId }, | |
416 | } | |
417 | ||
418 | // Flags that we track on types. These flags are propagated upwards | |
419 | // through the type during type construction, so that we can quickly | |
420 | // check whether the type has various kinds of types in it without | |
421 | // recursing over the type itself. | |
422 | bitflags! { | |
423 | flags TypeFlags: u32 { | |
424 | const HAS_PARAMS = 1 << 0, | |
425 | const HAS_SELF = 1 << 1, | |
426 | const HAS_TY_INFER = 1 << 2, | |
427 | const HAS_RE_INFER = 1 << 3, | |
428 | const HAS_RE_EARLY_BOUND = 1 << 4, | |
429 | const HAS_FREE_REGIONS = 1 << 5, | |
430 | const HAS_TY_ERR = 1 << 6, | |
431 | const HAS_PROJECTION = 1 << 7, | |
432 | const HAS_TY_CLOSURE = 1 << 8, | |
433 | ||
434 | // true if there are "names" of types and regions and so forth | |
435 | // that are local to a particular fn | |
436 | const HAS_LOCAL_NAMES = 1 << 9, | |
437 | ||
438 | const NEEDS_SUBST = TypeFlags::HAS_PARAMS.bits | | |
439 | TypeFlags::HAS_SELF.bits | | |
440 | TypeFlags::HAS_RE_EARLY_BOUND.bits, | |
441 | ||
442 | // Flags representing the nominal content of a type, | |
443 | // computed by FlagsComputation. If you add a new nominal | |
444 | // flag, it should be added here too. | |
445 | const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits | | |
446 | TypeFlags::HAS_SELF.bits | | |
447 | TypeFlags::HAS_TY_INFER.bits | | |
448 | TypeFlags::HAS_RE_INFER.bits | | |
449 | TypeFlags::HAS_RE_EARLY_BOUND.bits | | |
450 | TypeFlags::HAS_FREE_REGIONS.bits | | |
451 | TypeFlags::HAS_TY_ERR.bits | | |
452 | TypeFlags::HAS_PROJECTION.bits | | |
453 | TypeFlags::HAS_TY_CLOSURE.bits | | |
454 | TypeFlags::HAS_LOCAL_NAMES.bits, | |
455 | ||
456 | // Caches for type_is_sized, type_moves_by_default | |
457 | const SIZEDNESS_CACHED = 1 << 16, | |
458 | const IS_SIZED = 1 << 17, | |
459 | const MOVENESS_CACHED = 1 << 18, | |
460 | const MOVES_BY_DEFAULT = 1 << 19, | |
461 | } | |
462 | } | |
463 | ||
464 | pub struct TyS<'tcx> { | |
465 | pub sty: TypeVariants<'tcx>, | |
466 | pub flags: Cell<TypeFlags>, | |
467 | ||
468 | // the maximal depth of any bound regions appearing in this type. | |
469 | region_depth: u32, | |
470 | } | |
471 | ||
472 | impl<'tcx> PartialEq for TyS<'tcx> { | |
473 | #[inline] | |
474 | fn eq(&self, other: &TyS<'tcx>) -> bool { | |
475 | // (self as *const _) == (other as *const _) | |
476 | (self as *const TyS<'tcx>) == (other as *const TyS<'tcx>) | |
477 | } | |
478 | } | |
479 | impl<'tcx> Eq for TyS<'tcx> {} | |
480 | ||
481 | impl<'tcx> Hash for TyS<'tcx> { | |
482 | fn hash<H: Hasher>(&self, s: &mut H) { | |
483 | (self as *const TyS).hash(s) | |
484 | } | |
485 | } | |
486 | ||
487 | pub type Ty<'tcx> = &'tcx TyS<'tcx>; | |
488 | ||
9cc50fc6 SL |
489 | impl<'tcx> Encodable for Ty<'tcx> { |
490 | fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { | |
491 | cstore::tls::with_encoding_context(s, |ecx, rbml_w| { | |
492 | ecx.encode_ty(rbml_w, *self); | |
493 | Ok(()) | |
494 | }) | |
495 | } | |
496 | } | |
497 | ||
498 | impl<'tcx> Decodable for Ty<'tcx> { | |
499 | fn decode<D: Decoder>(d: &mut D) -> Result<Ty<'tcx>, D::Error> { | |
500 | cstore::tls::with_decoding_context(d, |dcx, rbml_r| { | |
501 | Ok(dcx.decode_ty(rbml_r)) | |
502 | }) | |
503 | } | |
504 | } | |
505 | ||
506 | ||
e9174d1e SL |
507 | /// Upvars do not get their own node-id. Instead, we use the pair of |
508 | /// the original var id (that is, the root variable that is referenced | |
509 | /// by the upvar) and the id of the closure expression. | |
510 | #[derive(Clone, Copy, PartialEq, Eq, Hash)] | |
511 | pub struct UpvarId { | |
512 | pub var_id: NodeId, | |
513 | pub closure_expr_id: NodeId, | |
514 | } | |
515 | ||
516 | #[derive(Clone, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable, Copy)] | |
517 | pub enum BorrowKind { | |
518 | /// Data must be immutable and is aliasable. | |
519 | ImmBorrow, | |
520 | ||
521 | /// Data must be immutable but not aliasable. This kind of borrow | |
522 | /// cannot currently be expressed by the user and is used only in | |
523 | /// implicit closure bindings. It is needed when you the closure | |
524 | /// is borrowing or mutating a mutable referent, e.g.: | |
525 | /// | |
526 | /// let x: &mut isize = ...; | |
527 | /// let y = || *x += 5; | |
528 | /// | |
529 | /// If we were to try to translate this closure into a more explicit | |
530 | /// form, we'd encounter an error with the code as written: | |
531 | /// | |
532 | /// struct Env { x: & &mut isize } | |
533 | /// let x: &mut isize = ...; | |
534 | /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn | |
535 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } | |
536 | /// | |
537 | /// This is then illegal because you cannot mutate a `&mut` found | |
538 | /// in an aliasable location. To solve, you'd have to translate with | |
539 | /// an `&mut` borrow: | |
540 | /// | |
541 | /// struct Env { x: & &mut isize } | |
542 | /// let x: &mut isize = ...; | |
543 | /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x | |
544 | /// fn fn_ptr(env: &mut Env) { **env.x += 5; } | |
545 | /// | |
546 | /// Now the assignment to `**env.x` is legal, but creating a | |
547 | /// mutable pointer to `x` is not because `x` is not mutable. We | |
548 | /// could fix this by declaring `x` as `let mut x`. This is ok in | |
549 | /// user code, if awkward, but extra weird for closures, since the | |
550 | /// borrow is hidden. | |
551 | /// | |
552 | /// So we introduce a "unique imm" borrow -- the referent is | |
553 | /// immutable, but not aliasable. This solves the problem. For | |
554 | /// simplicity, we don't give users the way to express this | |
555 | /// borrow, it's just used when translating closures. | |
556 | UniqueImmBorrow, | |
557 | ||
558 | /// Data is mutable and not aliasable. | |
559 | MutBorrow | |
560 | } | |
561 | ||
562 | /// Information describing the capture of an upvar. This is computed | |
563 | /// during `typeck`, specifically by `regionck`. | |
564 | #[derive(PartialEq, Clone, Debug, Copy)] | |
565 | pub enum UpvarCapture { | |
566 | /// Upvar is captured by value. This is always true when the | |
567 | /// closure is labeled `move`, but can also be true in other cases | |
568 | /// depending on inference. | |
569 | ByValue, | |
570 | ||
571 | /// Upvar is captured by reference. | |
572 | ByRef(UpvarBorrow), | |
573 | } | |
574 | ||
575 | #[derive(PartialEq, Clone, Copy)] | |
576 | pub struct UpvarBorrow { | |
577 | /// The kind of borrow: by-ref upvars have access to shared | |
578 | /// immutable borrows, which are not part of the normal language | |
579 | /// syntax. | |
580 | pub kind: BorrowKind, | |
581 | ||
582 | /// Region of the resulting reference. | |
583 | pub region: ty::Region, | |
584 | } | |
585 | ||
586 | pub type UpvarCaptureMap = FnvHashMap<UpvarId, UpvarCapture>; | |
587 | ||
588 | #[derive(Copy, Clone)] | |
589 | pub struct ClosureUpvar<'tcx> { | |
7453a54e | 590 | pub def: Def, |
e9174d1e SL |
591 | pub span: Span, |
592 | pub ty: Ty<'tcx>, | |
593 | } | |
594 | ||
595 | #[derive(Clone, Copy, PartialEq)] | |
596 | pub enum IntVarValue { | |
b039eaaf SL |
597 | IntType(ast::IntTy), |
598 | UintType(ast::UintTy), | |
e9174d1e SL |
599 | } |
600 | ||
601 | /// Default region to use for the bound of objects that are | |
602 | /// supplied as the value for this type parameter. This is derived | |
603 | /// from `T:'a` annotations appearing in the type definition. If | |
604 | /// this is `None`, then the default is inherited from the | |
605 | /// surrounding context. See RFC #599 for details. | |
606 | #[derive(Copy, Clone)] | |
607 | pub enum ObjectLifetimeDefault { | |
608 | /// Require an explicit annotation. Occurs when multiple | |
609 | /// `T:'a` constraints are found. | |
610 | Ambiguous, | |
611 | ||
612 | /// Use the base default, typically 'static, but in a fn body it is a fresh variable | |
613 | BaseDefault, | |
614 | ||
615 | /// Use the given region as the default. | |
616 | Specific(Region), | |
617 | } | |
618 | ||
619 | #[derive(Clone)] | |
620 | pub struct TypeParameterDef<'tcx> { | |
621 | pub name: Name, | |
622 | pub def_id: DefId, | |
623 | pub space: subst::ParamSpace, | |
624 | pub index: u32, | |
625 | pub default_def_id: DefId, // for use in error reporing about defaults | |
626 | pub default: Option<Ty<'tcx>>, | |
627 | pub object_lifetime_default: ObjectLifetimeDefault, | |
628 | } | |
629 | ||
630 | #[derive(Clone)] | |
631 | pub struct RegionParameterDef { | |
632 | pub name: Name, | |
633 | pub def_id: DefId, | |
634 | pub space: subst::ParamSpace, | |
635 | pub index: u32, | |
636 | pub bounds: Vec<ty::Region>, | |
637 | } | |
638 | ||
639 | impl RegionParameterDef { | |
640 | pub fn to_early_bound_region(&self) -> ty::Region { | |
641 | ty::ReEarlyBound(ty::EarlyBoundRegion { | |
e9174d1e SL |
642 | space: self.space, |
643 | index: self.index, | |
644 | name: self.name, | |
645 | }) | |
646 | } | |
647 | pub fn to_bound_region(&self) -> ty::BoundRegion { | |
648 | ty::BoundRegion::BrNamed(self.def_id, self.name) | |
649 | } | |
650 | } | |
651 | ||
652 | /// Information about the formal type/lifetime parameters associated | |
653 | /// with an item or method. Analogous to hir::Generics. | |
654 | #[derive(Clone, Debug)] | |
655 | pub struct Generics<'tcx> { | |
656 | pub types: VecPerParamSpace<TypeParameterDef<'tcx>>, | |
657 | pub regions: VecPerParamSpace<RegionParameterDef>, | |
658 | } | |
659 | ||
660 | impl<'tcx> Generics<'tcx> { | |
661 | pub fn empty() -> Generics<'tcx> { | |
662 | Generics { | |
663 | types: VecPerParamSpace::empty(), | |
664 | regions: VecPerParamSpace::empty(), | |
665 | } | |
666 | } | |
667 | ||
668 | pub fn is_empty(&self) -> bool { | |
669 | self.types.is_empty() && self.regions.is_empty() | |
670 | } | |
671 | ||
672 | pub fn has_type_params(&self, space: subst::ParamSpace) -> bool { | |
673 | !self.types.is_empty_in(space) | |
674 | } | |
675 | ||
676 | pub fn has_region_params(&self, space: subst::ParamSpace) -> bool { | |
677 | !self.regions.is_empty_in(space) | |
678 | } | |
679 | } | |
680 | ||
681 | /// Bounds on generics. | |
682 | #[derive(Clone)] | |
683 | pub struct GenericPredicates<'tcx> { | |
684 | pub predicates: VecPerParamSpace<Predicate<'tcx>>, | |
685 | } | |
686 | ||
687 | impl<'tcx> GenericPredicates<'tcx> { | |
688 | pub fn empty() -> GenericPredicates<'tcx> { | |
689 | GenericPredicates { | |
690 | predicates: VecPerParamSpace::empty(), | |
691 | } | |
692 | } | |
693 | ||
694 | pub fn instantiate(&self, tcx: &ctxt<'tcx>, substs: &Substs<'tcx>) | |
695 | -> InstantiatedPredicates<'tcx> { | |
696 | InstantiatedPredicates { | |
697 | predicates: self.predicates.subst(tcx, substs), | |
698 | } | |
699 | } | |
700 | ||
701 | pub fn instantiate_supertrait(&self, | |
702 | tcx: &ctxt<'tcx>, | |
703 | poly_trait_ref: &ty::PolyTraitRef<'tcx>) | |
704 | -> InstantiatedPredicates<'tcx> | |
705 | { | |
706 | InstantiatedPredicates { | |
707 | predicates: self.predicates.map(|pred| pred.subst_supertrait(tcx, poly_trait_ref)) | |
708 | } | |
709 | } | |
710 | } | |
711 | ||
712 | #[derive(Clone, PartialEq, Eq, Hash)] | |
713 | pub enum Predicate<'tcx> { | |
714 | /// Corresponds to `where Foo : Bar<A,B,C>`. `Foo` here would be | |
715 | /// the `Self` type of the trait reference and `A`, `B`, and `C` | |
716 | /// would be the parameters in the `TypeSpace`. | |
717 | Trait(PolyTraitPredicate<'tcx>), | |
718 | ||
719 | /// where `T1 == T2`. | |
720 | Equate(PolyEquatePredicate<'tcx>), | |
721 | ||
722 | /// where 'a : 'b | |
723 | RegionOutlives(PolyRegionOutlivesPredicate), | |
724 | ||
725 | /// where T : 'a | |
726 | TypeOutlives(PolyTypeOutlivesPredicate<'tcx>), | |
727 | ||
728 | /// where <T as TraitRef>::Name == X, approximately. | |
729 | /// See `ProjectionPredicate` struct for details. | |
730 | Projection(PolyProjectionPredicate<'tcx>), | |
731 | ||
732 | /// no syntax: T WF | |
733 | WellFormed(Ty<'tcx>), | |
734 | ||
735 | /// trait must be object-safe | |
736 | ObjectSafe(DefId), | |
737 | } | |
738 | ||
739 | impl<'tcx> Predicate<'tcx> { | |
740 | /// Performs a substitution suitable for going from a | |
741 | /// poly-trait-ref to supertraits that must hold if that | |
742 | /// poly-trait-ref holds. This is slightly different from a normal | |
743 | /// substitution in terms of what happens with bound regions. See | |
744 | /// lengthy comment below for details. | |
745 | pub fn subst_supertrait(&self, | |
746 | tcx: &ctxt<'tcx>, | |
747 | trait_ref: &ty::PolyTraitRef<'tcx>) | |
748 | -> ty::Predicate<'tcx> | |
749 | { | |
750 | // The interaction between HRTB and supertraits is not entirely | |
751 | // obvious. Let me walk you (and myself) through an example. | |
752 | // | |
753 | // Let's start with an easy case. Consider two traits: | |
754 | // | |
755 | // trait Foo<'a> : Bar<'a,'a> { } | |
756 | // trait Bar<'b,'c> { } | |
757 | // | |
758 | // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then | |
759 | // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we | |
760 | // knew that `Foo<'x>` (for any 'x) then we also know that | |
761 | // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from | |
762 | // normal substitution. | |
763 | // | |
764 | // In terms of why this is sound, the idea is that whenever there | |
765 | // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>` | |
766 | // holds. So if there is an impl of `T:Foo<'a>` that applies to | |
767 | // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all | |
768 | // `'a`. | |
769 | // | |
770 | // Another example to be careful of is this: | |
771 | // | |
772 | // trait Foo1<'a> : for<'b> Bar1<'a,'b> { } | |
773 | // trait Bar1<'b,'c> { } | |
774 | // | |
775 | // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know? | |
776 | // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The | |
777 | // reason is similar to the previous example: any impl of | |
778 | // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So | |
779 | // basically we would want to collapse the bound lifetimes from | |
780 | // the input (`trait_ref`) and the supertraits. | |
781 | // | |
782 | // To achieve this in practice is fairly straightforward. Let's | |
783 | // consider the more complicated scenario: | |
784 | // | |
785 | // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x` | |
786 | // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`, | |
787 | // where both `'x` and `'b` would have a DB index of 1. | |
788 | // The substitution from the input trait-ref is therefore going to be | |
789 | // `'a => 'x` (where `'x` has a DB index of 1). | |
790 | // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an | |
791 | // early-bound parameter and `'b' is a late-bound parameter with a | |
792 | // DB index of 1. | |
793 | // - If we replace `'a` with `'x` from the input, it too will have | |
794 | // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>` | |
795 | // just as we wanted. | |
796 | // | |
797 | // There is only one catch. If we just apply the substitution `'a | |
798 | // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will | |
799 | // adjust the DB index because we substituting into a binder (it | |
800 | // tries to be so smart...) resulting in `for<'x> for<'b> | |
801 | // Bar1<'x,'b>` (we have no syntax for this, so use your | |
802 | // imagination). Basically the 'x will have DB index of 2 and 'b | |
803 | // will have DB index of 1. Not quite what we want. So we apply | |
804 | // the substitution to the *contents* of the trait reference, | |
805 | // rather than the trait reference itself (put another way, the | |
806 | // substitution code expects equal binding levels in the values | |
807 | // from the substitution and the value being substituted into, and | |
808 | // this trick achieves that). | |
809 | ||
810 | let substs = &trait_ref.0.substs; | |
811 | match *self { | |
812 | Predicate::Trait(ty::Binder(ref data)) => | |
813 | Predicate::Trait(ty::Binder(data.subst(tcx, substs))), | |
814 | Predicate::Equate(ty::Binder(ref data)) => | |
815 | Predicate::Equate(ty::Binder(data.subst(tcx, substs))), | |
816 | Predicate::RegionOutlives(ty::Binder(ref data)) => | |
817 | Predicate::RegionOutlives(ty::Binder(data.subst(tcx, substs))), | |
818 | Predicate::TypeOutlives(ty::Binder(ref data)) => | |
819 | Predicate::TypeOutlives(ty::Binder(data.subst(tcx, substs))), | |
820 | Predicate::Projection(ty::Binder(ref data)) => | |
821 | Predicate::Projection(ty::Binder(data.subst(tcx, substs))), | |
822 | Predicate::WellFormed(data) => | |
823 | Predicate::WellFormed(data.subst(tcx, substs)), | |
824 | Predicate::ObjectSafe(trait_def_id) => | |
825 | Predicate::ObjectSafe(trait_def_id), | |
826 | } | |
827 | } | |
828 | } | |
829 | ||
830 | #[derive(Clone, PartialEq, Eq, Hash)] | |
831 | pub struct TraitPredicate<'tcx> { | |
832 | pub trait_ref: TraitRef<'tcx> | |
833 | } | |
834 | pub type PolyTraitPredicate<'tcx> = ty::Binder<TraitPredicate<'tcx>>; | |
835 | ||
836 | impl<'tcx> TraitPredicate<'tcx> { | |
837 | pub fn def_id(&self) -> DefId { | |
838 | self.trait_ref.def_id | |
839 | } | |
840 | ||
7453a54e SL |
841 | /// Creates the dep-node for selecting/evaluating this trait reference. |
842 | fn dep_node(&self) -> DepNode { | |
843 | DepNode::TraitSelect(self.def_id()) | |
844 | } | |
845 | ||
e9174d1e SL |
846 | pub fn input_types(&self) -> &[Ty<'tcx>] { |
847 | self.trait_ref.substs.types.as_slice() | |
848 | } | |
849 | ||
850 | pub fn self_ty(&self) -> Ty<'tcx> { | |
851 | self.trait_ref.self_ty() | |
852 | } | |
853 | } | |
854 | ||
855 | impl<'tcx> PolyTraitPredicate<'tcx> { | |
856 | pub fn def_id(&self) -> DefId { | |
7453a54e | 857 | // ok to skip binder since trait def-id does not care about regions |
e9174d1e SL |
858 | self.0.def_id() |
859 | } | |
7453a54e SL |
860 | |
861 | pub fn dep_node(&self) -> DepNode { | |
862 | // ok to skip binder since depnode does not care about regions | |
863 | self.0.dep_node() | |
864 | } | |
e9174d1e SL |
865 | } |
866 | ||
867 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | |
868 | pub struct EquatePredicate<'tcx>(pub Ty<'tcx>, pub Ty<'tcx>); // `0 == 1` | |
869 | pub type PolyEquatePredicate<'tcx> = ty::Binder<EquatePredicate<'tcx>>; | |
870 | ||
871 | #[derive(Clone, PartialEq, Eq, Hash, Debug)] | |
872 | pub struct OutlivesPredicate<A,B>(pub A, pub B); // `A : B` | |
873 | pub type PolyOutlivesPredicate<A,B> = ty::Binder<OutlivesPredicate<A,B>>; | |
874 | pub type PolyRegionOutlivesPredicate = PolyOutlivesPredicate<ty::Region, ty::Region>; | |
875 | pub type PolyTypeOutlivesPredicate<'tcx> = PolyOutlivesPredicate<Ty<'tcx>, ty::Region>; | |
876 | ||
877 | /// This kind of predicate has no *direct* correspondent in the | |
878 | /// syntax, but it roughly corresponds to the syntactic forms: | |
879 | /// | |
880 | /// 1. `T : TraitRef<..., Item=Type>` | |
881 | /// 2. `<T as TraitRef<...>>::Item == Type` (NYI) | |
882 | /// | |
883 | /// In particular, form #1 is "desugared" to the combination of a | |
884 | /// normal trait predicate (`T : TraitRef<...>`) and one of these | |
885 | /// predicates. Form #2 is a broader form in that it also permits | |
886 | /// equality between arbitrary types. Processing an instance of Form | |
887 | /// #2 eventually yields one of these `ProjectionPredicate` | |
888 | /// instances to normalize the LHS. | |
889 | #[derive(Clone, PartialEq, Eq, Hash)] | |
890 | pub struct ProjectionPredicate<'tcx> { | |
891 | pub projection_ty: ProjectionTy<'tcx>, | |
892 | pub ty: Ty<'tcx>, | |
893 | } | |
894 | ||
895 | pub type PolyProjectionPredicate<'tcx> = Binder<ProjectionPredicate<'tcx>>; | |
896 | ||
897 | impl<'tcx> PolyProjectionPredicate<'tcx> { | |
898 | pub fn item_name(&self) -> Name { | |
899 | self.0.projection_ty.item_name // safe to skip the binder to access a name | |
900 | } | |
901 | ||
902 | pub fn sort_key(&self) -> (DefId, Name) { | |
903 | self.0.projection_ty.sort_key() | |
904 | } | |
905 | } | |
906 | ||
907 | pub trait ToPolyTraitRef<'tcx> { | |
908 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx>; | |
909 | } | |
910 | ||
911 | impl<'tcx> ToPolyTraitRef<'tcx> for TraitRef<'tcx> { | |
912 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
913 | assert!(!self.has_escaping_regions()); | |
914 | ty::Binder(self.clone()) | |
915 | } | |
916 | } | |
917 | ||
918 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyTraitPredicate<'tcx> { | |
919 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
7453a54e | 920 | self.map_bound_ref(|trait_pred| trait_pred.trait_ref) |
e9174d1e SL |
921 | } |
922 | } | |
923 | ||
924 | impl<'tcx> ToPolyTraitRef<'tcx> for PolyProjectionPredicate<'tcx> { | |
925 | fn to_poly_trait_ref(&self) -> PolyTraitRef<'tcx> { | |
926 | // Note: unlike with TraitRef::to_poly_trait_ref(), | |
927 | // self.0.trait_ref is permitted to have escaping regions. | |
928 | // This is because here `self` has a `Binder` and so does our | |
929 | // return value, so we are preserving the number of binding | |
930 | // levels. | |
7453a54e | 931 | ty::Binder(self.0.projection_ty.trait_ref) |
e9174d1e SL |
932 | } |
933 | } | |
934 | ||
935 | pub trait ToPredicate<'tcx> { | |
936 | fn to_predicate(&self) -> Predicate<'tcx>; | |
937 | } | |
938 | ||
939 | impl<'tcx> ToPredicate<'tcx> for TraitRef<'tcx> { | |
940 | fn to_predicate(&self) -> Predicate<'tcx> { | |
941 | // we're about to add a binder, so let's check that we don't | |
942 | // accidentally capture anything, or else that might be some | |
943 | // weird debruijn accounting. | |
944 | assert!(!self.has_escaping_regions()); | |
945 | ||
946 | ty::Predicate::Trait(ty::Binder(ty::TraitPredicate { | |
947 | trait_ref: self.clone() | |
948 | })) | |
949 | } | |
950 | } | |
951 | ||
952 | impl<'tcx> ToPredicate<'tcx> for PolyTraitRef<'tcx> { | |
953 | fn to_predicate(&self) -> Predicate<'tcx> { | |
954 | ty::Predicate::Trait(self.to_poly_trait_predicate()) | |
955 | } | |
956 | } | |
957 | ||
958 | impl<'tcx> ToPredicate<'tcx> for PolyEquatePredicate<'tcx> { | |
959 | fn to_predicate(&self) -> Predicate<'tcx> { | |
960 | Predicate::Equate(self.clone()) | |
961 | } | |
962 | } | |
963 | ||
964 | impl<'tcx> ToPredicate<'tcx> for PolyRegionOutlivesPredicate { | |
965 | fn to_predicate(&self) -> Predicate<'tcx> { | |
966 | Predicate::RegionOutlives(self.clone()) | |
967 | } | |
968 | } | |
969 | ||
970 | impl<'tcx> ToPredicate<'tcx> for PolyTypeOutlivesPredicate<'tcx> { | |
971 | fn to_predicate(&self) -> Predicate<'tcx> { | |
972 | Predicate::TypeOutlives(self.clone()) | |
973 | } | |
974 | } | |
975 | ||
976 | impl<'tcx> ToPredicate<'tcx> for PolyProjectionPredicate<'tcx> { | |
977 | fn to_predicate(&self) -> Predicate<'tcx> { | |
978 | Predicate::Projection(self.clone()) | |
979 | } | |
980 | } | |
981 | ||
982 | impl<'tcx> Predicate<'tcx> { | |
983 | /// Iterates over the types in this predicate. Note that in all | |
984 | /// cases this is skipping over a binder, so late-bound regions | |
985 | /// with depth 0 are bound by the predicate. | |
986 | pub fn walk_tys(&self) -> IntoIter<Ty<'tcx>> { | |
987 | let vec: Vec<_> = match *self { | |
988 | ty::Predicate::Trait(ref data) => { | |
989 | data.0.trait_ref.substs.types.as_slice().to_vec() | |
990 | } | |
991 | ty::Predicate::Equate(ty::Binder(ref data)) => { | |
992 | vec![data.0, data.1] | |
993 | } | |
994 | ty::Predicate::TypeOutlives(ty::Binder(ref data)) => { | |
995 | vec![data.0] | |
996 | } | |
997 | ty::Predicate::RegionOutlives(..) => { | |
998 | vec![] | |
999 | } | |
1000 | ty::Predicate::Projection(ref data) => { | |
1001 | let trait_inputs = data.0.projection_ty.trait_ref.substs.types.as_slice(); | |
1002 | trait_inputs.iter() | |
1003 | .cloned() | |
1004 | .chain(Some(data.0.ty)) | |
1005 | .collect() | |
1006 | } | |
1007 | ty::Predicate::WellFormed(data) => { | |
1008 | vec![data] | |
1009 | } | |
1010 | ty::Predicate::ObjectSafe(_trait_def_id) => { | |
1011 | vec![] | |
1012 | } | |
1013 | }; | |
1014 | ||
1015 | // The only reason to collect into a vector here is that I was | |
1016 | // too lazy to make the full (somewhat complicated) iterator | |
1017 | // type that would be needed here. But I wanted this fn to | |
1018 | // return an iterator conceptually, rather than a `Vec`, so as | |
1019 | // to be closer to `Ty::walk`. | |
1020 | vec.into_iter() | |
1021 | } | |
1022 | ||
1023 | pub fn to_opt_poly_trait_ref(&self) -> Option<PolyTraitRef<'tcx>> { | |
1024 | match *self { | |
1025 | Predicate::Trait(ref t) => { | |
1026 | Some(t.to_poly_trait_ref()) | |
1027 | } | |
1028 | Predicate::Projection(..) | | |
1029 | Predicate::Equate(..) | | |
1030 | Predicate::RegionOutlives(..) | | |
1031 | Predicate::WellFormed(..) | | |
1032 | Predicate::ObjectSafe(..) | | |
1033 | Predicate::TypeOutlives(..) => { | |
1034 | None | |
1035 | } | |
1036 | } | |
1037 | } | |
1038 | } | |
1039 | ||
1040 | /// Represents the bounds declared on a particular set of type | |
1041 | /// parameters. Should eventually be generalized into a flag list of | |
1042 | /// where clauses. You can obtain a `InstantiatedPredicates` list from a | |
1043 | /// `GenericPredicates` by using the `instantiate` method. Note that this method | |
1044 | /// reflects an important semantic invariant of `InstantiatedPredicates`: while | |
1045 | /// the `GenericPredicates` are expressed in terms of the bound type | |
1046 | /// parameters of the impl/trait/whatever, an `InstantiatedPredicates` instance | |
1047 | /// represented a set of bounds for some particular instantiation, | |
1048 | /// meaning that the generic parameters have been substituted with | |
1049 | /// their values. | |
1050 | /// | |
1051 | /// Example: | |
1052 | /// | |
1053 | /// struct Foo<T,U:Bar<T>> { ... } | |
1054 | /// | |
1055 | /// Here, the `GenericPredicates` for `Foo` would contain a list of bounds like | |
1056 | /// `[[], [U:Bar<T>]]`. Now if there were some particular reference | |
1057 | /// like `Foo<isize,usize>`, then the `InstantiatedPredicates` would be `[[], | |
1058 | /// [usize:Bar<isize>]]`. | |
1059 | #[derive(Clone)] | |
1060 | pub struct InstantiatedPredicates<'tcx> { | |
1061 | pub predicates: VecPerParamSpace<Predicate<'tcx>>, | |
1062 | } | |
1063 | ||
1064 | impl<'tcx> InstantiatedPredicates<'tcx> { | |
1065 | pub fn empty() -> InstantiatedPredicates<'tcx> { | |
1066 | InstantiatedPredicates { predicates: VecPerParamSpace::empty() } | |
1067 | } | |
1068 | ||
1069 | pub fn is_empty(&self) -> bool { | |
1070 | self.predicates.is_empty() | |
1071 | } | |
1072 | } | |
1073 | ||
1074 | impl<'tcx> TraitRef<'tcx> { | |
1075 | pub fn new(def_id: DefId, substs: &'tcx Substs<'tcx>) -> TraitRef<'tcx> { | |
1076 | TraitRef { def_id: def_id, substs: substs } | |
1077 | } | |
1078 | ||
1079 | pub fn self_ty(&self) -> Ty<'tcx> { | |
1080 | self.substs.self_ty().unwrap() | |
1081 | } | |
1082 | ||
1083 | pub fn input_types(&self) -> &[Ty<'tcx>] { | |
1084 | // Select only the "input types" from a trait-reference. For | |
1085 | // now this is all the types that appear in the | |
1086 | // trait-reference, but it should eventually exclude | |
1087 | // associated types. | |
1088 | self.substs.types.as_slice() | |
1089 | } | |
1090 | } | |
1091 | ||
1092 | /// When type checking, we use the `ParameterEnvironment` to track | |
1093 | /// details about the type/lifetime parameters that are in scope. | |
1094 | /// It primarily stores the bounds information. | |
1095 | /// | |
1096 | /// Note: This information might seem to be redundant with the data in | |
1097 | /// `tcx.ty_param_defs`, but it is not. That table contains the | |
1098 | /// parameter definitions from an "outside" perspective, but this | |
1099 | /// struct will contain the bounds for a parameter as seen from inside | |
1100 | /// the function body. Currently the only real distinction is that | |
1101 | /// bound lifetime parameters are replaced with free ones, but in the | |
1102 | /// future I hope to refine the representation of types so as to make | |
1103 | /// more distinctions clearer. | |
1104 | #[derive(Clone)] | |
1105 | pub struct ParameterEnvironment<'a, 'tcx:'a> { | |
1106 | pub tcx: &'a ctxt<'tcx>, | |
1107 | ||
1108 | /// See `construct_free_substs` for details. | |
1109 | pub free_substs: Substs<'tcx>, | |
1110 | ||
1111 | /// Each type parameter has an implicit region bound that | |
1112 | /// indicates it must outlive at least the function body (the user | |
1113 | /// may specify stronger requirements). This field indicates the | |
1114 | /// region of the callee. | |
1115 | pub implicit_region_bound: ty::Region, | |
1116 | ||
1117 | /// Obligations that the caller must satisfy. This is basically | |
1118 | /// the set of bounds on the in-scope type parameters, translated | |
1119 | /// into Obligations, and elaborated and normalized. | |
1120 | pub caller_bounds: Vec<ty::Predicate<'tcx>>, | |
1121 | ||
1122 | /// Caches the results of trait selection. This cache is used | |
1123 | /// for things that have to do with the parameters in scope. | |
1124 | pub selection_cache: traits::SelectionCache<'tcx>, | |
1125 | ||
92a42be0 SL |
1126 | /// Caches the results of trait evaluation. |
1127 | pub evaluation_cache: traits::EvaluationCache<'tcx>, | |
1128 | ||
e9174d1e SL |
1129 | /// Scope that is attached to free regions for this scope. This |
1130 | /// is usually the id of the fn body, but for more abstract scopes | |
1131 | /// like structs we often use the node-id of the struct. | |
1132 | /// | |
1133 | /// FIXME(#3696). It would be nice to refactor so that free | |
1134 | /// regions don't have this implicit scope and instead introduce | |
1135 | /// relationships in the environment. | |
9cc50fc6 | 1136 | pub free_id_outlive: CodeExtent, |
e9174d1e SL |
1137 | } |
1138 | ||
1139 | impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> { | |
1140 | pub fn with_caller_bounds(&self, | |
1141 | caller_bounds: Vec<ty::Predicate<'tcx>>) | |
1142 | -> ParameterEnvironment<'a,'tcx> | |
1143 | { | |
1144 | ParameterEnvironment { | |
1145 | tcx: self.tcx, | |
1146 | free_substs: self.free_substs.clone(), | |
1147 | implicit_region_bound: self.implicit_region_bound, | |
1148 | caller_bounds: caller_bounds, | |
1149 | selection_cache: traits::SelectionCache::new(), | |
92a42be0 | 1150 | evaluation_cache: traits::EvaluationCache::new(), |
9cc50fc6 | 1151 | free_id_outlive: self.free_id_outlive, |
e9174d1e SL |
1152 | } |
1153 | } | |
1154 | ||
1155 | pub fn for_item(cx: &'a ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx> { | |
1156 | match cx.map.find(id) { | |
1157 | Some(ast_map::NodeImplItem(ref impl_item)) => { | |
1158 | match impl_item.node { | |
92a42be0 | 1159 | hir::ImplItemKind::Type(_) => { |
e9174d1e SL |
1160 | // associated types don't have their own entry (for some reason), |
1161 | // so for now just grab environment for the impl | |
1162 | let impl_id = cx.map.get_parent(id); | |
b039eaaf | 1163 | let impl_def_id = cx.map.local_def_id(impl_id); |
e9174d1e SL |
1164 | let scheme = cx.lookup_item_type(impl_def_id); |
1165 | let predicates = cx.lookup_predicates(impl_def_id); | |
1166 | cx.construct_parameter_environment(impl_item.span, | |
1167 | &scheme.generics, | |
1168 | &predicates, | |
9cc50fc6 | 1169 | cx.region_maps.item_extent(id)) |
e9174d1e | 1170 | } |
92a42be0 | 1171 | hir::ImplItemKind::Const(_, _) => { |
b039eaaf | 1172 | let def_id = cx.map.local_def_id(id); |
e9174d1e SL |
1173 | let scheme = cx.lookup_item_type(def_id); |
1174 | let predicates = cx.lookup_predicates(def_id); | |
1175 | cx.construct_parameter_environment(impl_item.span, | |
1176 | &scheme.generics, | |
1177 | &predicates, | |
9cc50fc6 | 1178 | cx.region_maps.item_extent(id)) |
e9174d1e | 1179 | } |
92a42be0 | 1180 | hir::ImplItemKind::Method(_, ref body) => { |
b039eaaf | 1181 | let method_def_id = cx.map.local_def_id(id); |
e9174d1e SL |
1182 | match cx.impl_or_trait_item(method_def_id) { |
1183 | MethodTraitItem(ref method_ty) => { | |
1184 | let method_generics = &method_ty.generics; | |
1185 | let method_bounds = &method_ty.predicates; | |
1186 | cx.construct_parameter_environment( | |
1187 | impl_item.span, | |
1188 | method_generics, | |
1189 | method_bounds, | |
9cc50fc6 | 1190 | cx.region_maps.call_site_extent(id, body.id)) |
e9174d1e SL |
1191 | } |
1192 | _ => { | |
1193 | cx.sess | |
1194 | .bug("ParameterEnvironment::for_item(): \ | |
1195 | got non-method item from impl method?!") | |
1196 | } | |
1197 | } | |
1198 | } | |
1199 | } | |
1200 | } | |
1201 | Some(ast_map::NodeTraitItem(trait_item)) => { | |
1202 | match trait_item.node { | |
1203 | hir::TypeTraitItem(..) => { | |
1204 | // associated types don't have their own entry (for some reason), | |
1205 | // so for now just grab environment for the trait | |
1206 | let trait_id = cx.map.get_parent(id); | |
b039eaaf | 1207 | let trait_def_id = cx.map.local_def_id(trait_id); |
e9174d1e SL |
1208 | let trait_def = cx.lookup_trait_def(trait_def_id); |
1209 | let predicates = cx.lookup_predicates(trait_def_id); | |
1210 | cx.construct_parameter_environment(trait_item.span, | |
1211 | &trait_def.generics, | |
1212 | &predicates, | |
9cc50fc6 | 1213 | cx.region_maps.item_extent(id)) |
e9174d1e SL |
1214 | } |
1215 | hir::ConstTraitItem(..) => { | |
b039eaaf | 1216 | let def_id = cx.map.local_def_id(id); |
e9174d1e SL |
1217 | let scheme = cx.lookup_item_type(def_id); |
1218 | let predicates = cx.lookup_predicates(def_id); | |
1219 | cx.construct_parameter_environment(trait_item.span, | |
1220 | &scheme.generics, | |
1221 | &predicates, | |
9cc50fc6 | 1222 | cx.region_maps.item_extent(id)) |
e9174d1e SL |
1223 | } |
1224 | hir::MethodTraitItem(_, ref body) => { | |
9cc50fc6 SL |
1225 | // Use call-site for extent (unless this is a |
1226 | // trait method with no default; then fallback | |
1227 | // to the method id). | |
b039eaaf | 1228 | let method_def_id = cx.map.local_def_id(id); |
e9174d1e SL |
1229 | match cx.impl_or_trait_item(method_def_id) { |
1230 | MethodTraitItem(ref method_ty) => { | |
1231 | let method_generics = &method_ty.generics; | |
1232 | let method_bounds = &method_ty.predicates; | |
9cc50fc6 SL |
1233 | let extent = if let Some(ref body) = *body { |
1234 | // default impl: use call_site extent as free_id_outlive bound. | |
1235 | cx.region_maps.call_site_extent(id, body.id) | |
1236 | } else { | |
1237 | // no default impl: use item extent as free_id_outlive bound. | |
1238 | cx.region_maps.item_extent(id) | |
1239 | }; | |
e9174d1e SL |
1240 | cx.construct_parameter_environment( |
1241 | trait_item.span, | |
1242 | method_generics, | |
1243 | method_bounds, | |
9cc50fc6 | 1244 | extent) |
e9174d1e SL |
1245 | } |
1246 | _ => { | |
1247 | cx.sess | |
1248 | .bug("ParameterEnvironment::for_item(): \ | |
1249 | got non-method item from provided \ | |
1250 | method?!") | |
1251 | } | |
1252 | } | |
1253 | } | |
1254 | } | |
1255 | } | |
1256 | Some(ast_map::NodeItem(item)) => { | |
1257 | match item.node { | |
1258 | hir::ItemFn(_, _, _, _, _, ref body) => { | |
1259 | // We assume this is a function. | |
b039eaaf | 1260 | let fn_def_id = cx.map.local_def_id(id); |
e9174d1e SL |
1261 | let fn_scheme = cx.lookup_item_type(fn_def_id); |
1262 | let fn_predicates = cx.lookup_predicates(fn_def_id); | |
1263 | ||
1264 | cx.construct_parameter_environment(item.span, | |
1265 | &fn_scheme.generics, | |
1266 | &fn_predicates, | |
9cc50fc6 SL |
1267 | cx.region_maps.call_site_extent(id, |
1268 | body.id)) | |
e9174d1e SL |
1269 | } |
1270 | hir::ItemEnum(..) | | |
1271 | hir::ItemStruct(..) | | |
1272 | hir::ItemImpl(..) | | |
1273 | hir::ItemConst(..) | | |
1274 | hir::ItemStatic(..) => { | |
b039eaaf | 1275 | let def_id = cx.map.local_def_id(id); |
e9174d1e SL |
1276 | let scheme = cx.lookup_item_type(def_id); |
1277 | let predicates = cx.lookup_predicates(def_id); | |
1278 | cx.construct_parameter_environment(item.span, | |
1279 | &scheme.generics, | |
1280 | &predicates, | |
9cc50fc6 | 1281 | cx.region_maps.item_extent(id)) |
e9174d1e SL |
1282 | } |
1283 | hir::ItemTrait(..) => { | |
b039eaaf | 1284 | let def_id = cx.map.local_def_id(id); |
e9174d1e SL |
1285 | let trait_def = cx.lookup_trait_def(def_id); |
1286 | let predicates = cx.lookup_predicates(def_id); | |
1287 | cx.construct_parameter_environment(item.span, | |
1288 | &trait_def.generics, | |
1289 | &predicates, | |
9cc50fc6 | 1290 | cx.region_maps.item_extent(id)) |
e9174d1e SL |
1291 | } |
1292 | _ => { | |
1293 | cx.sess.span_bug(item.span, | |
1294 | "ParameterEnvironment::from_item(): | |
1295 | can't create a parameter \ | |
1296 | environment for this kind of item") | |
1297 | } | |
1298 | } | |
1299 | } | |
1300 | Some(ast_map::NodeExpr(..)) => { | |
1301 | // This is a convenience to allow closures to work. | |
1302 | ParameterEnvironment::for_item(cx, cx.map.get_parent(id)) | |
1303 | } | |
1304 | _ => { | |
1305 | cx.sess.bug(&format!("ParameterEnvironment::from_item(): \ | |
1306 | `{}` is not an item", | |
1307 | cx.map.node_to_string(id))) | |
1308 | } | |
1309 | } | |
1310 | } | |
1311 | } | |
1312 | ||
1313 | /// A "type scheme", in ML terminology, is a type combined with some | |
1314 | /// set of generic types that the type is, well, generic over. In Rust | |
1315 | /// terms, it is the "type" of a fn item or struct -- this type will | |
1316 | /// include various generic parameters that must be substituted when | |
1317 | /// the item/struct is referenced. That is called converting the type | |
1318 | /// scheme to a monotype. | |
1319 | /// | |
1320 | /// - `generics`: the set of type parameters and their bounds | |
1321 | /// - `ty`: the base types, which may reference the parameters defined | |
1322 | /// in `generics` | |
1323 | /// | |
1324 | /// Note that TypeSchemes are also sometimes called "polytypes" (and | |
1325 | /// in fact this struct used to carry that name, so you may find some | |
1326 | /// stray references in a comment or something). We try to reserve the | |
1327 | /// "poly" prefix to refer to higher-ranked things, as in | |
1328 | /// `PolyTraitRef`. | |
1329 | /// | |
1330 | /// Note that each item also comes with predicates, see | |
1331 | /// `lookup_predicates`. | |
1332 | #[derive(Clone, Debug)] | |
1333 | pub struct TypeScheme<'tcx> { | |
1334 | pub generics: Generics<'tcx>, | |
1335 | pub ty: Ty<'tcx>, | |
1336 | } | |
1337 | ||
e9174d1e SL |
1338 | bitflags! { |
1339 | flags AdtFlags: u32 { | |
1340 | const NO_ADT_FLAGS = 0, | |
1341 | const IS_ENUM = 1 << 0, | |
1342 | const IS_DTORCK = 1 << 1, // is this a dtorck type? | |
1343 | const IS_DTORCK_VALID = 1 << 2, | |
1344 | const IS_PHANTOM_DATA = 1 << 3, | |
1345 | const IS_SIMD = 1 << 4, | |
1346 | const IS_FUNDAMENTAL = 1 << 5, | |
1347 | const IS_NO_DROP_FLAG = 1 << 6, | |
1348 | } | |
1349 | } | |
1350 | ||
1351 | pub type AdtDef<'tcx> = &'tcx AdtDefData<'tcx, 'static>; | |
1352 | pub type VariantDef<'tcx> = &'tcx VariantDefData<'tcx, 'static>; | |
1353 | pub type FieldDef<'tcx> = &'tcx FieldDefData<'tcx, 'static>; | |
1354 | ||
1355 | // See comment on AdtDefData for explanation | |
1356 | pub type AdtDefMaster<'tcx> = &'tcx AdtDefData<'tcx, 'tcx>; | |
1357 | pub type VariantDefMaster<'tcx> = &'tcx VariantDefData<'tcx, 'tcx>; | |
1358 | pub type FieldDefMaster<'tcx> = &'tcx FieldDefData<'tcx, 'tcx>; | |
1359 | ||
1360 | pub struct VariantDefData<'tcx, 'container: 'tcx> { | |
b039eaaf SL |
1361 | /// The variant's DefId. If this is a tuple-like struct, |
1362 | /// this is the DefId of the struct's ctor. | |
e9174d1e SL |
1363 | pub did: DefId, |
1364 | pub name: Name, // struct's name if this is a struct | |
1365 | pub disr_val: Disr, | |
b039eaaf | 1366 | pub fields: Vec<FieldDefData<'tcx, 'container>>, |
9cc50fc6 | 1367 | pub kind: VariantKind, |
e9174d1e SL |
1368 | } |
1369 | ||
1370 | pub struct FieldDefData<'tcx, 'container: 'tcx> { | |
1371 | /// The field's DefId. NOTE: the fields of tuple-like enum variants | |
1372 | /// are not real items, and don't have entries in tcache etc. | |
1373 | pub did: DefId, | |
1374 | /// special_idents::unnamed_field.name | |
1375 | /// if this is a tuple-like field | |
1376 | pub name: Name, | |
1377 | pub vis: hir::Visibility, | |
1378 | /// TyIVar is used here to allow for variance (see the doc at | |
1379 | /// AdtDefData). | |
9cc50fc6 SL |
1380 | /// |
1381 | /// Note: direct accesses to `ty` must also add dep edges. | |
e9174d1e SL |
1382 | ty: ivar::TyIVar<'tcx, 'container> |
1383 | } | |
1384 | ||
1385 | /// The definition of an abstract data type - a struct or enum. | |
1386 | /// | |
1387 | /// These are all interned (by intern_adt_def) into the adt_defs | |
1388 | /// table. | |
1389 | /// | |
1390 | /// Because of the possibility of nested tcx-s, this type | |
1391 | /// needs 2 lifetimes: the traditional variant lifetime ('tcx) | |
1392 | /// bounding the lifetime of the inner types is of course necessary. | |
1393 | /// However, it is not sufficient - types from a child tcx must | |
1394 | /// not be leaked into the master tcx by being stored in an AdtDefData. | |
1395 | /// | |
1396 | /// The 'container lifetime ensures that by outliving the container | |
1397 | /// tcx and preventing shorter-lived types from being inserted. When | |
1398 | /// write access is not needed, the 'container lifetime can be | |
1399 | /// erased to 'static, which can be done by the AdtDef wrapper. | |
1400 | pub struct AdtDefData<'tcx, 'container: 'tcx> { | |
1401 | pub did: DefId, | |
1402 | pub variants: Vec<VariantDefData<'tcx, 'container>>, | |
1403 | destructor: Cell<Option<DefId>>, | |
1404 | flags: Cell<AdtFlags>, | |
1405 | } | |
1406 | ||
1407 | impl<'tcx, 'container> PartialEq for AdtDefData<'tcx, 'container> { | |
1408 | // AdtDefData are always interned and this is part of TyS equality | |
1409 | #[inline] | |
1410 | fn eq(&self, other: &Self) -> bool { self as *const _ == other as *const _ } | |
1411 | } | |
1412 | ||
1413 | impl<'tcx, 'container> Eq for AdtDefData<'tcx, 'container> {} | |
1414 | ||
1415 | impl<'tcx, 'container> Hash for AdtDefData<'tcx, 'container> { | |
1416 | #[inline] | |
1417 | fn hash<H: Hasher>(&self, s: &mut H) { | |
1418 | (self as *const AdtDefData).hash(s) | |
1419 | } | |
1420 | } | |
1421 | ||
9cc50fc6 SL |
1422 | impl<'tcx> Encodable for AdtDef<'tcx> { |
1423 | fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> { | |
1424 | self.did.encode(s) | |
1425 | } | |
1426 | } | |
1427 | ||
1428 | impl<'tcx> Decodable for AdtDef<'tcx> { | |
1429 | fn decode<D: Decoder>(d: &mut D) -> Result<AdtDef<'tcx>, D::Error> { | |
1430 | let def_id: DefId = try!{ Decodable::decode(d) }; | |
1431 | ||
1432 | cstore::tls::with_decoding_context(d, |dcx, _| { | |
1433 | let def_id = dcx.translate_def_id(def_id); | |
1434 | Ok(dcx.tcx().lookup_adt_def(def_id)) | |
1435 | }) | |
1436 | } | |
1437 | } | |
1438 | ||
e9174d1e SL |
1439 | |
1440 | #[derive(Copy, Clone, Debug, Eq, PartialEq)] | |
1441 | pub enum AdtKind { Struct, Enum } | |
1442 | ||
7453a54e | 1443 | #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, RustcEncodable, RustcDecodable)] |
b039eaaf | 1444 | pub enum VariantKind { Struct, Tuple, Unit } |
e9174d1e | 1445 | |
7453a54e SL |
1446 | impl VariantKind { |
1447 | pub fn from_variant_data(vdata: &hir::VariantData) -> Self { | |
1448 | match *vdata { | |
1449 | hir::VariantData::Struct(..) => VariantKind::Struct, | |
1450 | hir::VariantData::Tuple(..) => VariantKind::Tuple, | |
1451 | hir::VariantData::Unit(..) => VariantKind::Unit, | |
1452 | } | |
1453 | } | |
1454 | } | |
1455 | ||
e9174d1e SL |
1456 | impl<'tcx, 'container> AdtDefData<'tcx, 'container> { |
1457 | fn new(tcx: &ctxt<'tcx>, | |
1458 | did: DefId, | |
1459 | kind: AdtKind, | |
1460 | variants: Vec<VariantDefData<'tcx, 'container>>) -> Self { | |
1461 | let mut flags = AdtFlags::NO_ADT_FLAGS; | |
1462 | let attrs = tcx.get_attrs(did); | |
1463 | if attr::contains_name(&attrs, "fundamental") { | |
1464 | flags = flags | AdtFlags::IS_FUNDAMENTAL; | |
1465 | } | |
1466 | if attr::contains_name(&attrs, "unsafe_no_drop_flag") { | |
1467 | flags = flags | AdtFlags::IS_NO_DROP_FLAG; | |
1468 | } | |
1469 | if tcx.lookup_simd(did) { | |
1470 | flags = flags | AdtFlags::IS_SIMD; | |
1471 | } | |
1472 | if Some(did) == tcx.lang_items.phantom_data() { | |
1473 | flags = flags | AdtFlags::IS_PHANTOM_DATA; | |
1474 | } | |
1475 | if let AdtKind::Enum = kind { | |
1476 | flags = flags | AdtFlags::IS_ENUM; | |
1477 | } | |
1478 | AdtDefData { | |
1479 | did: did, | |
1480 | variants: variants, | |
1481 | flags: Cell::new(flags), | |
1482 | destructor: Cell::new(None) | |
1483 | } | |
1484 | } | |
1485 | ||
1486 | fn calculate_dtorck(&'tcx self, tcx: &ctxt<'tcx>) { | |
1487 | if tcx.is_adt_dtorck(self) { | |
1488 | self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK); | |
1489 | } | |
1490 | self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK_VALID) | |
1491 | } | |
1492 | ||
1493 | /// Returns the kind of the ADT - Struct or Enum. | |
1494 | #[inline] | |
1495 | pub fn adt_kind(&self) -> AdtKind { | |
1496 | if self.flags.get().intersects(AdtFlags::IS_ENUM) { | |
1497 | AdtKind::Enum | |
1498 | } else { | |
1499 | AdtKind::Struct | |
1500 | } | |
1501 | } | |
1502 | ||
1503 | /// Returns whether this is a dtorck type. If this returns | |
1504 | /// true, this type being safe for destruction requires it to be | |
1505 | /// alive; Otherwise, only the contents are required to be. | |
1506 | #[inline] | |
1507 | pub fn is_dtorck(&'tcx self, tcx: &ctxt<'tcx>) -> bool { | |
1508 | if !self.flags.get().intersects(AdtFlags::IS_DTORCK_VALID) { | |
1509 | self.calculate_dtorck(tcx) | |
1510 | } | |
1511 | self.flags.get().intersects(AdtFlags::IS_DTORCK) | |
1512 | } | |
1513 | ||
1514 | /// Returns whether this type is #[fundamental] for the purposes | |
1515 | /// of coherence checking. | |
1516 | #[inline] | |
1517 | pub fn is_fundamental(&self) -> bool { | |
1518 | self.flags.get().intersects(AdtFlags::IS_FUNDAMENTAL) | |
1519 | } | |
1520 | ||
1521 | #[inline] | |
1522 | pub fn is_simd(&self) -> bool { | |
1523 | self.flags.get().intersects(AdtFlags::IS_SIMD) | |
1524 | } | |
1525 | ||
1526 | /// Returns true if this is PhantomData<T>. | |
1527 | #[inline] | |
1528 | pub fn is_phantom_data(&self) -> bool { | |
1529 | self.flags.get().intersects(AdtFlags::IS_PHANTOM_DATA) | |
1530 | } | |
1531 | ||
1532 | /// Returns whether this type has a destructor. | |
1533 | pub fn has_dtor(&self) -> bool { | |
1534 | match self.dtor_kind() { | |
1535 | NoDtor => false, | |
1536 | TraitDtor(..) => true | |
1537 | } | |
1538 | } | |
1539 | ||
1540 | /// Asserts this is a struct and returns the struct's unique | |
1541 | /// variant. | |
1542 | pub fn struct_variant(&self) -> &VariantDefData<'tcx, 'container> { | |
1543 | assert!(self.adt_kind() == AdtKind::Struct); | |
1544 | &self.variants[0] | |
1545 | } | |
1546 | ||
1547 | #[inline] | |
1548 | pub fn type_scheme(&self, tcx: &ctxt<'tcx>) -> TypeScheme<'tcx> { | |
1549 | tcx.lookup_item_type(self.did) | |
1550 | } | |
1551 | ||
1552 | #[inline] | |
1553 | pub fn predicates(&self, tcx: &ctxt<'tcx>) -> GenericPredicates<'tcx> { | |
1554 | tcx.lookup_predicates(self.did) | |
1555 | } | |
1556 | ||
1557 | /// Returns an iterator over all fields contained | |
1558 | /// by this ADT. | |
1559 | #[inline] | |
1560 | pub fn all_fields(&self) -> | |
1561 | iter::FlatMap< | |
1562 | slice::Iter<VariantDefData<'tcx, 'container>>, | |
1563 | slice::Iter<FieldDefData<'tcx, 'container>>, | |
1564 | for<'s> fn(&'s VariantDefData<'tcx, 'container>) | |
1565 | -> slice::Iter<'s, FieldDefData<'tcx, 'container>> | |
1566 | > { | |
1567 | self.variants.iter().flat_map(VariantDefData::fields_iter) | |
1568 | } | |
1569 | ||
1570 | #[inline] | |
1571 | pub fn is_empty(&self) -> bool { | |
1572 | self.variants.is_empty() | |
1573 | } | |
1574 | ||
1575 | #[inline] | |
1576 | pub fn is_univariant(&self) -> bool { | |
1577 | self.variants.len() == 1 | |
1578 | } | |
1579 | ||
1580 | pub fn is_payloadfree(&self) -> bool { | |
1581 | !self.variants.is_empty() && | |
1582 | self.variants.iter().all(|v| v.fields.is_empty()) | |
1583 | } | |
1584 | ||
1585 | pub fn variant_with_id(&self, vid: DefId) -> &VariantDefData<'tcx, 'container> { | |
1586 | self.variants | |
1587 | .iter() | |
1588 | .find(|v| v.did == vid) | |
1589 | .expect("variant_with_id: unknown variant") | |
1590 | } | |
1591 | ||
1592 | pub fn variant_index_with_id(&self, vid: DefId) -> usize { | |
1593 | self.variants | |
1594 | .iter() | |
1595 | .position(|v| v.did == vid) | |
1596 | .expect("variant_index_with_id: unknown variant") | |
1597 | } | |
1598 | ||
7453a54e | 1599 | pub fn variant_of_def(&self, def: Def) -> &VariantDefData<'tcx, 'container> { |
e9174d1e | 1600 | match def { |
7453a54e SL |
1601 | Def::Variant(_, vid) => self.variant_with_id(vid), |
1602 | Def::Struct(..) | Def::TyAlias(..) => self.struct_variant(), | |
e9174d1e SL |
1603 | _ => panic!("unexpected def {:?} in variant_of_def", def) |
1604 | } | |
1605 | } | |
1606 | ||
1607 | pub fn destructor(&self) -> Option<DefId> { | |
1608 | self.destructor.get() | |
1609 | } | |
1610 | ||
1611 | pub fn set_destructor(&self, dtor: DefId) { | |
1612 | self.destructor.set(Some(dtor)); | |
1613 | } | |
1614 | ||
1615 | pub fn dtor_kind(&self) -> DtorKind { | |
1616 | match self.destructor.get() { | |
1617 | Some(_) => { | |
1618 | TraitDtor(!self.flags.get().intersects(AdtFlags::IS_NO_DROP_FLAG)) | |
1619 | } | |
1620 | None => NoDtor, | |
1621 | } | |
1622 | } | |
1623 | } | |
1624 | ||
1625 | impl<'tcx, 'container> VariantDefData<'tcx, 'container> { | |
1626 | #[inline] | |
1627 | fn fields_iter(&self) -> slice::Iter<FieldDefData<'tcx, 'container>> { | |
1628 | self.fields.iter() | |
1629 | } | |
1630 | ||
1631 | pub fn kind(&self) -> VariantKind { | |
9cc50fc6 | 1632 | self.kind |
e9174d1e SL |
1633 | } |
1634 | ||
1635 | pub fn is_tuple_struct(&self) -> bool { | |
1636 | self.kind() == VariantKind::Tuple | |
1637 | } | |
1638 | ||
1639 | #[inline] | |
1640 | pub fn find_field_named(&self, | |
1641 | name: ast::Name) | |
1642 | -> Option<&FieldDefData<'tcx, 'container>> { | |
1643 | self.fields.iter().find(|f| f.name == name) | |
1644 | } | |
1645 | ||
92a42be0 SL |
1646 | #[inline] |
1647 | pub fn index_of_field_named(&self, | |
1648 | name: ast::Name) | |
1649 | -> Option<usize> { | |
1650 | self.fields.iter().position(|f| f.name == name) | |
1651 | } | |
1652 | ||
e9174d1e SL |
1653 | #[inline] |
1654 | pub fn field_named(&self, name: ast::Name) -> &FieldDefData<'tcx, 'container> { | |
1655 | self.find_field_named(name).unwrap() | |
1656 | } | |
1657 | } | |
1658 | ||
1659 | impl<'tcx, 'container> FieldDefData<'tcx, 'container> { | |
1660 | pub fn new(did: DefId, | |
1661 | name: Name, | |
1662 | vis: hir::Visibility) -> Self { | |
1663 | FieldDefData { | |
1664 | did: did, | |
1665 | name: name, | |
1666 | vis: vis, | |
1667 | ty: ivar::TyIVar::new() | |
1668 | } | |
1669 | } | |
1670 | ||
1671 | pub fn ty(&self, tcx: &ctxt<'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> { | |
1672 | self.unsubst_ty().subst(tcx, subst) | |
1673 | } | |
1674 | ||
1675 | pub fn unsubst_ty(&self) -> Ty<'tcx> { | |
9cc50fc6 | 1676 | self.ty.unwrap(DepNode::FieldTy(self.did)) |
e9174d1e SL |
1677 | } |
1678 | ||
1679 | pub fn fulfill_ty(&self, ty: Ty<'container>) { | |
9cc50fc6 | 1680 | self.ty.fulfill(DepNode::FieldTy(self.did), ty); |
e9174d1e SL |
1681 | } |
1682 | } | |
1683 | ||
1684 | /// Records the substitutions used to translate the polytype for an | |
1685 | /// item into the monotype of an item reference. | |
1686 | #[derive(Clone)] | |
1687 | pub struct ItemSubsts<'tcx> { | |
1688 | pub substs: Substs<'tcx>, | |
1689 | } | |
1690 | ||
1691 | #[derive(Clone, Copy, PartialOrd, Ord, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable)] | |
1692 | pub enum ClosureKind { | |
1693 | // Warning: Ordering is significant here! The ordering is chosen | |
1694 | // because the trait Fn is a subtrait of FnMut and so in turn, and | |
1695 | // hence we order it so that Fn < FnMut < FnOnce. | |
1696 | FnClosureKind, | |
1697 | FnMutClosureKind, | |
1698 | FnOnceClosureKind, | |
1699 | } | |
1700 | ||
1701 | impl ClosureKind { | |
1702 | pub fn trait_did(&self, cx: &ctxt) -> DefId { | |
1703 | let result = match *self { | |
1704 | FnClosureKind => cx.lang_items.require(FnTraitLangItem), | |
1705 | FnMutClosureKind => { | |
1706 | cx.lang_items.require(FnMutTraitLangItem) | |
1707 | } | |
1708 | FnOnceClosureKind => { | |
1709 | cx.lang_items.require(FnOnceTraitLangItem) | |
1710 | } | |
1711 | }; | |
1712 | match result { | |
1713 | Ok(trait_did) => trait_did, | |
1714 | Err(err) => cx.sess.fatal(&err[..]), | |
1715 | } | |
1716 | } | |
1717 | ||
1718 | /// True if this a type that impls this closure kind | |
1719 | /// must also implement `other`. | |
1720 | pub fn extends(self, other: ty::ClosureKind) -> bool { | |
1721 | match (self, other) { | |
1722 | (FnClosureKind, FnClosureKind) => true, | |
1723 | (FnClosureKind, FnMutClosureKind) => true, | |
1724 | (FnClosureKind, FnOnceClosureKind) => true, | |
1725 | (FnMutClosureKind, FnMutClosureKind) => true, | |
1726 | (FnMutClosureKind, FnOnceClosureKind) => true, | |
1727 | (FnOnceClosureKind, FnOnceClosureKind) => true, | |
1728 | _ => false, | |
1729 | } | |
1730 | } | |
1731 | } | |
1732 | ||
1733 | impl<'tcx> TyS<'tcx> { | |
1734 | /// Iterator that walks `self` and any types reachable from | |
1735 | /// `self`, in depth-first order. Note that just walks the types | |
1736 | /// that appear in `self`, it does not descend into the fields of | |
1737 | /// structs or variants. For example: | |
1738 | /// | |
1739 | /// ```notrust | |
1740 | /// isize => { isize } | |
1741 | /// Foo<Bar<isize>> => { Foo<Bar<isize>>, Bar<isize>, isize } | |
1742 | /// [isize] => { [isize], isize } | |
1743 | /// ``` | |
1744 | pub fn walk(&'tcx self) -> TypeWalker<'tcx> { | |
1745 | TypeWalker::new(self) | |
1746 | } | |
1747 | ||
1748 | /// Iterator that walks the immediate children of `self`. Hence | |
1749 | /// `Foo<Bar<i32>, u32>` yields the sequence `[Bar<i32>, u32]` | |
1750 | /// (but not `i32`, like `walk`). | |
1751 | pub fn walk_shallow(&'tcx self) -> IntoIter<Ty<'tcx>> { | |
1752 | walk::walk_shallow(self) | |
1753 | } | |
1754 | ||
1755 | /// Walks `ty` and any types appearing within `ty`, invoking the | |
1756 | /// callback `f` on each type. If the callback returns false, then the | |
1757 | /// children of the current type are ignored. | |
1758 | /// | |
1759 | /// Note: prefer `ty.walk()` where possible. | |
1760 | pub fn maybe_walk<F>(&'tcx self, mut f: F) | |
1761 | where F : FnMut(Ty<'tcx>) -> bool | |
1762 | { | |
1763 | let mut walker = self.walk(); | |
1764 | while let Some(ty) = walker.next() { | |
1765 | if !f(ty) { | |
1766 | walker.skip_current_subtree(); | |
1767 | } | |
1768 | } | |
1769 | } | |
1770 | } | |
1771 | ||
1772 | impl<'tcx> ItemSubsts<'tcx> { | |
1773 | pub fn empty() -> ItemSubsts<'tcx> { | |
1774 | ItemSubsts { substs: Substs::empty() } | |
1775 | } | |
1776 | ||
1777 | pub fn is_noop(&self) -> bool { | |
1778 | self.substs.is_noop() | |
1779 | } | |
1780 | } | |
1781 | ||
1782 | #[derive(Copy, Clone, Debug, PartialEq, Eq)] | |
1783 | pub enum LvaluePreference { | |
1784 | PreferMutLvalue, | |
1785 | NoPreference | |
1786 | } | |
1787 | ||
1788 | impl LvaluePreference { | |
1789 | pub fn from_mutbl(m: hir::Mutability) -> Self { | |
1790 | match m { | |
1791 | hir::MutMutable => PreferMutLvalue, | |
1792 | hir::MutImmutable => NoPreference, | |
1793 | } | |
1794 | } | |
1795 | } | |
1796 | ||
1797 | /// Helper for looking things up in the various maps that are populated during | |
1798 | /// typeck::collect (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of | |
1799 | /// these share the pattern that if the id is local, it should have been loaded | |
1800 | /// into the map by the `typeck::collect` phase. If the def-id is external, | |
1801 | /// then we have to go consult the crate loading code (and cache the result for | |
1802 | /// the future). | |
9cc50fc6 | 1803 | fn lookup_locally_or_in_crate_store<M, F>(descr: &str, |
e9174d1e | 1804 | def_id: DefId, |
9cc50fc6 SL |
1805 | map: &M, |
1806 | load_external: F) | |
1807 | -> M::Value where | |
1808 | M: MemoizationMap<Key=DefId>, | |
1809 | F: FnOnce() -> M::Value, | |
e9174d1e | 1810 | { |
9cc50fc6 SL |
1811 | map.memoize(def_id, || { |
1812 | if def_id.is_local() { | |
1813 | panic!("No def'n found for {:?} in tcx.{}", def_id, descr); | |
1814 | } | |
1815 | load_external() | |
1816 | }) | |
e9174d1e SL |
1817 | } |
1818 | ||
1819 | impl BorrowKind { | |
1820 | pub fn from_mutbl(m: hir::Mutability) -> BorrowKind { | |
1821 | match m { | |
1822 | hir::MutMutable => MutBorrow, | |
1823 | hir::MutImmutable => ImmBorrow, | |
1824 | } | |
1825 | } | |
1826 | ||
1827 | /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow | |
1828 | /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a | |
1829 | /// mutability that is stronger than necessary so that it at least *would permit* the borrow in | |
1830 | /// question. | |
1831 | pub fn to_mutbl_lossy(self) -> hir::Mutability { | |
1832 | match self { | |
1833 | MutBorrow => hir::MutMutable, | |
1834 | ImmBorrow => hir::MutImmutable, | |
1835 | ||
1836 | // We have no type corresponding to a unique imm borrow, so | |
1837 | // use `&mut`. It gives all the capabilities of an `&uniq` | |
1838 | // and hence is a safe "over approximation". | |
1839 | UniqueImmBorrow => hir::MutMutable, | |
1840 | } | |
1841 | } | |
1842 | ||
1843 | pub fn to_user_str(&self) -> &'static str { | |
1844 | match *self { | |
1845 | MutBorrow => "mutable", | |
1846 | ImmBorrow => "immutable", | |
1847 | UniqueImmBorrow => "uniquely immutable", | |
1848 | } | |
1849 | } | |
1850 | } | |
1851 | ||
1852 | impl<'tcx> ctxt<'tcx> { | |
1853 | pub fn node_id_to_type(&self, id: NodeId) -> Ty<'tcx> { | |
1854 | match self.node_id_to_type_opt(id) { | |
1855 | Some(ty) => ty, | |
1856 | None => self.sess.bug( | |
1857 | &format!("node_id_to_type: no type for node `{}`", | |
1858 | self.map.node_to_string(id))) | |
1859 | } | |
1860 | } | |
1861 | ||
1862 | pub fn node_id_to_type_opt(&self, id: NodeId) -> Option<Ty<'tcx>> { | |
1863 | self.tables.borrow().node_types.get(&id).cloned() | |
1864 | } | |
1865 | ||
1866 | pub fn node_id_item_substs(&self, id: NodeId) -> ItemSubsts<'tcx> { | |
1867 | match self.tables.borrow().item_substs.get(&id) { | |
1868 | None => ItemSubsts::empty(), | |
1869 | Some(ts) => ts.clone(), | |
1870 | } | |
1871 | } | |
1872 | ||
1873 | // Returns the type of a pattern as a monotype. Like @expr_ty, this function | |
1874 | // doesn't provide type parameter substitutions. | |
1875 | pub fn pat_ty(&self, pat: &hir::Pat) -> Ty<'tcx> { | |
1876 | self.node_id_to_type(pat.id) | |
1877 | } | |
1878 | pub fn pat_ty_opt(&self, pat: &hir::Pat) -> Option<Ty<'tcx>> { | |
1879 | self.node_id_to_type_opt(pat.id) | |
1880 | } | |
1881 | ||
1882 | // Returns the type of an expression as a monotype. | |
1883 | // | |
1884 | // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in | |
1885 | // some cases, we insert `AutoAdjustment` annotations such as auto-deref or | |
1886 | // auto-ref. The type returned by this function does not consider such | |
1887 | // adjustments. See `expr_ty_adjusted()` instead. | |
1888 | // | |
1889 | // NB (2): This type doesn't provide type parameter substitutions; e.g. if you | |
1890 | // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize" | |
1891 | // instead of "fn(ty) -> T with T = isize". | |
1892 | pub fn expr_ty(&self, expr: &hir::Expr) -> Ty<'tcx> { | |
1893 | self.node_id_to_type(expr.id) | |
1894 | } | |
1895 | ||
1896 | pub fn expr_ty_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> { | |
1897 | self.node_id_to_type_opt(expr.id) | |
1898 | } | |
1899 | ||
1900 | /// Returns the type of `expr`, considering any `AutoAdjustment` | |
1901 | /// entry recorded for that expression. | |
1902 | /// | |
1903 | /// It would almost certainly be better to store the adjusted ty in with | |
1904 | /// the `AutoAdjustment`, but I opted not to do this because it would | |
1905 | /// require serializing and deserializing the type and, although that's not | |
1906 | /// hard to do, I just hate that code so much I didn't want to touch it | |
1907 | /// unless it was to fix it properly, which seemed a distraction from the | |
1908 | /// thread at hand! -nmatsakis | |
1909 | pub fn expr_ty_adjusted(&self, expr: &hir::Expr) -> Ty<'tcx> { | |
1910 | self.expr_ty(expr) | |
1911 | .adjust(self, expr.span, expr.id, | |
1912 | self.tables.borrow().adjustments.get(&expr.id), | |
1913 | |method_call| { | |
1914 | self.tables.borrow().method_map.get(&method_call).map(|method| method.ty) | |
1915 | }) | |
1916 | } | |
1917 | ||
7453a54e SL |
1918 | pub fn expr_ty_adjusted_opt(&self, expr: &hir::Expr) -> Option<Ty<'tcx>> { |
1919 | self.expr_ty_opt(expr).map(|t| t.adjust(self, | |
1920 | expr.span, | |
1921 | expr.id, | |
1922 | self.tables.borrow().adjustments.get(&expr.id), | |
1923 | |method_call| { | |
1924 | self.tables.borrow().method_map.get(&method_call).map(|method| method.ty) | |
1925 | })) | |
1926 | } | |
1927 | ||
e9174d1e SL |
1928 | pub fn expr_span(&self, id: NodeId) -> Span { |
1929 | match self.map.find(id) { | |
1930 | Some(ast_map::NodeExpr(e)) => { | |
1931 | e.span | |
1932 | } | |
1933 | Some(f) => { | |
1934 | self.sess.bug(&format!("Node id {} is not an expr: {:?}", | |
1935 | id, f)); | |
1936 | } | |
1937 | None => { | |
1938 | self.sess.bug(&format!("Node id {} is not present \ | |
1939 | in the node map", id)); | |
1940 | } | |
1941 | } | |
1942 | } | |
1943 | ||
1944 | pub fn local_var_name_str(&self, id: NodeId) -> InternedString { | |
1945 | match self.map.find(id) { | |
1946 | Some(ast_map::NodeLocal(pat)) => { | |
1947 | match pat.node { | |
7453a54e | 1948 | PatKind::Ident(_, ref path1, _) => path1.node.name.as_str(), |
e9174d1e SL |
1949 | _ => { |
1950 | self.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, pat)); | |
1951 | }, | |
1952 | } | |
1953 | }, | |
1954 | r => self.sess.bug(&format!("Variable id {} maps to {:?}, not local", id, r)), | |
1955 | } | |
1956 | } | |
1957 | ||
7453a54e | 1958 | pub fn resolve_expr(&self, expr: &hir::Expr) -> Def { |
e9174d1e SL |
1959 | match self.def_map.borrow().get(&expr.id) { |
1960 | Some(def) => def.full_def(), | |
1961 | None => { | |
1962 | self.sess.span_bug(expr.span, &format!( | |
1963 | "no def-map entry for expr {}", expr.id)); | |
1964 | } | |
1965 | } | |
1966 | } | |
1967 | ||
1968 | pub fn expr_is_lval(&self, expr: &hir::Expr) -> bool { | |
1969 | match expr.node { | |
1970 | hir::ExprPath(..) => { | |
1971 | // We can't use resolve_expr here, as this needs to run on broken | |
1972 | // programs. We don't need to through - associated items are all | |
1973 | // rvalues. | |
1974 | match self.def_map.borrow().get(&expr.id) { | |
1975 | Some(&def::PathResolution { | |
7453a54e | 1976 | base_def: Def::Static(..), .. |
e9174d1e | 1977 | }) | Some(&def::PathResolution { |
7453a54e | 1978 | base_def: Def::Upvar(..), .. |
e9174d1e | 1979 | }) | Some(&def::PathResolution { |
7453a54e | 1980 | base_def: Def::Local(..), .. |
e9174d1e SL |
1981 | }) => { |
1982 | true | |
1983 | } | |
7453a54e | 1984 | Some(&def::PathResolution { base_def: Def::Err, .. })=> true, |
e9174d1e | 1985 | Some(..) => false, |
e9174d1e SL |
1986 | None => self.sess.span_bug(expr.span, &format!( |
1987 | "no def for path {}", expr.id)) | |
1988 | } | |
1989 | } | |
1990 | ||
9cc50fc6 SL |
1991 | hir::ExprType(ref e, _) => { |
1992 | self.expr_is_lval(e) | |
1993 | } | |
1994 | ||
e9174d1e SL |
1995 | hir::ExprUnary(hir::UnDeref, _) | |
1996 | hir::ExprField(..) | | |
1997 | hir::ExprTupField(..) | | |
1998 | hir::ExprIndex(..) => { | |
1999 | true | |
2000 | } | |
2001 | ||
2002 | hir::ExprCall(..) | | |
2003 | hir::ExprMethodCall(..) | | |
2004 | hir::ExprStruct(..) | | |
2005 | hir::ExprRange(..) | | |
2006 | hir::ExprTup(..) | | |
2007 | hir::ExprIf(..) | | |
2008 | hir::ExprMatch(..) | | |
2009 | hir::ExprClosure(..) | | |
2010 | hir::ExprBlock(..) | | |
2011 | hir::ExprRepeat(..) | | |
2012 | hir::ExprVec(..) | | |
2013 | hir::ExprBreak(..) | | |
2014 | hir::ExprAgain(..) | | |
2015 | hir::ExprRet(..) | | |
2016 | hir::ExprWhile(..) | | |
2017 | hir::ExprLoop(..) | | |
2018 | hir::ExprAssign(..) | | |
2019 | hir::ExprInlineAsm(..) | | |
2020 | hir::ExprAssignOp(..) | | |
2021 | hir::ExprLit(_) | | |
2022 | hir::ExprUnary(..) | | |
2023 | hir::ExprBox(..) | | |
2024 | hir::ExprAddrOf(..) | | |
2025 | hir::ExprBinary(..) | | |
2026 | hir::ExprCast(..) => { | |
2027 | false | |
2028 | } | |
e9174d1e SL |
2029 | } |
2030 | } | |
2031 | ||
e9174d1e | 2032 | pub fn provided_trait_methods(&self, id: DefId) -> Vec<Rc<Method<'tcx>>> { |
b039eaaf SL |
2033 | if let Some(id) = self.map.as_local_node_id(id) { |
2034 | if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id).node { | |
e9174d1e SL |
2035 | ms.iter().filter_map(|ti| { |
2036 | if let hir::MethodTraitItem(_, Some(_)) = ti.node { | |
b039eaaf | 2037 | match self.impl_or_trait_item(self.map.local_def_id(ti.id)) { |
e9174d1e SL |
2038 | MethodTraitItem(m) => Some(m), |
2039 | _ => { | |
2040 | self.sess.bug("provided_trait_methods(): \ | |
2041 | non-method item found from \ | |
2042 | looking up provided method?!") | |
2043 | } | |
2044 | } | |
2045 | } else { | |
2046 | None | |
2047 | } | |
2048 | }).collect() | |
2049 | } else { | |
2050 | self.sess.bug(&format!("provided_trait_methods: `{:?}` is not a trait", id)) | |
2051 | } | |
2052 | } else { | |
92a42be0 | 2053 | self.sess.cstore.provided_trait_methods(self, id) |
e9174d1e SL |
2054 | } |
2055 | } | |
2056 | ||
2057 | pub fn associated_consts(&self, id: DefId) -> Vec<Rc<AssociatedConst<'tcx>>> { | |
b039eaaf SL |
2058 | if let Some(id) = self.map.as_local_node_id(id) { |
2059 | match self.map.expect_item(id).node { | |
e9174d1e SL |
2060 | ItemTrait(_, _, _, ref tis) => { |
2061 | tis.iter().filter_map(|ti| { | |
2062 | if let hir::ConstTraitItem(_, _) = ti.node { | |
b039eaaf | 2063 | match self.impl_or_trait_item(self.map.local_def_id(ti.id)) { |
e9174d1e SL |
2064 | ConstTraitItem(ac) => Some(ac), |
2065 | _ => { | |
2066 | self.sess.bug("associated_consts(): \ | |
2067 | non-const item found from \ | |
2068 | looking up a constant?!") | |
2069 | } | |
2070 | } | |
2071 | } else { | |
2072 | None | |
2073 | } | |
2074 | }).collect() | |
2075 | } | |
2076 | ItemImpl(_, _, _, _, _, ref iis) => { | |
2077 | iis.iter().filter_map(|ii| { | |
92a42be0 | 2078 | if let hir::ImplItemKind::Const(_, _) = ii.node { |
b039eaaf | 2079 | match self.impl_or_trait_item(self.map.local_def_id(ii.id)) { |
e9174d1e SL |
2080 | ConstTraitItem(ac) => Some(ac), |
2081 | _ => { | |
2082 | self.sess.bug("associated_consts(): \ | |
2083 | non-const item found from \ | |
2084 | looking up a constant?!") | |
2085 | } | |
2086 | } | |
2087 | } else { | |
2088 | None | |
2089 | } | |
2090 | }).collect() | |
2091 | } | |
2092 | _ => { | |
2093 | self.sess.bug(&format!("associated_consts: `{:?}` is not a trait \ | |
2094 | or impl", id)) | |
2095 | } | |
2096 | } | |
2097 | } else { | |
92a42be0 | 2098 | self.sess.cstore.associated_consts(self, id) |
e9174d1e SL |
2099 | } |
2100 | } | |
2101 | ||
e9174d1e | 2102 | pub fn trait_impl_polarity(&self, id: DefId) -> Option<hir::ImplPolarity> { |
b039eaaf SL |
2103 | if let Some(id) = self.map.as_local_node_id(id) { |
2104 | match self.map.find(id) { | |
e9174d1e SL |
2105 | Some(ast_map::NodeItem(item)) => { |
2106 | match item.node { | |
2107 | hir::ItemImpl(_, polarity, _, _, _, _) => Some(polarity), | |
2108 | _ => None | |
2109 | } | |
2110 | } | |
2111 | _ => None | |
2112 | } | |
2113 | } else { | |
92a42be0 | 2114 | self.sess.cstore.impl_polarity(id) |
e9174d1e SL |
2115 | } |
2116 | } | |
2117 | ||
2118 | pub fn custom_coerce_unsized_kind(&self, did: DefId) -> adjustment::CustomCoerceUnsized { | |
9cc50fc6 | 2119 | self.custom_coerce_unsized_kinds.memoize(did, || { |
e9174d1e | 2120 | let (kind, src) = if did.krate != LOCAL_CRATE { |
92a42be0 | 2121 | (self.sess.cstore.custom_coerce_unsized_kind(did), "external") |
e9174d1e SL |
2122 | } else { |
2123 | (None, "local") | |
2124 | }; | |
2125 | ||
2126 | match kind { | |
2127 | Some(kind) => kind, | |
2128 | None => { | |
2129 | self.sess.bug(&format!("custom_coerce_unsized_kind: \ | |
2130 | {} impl `{}` is missing its kind", | |
2131 | src, self.item_path_str(did))); | |
2132 | } | |
2133 | } | |
2134 | }) | |
2135 | } | |
2136 | ||
2137 | pub fn impl_or_trait_item(&self, id: DefId) -> ImplOrTraitItem<'tcx> { | |
2138 | lookup_locally_or_in_crate_store( | |
2139 | "impl_or_trait_items", id, &self.impl_or_trait_items, | |
92a42be0 | 2140 | || self.sess.cstore.impl_or_trait_item(self, id)) |
e9174d1e SL |
2141 | } |
2142 | ||
2143 | pub fn trait_item_def_ids(&self, id: DefId) -> Rc<Vec<ImplOrTraitItemId>> { | |
2144 | lookup_locally_or_in_crate_store( | |
2145 | "trait_item_def_ids", id, &self.trait_item_def_ids, | |
92a42be0 | 2146 | || Rc::new(self.sess.cstore.trait_item_def_ids(id))) |
e9174d1e SL |
2147 | } |
2148 | ||
2149 | /// Returns the trait-ref corresponding to a given impl, or None if it is | |
2150 | /// an inherent impl. | |
2151 | pub fn impl_trait_ref(&self, id: DefId) -> Option<TraitRef<'tcx>> { | |
2152 | lookup_locally_or_in_crate_store( | |
2153 | "impl_trait_refs", id, &self.impl_trait_refs, | |
92a42be0 | 2154 | || self.sess.cstore.impl_trait_ref(self, id)) |
e9174d1e SL |
2155 | } |
2156 | ||
2157 | /// Returns whether this DefId refers to an impl | |
2158 | pub fn is_impl(&self, id: DefId) -> bool { | |
b039eaaf | 2159 | if let Some(id) = self.map.as_local_node_id(id) { |
e9174d1e | 2160 | if let Some(ast_map::NodeItem( |
b039eaaf | 2161 | &hir::Item { node: hir::ItemImpl(..), .. })) = self.map.find(id) { |
e9174d1e SL |
2162 | true |
2163 | } else { | |
2164 | false | |
2165 | } | |
2166 | } else { | |
92a42be0 | 2167 | self.sess.cstore.is_impl(id) |
e9174d1e SL |
2168 | } |
2169 | } | |
2170 | ||
2171 | pub fn trait_ref_to_def_id(&self, tr: &hir::TraitRef) -> DefId { | |
2172 | self.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id() | |
2173 | } | |
2174 | ||
2175 | pub fn item_path_str(&self, id: DefId) -> String { | |
2176 | self.with_path(id, |path| ast_map::path_to_string(path)) | |
2177 | } | |
2178 | ||
b039eaaf SL |
2179 | pub fn def_path(&self, id: DefId) -> ast_map::DefPath { |
2180 | if id.is_local() { | |
2181 | self.map.def_path(id) | |
2182 | } else { | |
92a42be0 | 2183 | self.sess.cstore.def_path(id) |
b039eaaf SL |
2184 | } |
2185 | } | |
2186 | ||
e9174d1e SL |
2187 | pub fn with_path<T, F>(&self, id: DefId, f: F) -> T where |
2188 | F: FnOnce(ast_map::PathElems) -> T, | |
2189 | { | |
b039eaaf SL |
2190 | if let Some(id) = self.map.as_local_node_id(id) { |
2191 | self.map.with_path(id, f) | |
e9174d1e | 2192 | } else { |
92a42be0 | 2193 | f(self.sess.cstore.item_path(id).iter().cloned().chain(LinkedPath::empty())) |
e9174d1e SL |
2194 | } |
2195 | } | |
2196 | ||
2197 | pub fn item_name(&self, id: DefId) -> ast::Name { | |
b039eaaf SL |
2198 | if let Some(id) = self.map.as_local_node_id(id) { |
2199 | self.map.get_path_elem(id).name() | |
e9174d1e | 2200 | } else { |
92a42be0 | 2201 | self.sess.cstore.item_name(id) |
e9174d1e SL |
2202 | } |
2203 | } | |
2204 | ||
2205 | // Register a given item type | |
2206 | pub fn register_item_type(&self, did: DefId, ty: TypeScheme<'tcx>) { | |
2207 | self.tcache.borrow_mut().insert(did, ty); | |
2208 | } | |
2209 | ||
2210 | // If the given item is in an external crate, looks up its type and adds it to | |
2211 | // the type cache. Returns the type parameters and type. | |
2212 | pub fn lookup_item_type(&self, did: DefId) -> TypeScheme<'tcx> { | |
2213 | lookup_locally_or_in_crate_store( | |
2214 | "tcache", did, &self.tcache, | |
92a42be0 | 2215 | || self.sess.cstore.item_type(self, did)) |
e9174d1e SL |
2216 | } |
2217 | ||
2218 | /// Given the did of a trait, returns its canonical trait ref. | |
2219 | pub fn lookup_trait_def(&self, did: DefId) -> &'tcx TraitDef<'tcx> { | |
2220 | lookup_locally_or_in_crate_store( | |
2221 | "trait_defs", did, &self.trait_defs, | |
92a42be0 | 2222 | || self.alloc_trait_def(self.sess.cstore.trait_def(self, did)) |
e9174d1e SL |
2223 | ) |
2224 | } | |
2225 | ||
2226 | /// Given the did of an ADT, return a master reference to its | |
2227 | /// definition. Unless you are planning on fulfilling the ADT's fields, | |
2228 | /// use lookup_adt_def instead. | |
2229 | pub fn lookup_adt_def_master(&self, did: DefId) -> AdtDefMaster<'tcx> { | |
2230 | lookup_locally_or_in_crate_store( | |
2231 | "adt_defs", did, &self.adt_defs, | |
92a42be0 | 2232 | || self.sess.cstore.adt_def(self, did) |
e9174d1e SL |
2233 | ) |
2234 | } | |
2235 | ||
2236 | /// Given the did of an ADT, return a reference to its definition. | |
2237 | pub fn lookup_adt_def(&self, did: DefId) -> AdtDef<'tcx> { | |
2238 | // when reverse-variance goes away, a transmute::<AdtDefMaster,AdtDef> | |
7453a54e | 2239 | // would be needed here. |
e9174d1e SL |
2240 | self.lookup_adt_def_master(did) |
2241 | } | |
2242 | ||
2243 | /// Given the did of an item, returns its full set of predicates. | |
2244 | pub fn lookup_predicates(&self, did: DefId) -> GenericPredicates<'tcx> { | |
2245 | lookup_locally_or_in_crate_store( | |
2246 | "predicates", did, &self.predicates, | |
92a42be0 | 2247 | || self.sess.cstore.item_predicates(self, did)) |
e9174d1e SL |
2248 | } |
2249 | ||
2250 | /// Given the did of a trait, returns its superpredicates. | |
2251 | pub fn lookup_super_predicates(&self, did: DefId) -> GenericPredicates<'tcx> { | |
2252 | lookup_locally_or_in_crate_store( | |
2253 | "super_predicates", did, &self.super_predicates, | |
92a42be0 | 2254 | || self.sess.cstore.item_super_predicates(self, did)) |
e9174d1e SL |
2255 | } |
2256 | ||
9cc50fc6 SL |
2257 | /// If `type_needs_drop` returns true, then `ty` is definitely |
2258 | /// non-copy and *might* have a destructor attached; if it returns | |
2259 | /// false, then `ty` definitely has no destructor (i.e. no drop glue). | |
2260 | /// | |
2261 | /// (Note that this implies that if `ty` has a destructor attached, | |
2262 | /// then `type_needs_drop` will definitely return `true` for `ty`.) | |
2263 | pub fn type_needs_drop_given_env<'a>(&self, | |
2264 | ty: Ty<'tcx>, | |
2265 | param_env: &ty::ParameterEnvironment<'a,'tcx>) -> bool { | |
2266 | // Issue #22536: We first query type_moves_by_default. It sees a | |
2267 | // normalized version of the type, and therefore will definitely | |
2268 | // know whether the type implements Copy (and thus needs no | |
2269 | // cleanup/drop/zeroing) ... | |
2270 | let implements_copy = !ty.moves_by_default(param_env, DUMMY_SP); | |
2271 | ||
2272 | if implements_copy { return false; } | |
2273 | ||
2274 | // ... (issue #22536 continued) but as an optimization, still use | |
2275 | // prior logic of asking if the `needs_drop` bit is set; we need | |
2276 | // not zero non-Copy types if they have no destructor. | |
2277 | ||
2278 | // FIXME(#22815): Note that calling `ty::type_contents` is a | |
2279 | // conservative heuristic; it may report that `needs_drop` is set | |
2280 | // when actual type does not actually have a destructor associated | |
2281 | // with it. But since `ty` absolutely did not have the `Copy` | |
2282 | // bound attached (see above), it is sound to treat it as having a | |
2283 | // destructor (e.g. zero its memory on move). | |
2284 | ||
2285 | let contents = ty.type_contents(self); | |
2286 | debug!("type_needs_drop ty={:?} contents={:?}", ty, contents); | |
2287 | contents.needs_drop(self) | |
2288 | } | |
2289 | ||
e9174d1e | 2290 | /// Get the attributes of a definition. |
b039eaaf SL |
2291 | pub fn get_attrs(&self, did: DefId) -> Cow<'tcx, [ast::Attribute]> { |
2292 | if let Some(id) = self.map.as_local_node_id(did) { | |
2293 | Cow::Borrowed(self.map.attrs(id)) | |
e9174d1e | 2294 | } else { |
92a42be0 | 2295 | Cow::Owned(self.sess.cstore.item_attrs(did)) |
e9174d1e SL |
2296 | } |
2297 | } | |
2298 | ||
2299 | /// Determine whether an item is annotated with an attribute | |
2300 | pub fn has_attr(&self, did: DefId, attr: &str) -> bool { | |
2301 | self.get_attrs(did).iter().any(|item| item.check_name(attr)) | |
2302 | } | |
2303 | ||
2304 | /// Determine whether an item is annotated with `#[repr(packed)]` | |
2305 | pub fn lookup_packed(&self, did: DefId) -> bool { | |
2306 | self.lookup_repr_hints(did).contains(&attr::ReprPacked) | |
2307 | } | |
2308 | ||
2309 | /// Determine whether an item is annotated with `#[simd]` | |
2310 | pub fn lookup_simd(&self, did: DefId) -> bool { | |
2311 | self.has_attr(did, "simd") | |
2312 | || self.lookup_repr_hints(did).contains(&attr::ReprSimd) | |
2313 | } | |
2314 | ||
e9174d1e SL |
2315 | pub fn item_variances(&self, item_id: DefId) -> Rc<ItemVariances> { |
2316 | lookup_locally_or_in_crate_store( | |
2317 | "item_variance_map", item_id, &self.item_variance_map, | |
92a42be0 | 2318 | || Rc::new(self.sess.cstore.item_variances(item_id))) |
e9174d1e SL |
2319 | } |
2320 | ||
2321 | pub fn trait_has_default_impl(&self, trait_def_id: DefId) -> bool { | |
2322 | self.populate_implementations_for_trait_if_necessary(trait_def_id); | |
2323 | ||
2324 | let def = self.lookup_trait_def(trait_def_id); | |
2325 | def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL) | |
2326 | } | |
2327 | ||
2328 | /// Records a trait-to-implementation mapping. | |
2329 | pub fn record_trait_has_default_impl(&self, trait_def_id: DefId) { | |
2330 | let def = self.lookup_trait_def(trait_def_id); | |
2331 | def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL) | |
2332 | } | |
2333 | ||
2334 | /// Load primitive inherent implementations if necessary | |
2335 | pub fn populate_implementations_for_primitive_if_necessary(&self, | |
2336 | primitive_def_id: DefId) { | |
2337 | if primitive_def_id.is_local() { | |
2338 | return | |
2339 | } | |
2340 | ||
9cc50fc6 SL |
2341 | // The primitive is not local, hence we are reading this out |
2342 | // of metadata. | |
2343 | let _ignore = self.dep_graph.in_ignore(); | |
2344 | ||
e9174d1e SL |
2345 | if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) { |
2346 | return | |
2347 | } | |
2348 | ||
2349 | debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}", | |
2350 | primitive_def_id); | |
2351 | ||
92a42be0 | 2352 | let impl_items = self.sess.cstore.impl_items(primitive_def_id); |
e9174d1e SL |
2353 | |
2354 | // Store the implementation info. | |
2355 | self.impl_items.borrow_mut().insert(primitive_def_id, impl_items); | |
2356 | self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id); | |
2357 | } | |
2358 | ||
2359 | /// Populates the type context with all the inherent implementations for | |
2360 | /// the given type if necessary. | |
2361 | pub fn populate_inherent_implementations_for_type_if_necessary(&self, | |
2362 | type_id: DefId) { | |
2363 | if type_id.is_local() { | |
2364 | return | |
2365 | } | |
2366 | ||
9cc50fc6 SL |
2367 | // The type is not local, hence we are reading this out of |
2368 | // metadata and don't need to track edges. | |
2369 | let _ignore = self.dep_graph.in_ignore(); | |
2370 | ||
e9174d1e SL |
2371 | if self.populated_external_types.borrow().contains(&type_id) { |
2372 | return | |
2373 | } | |
2374 | ||
2375 | debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}", | |
2376 | type_id); | |
2377 | ||
92a42be0 SL |
2378 | let inherent_impls = self.sess.cstore.inherent_implementations_for_type(type_id); |
2379 | for &impl_def_id in &inherent_impls { | |
e9174d1e | 2380 | // Store the implementation info. |
92a42be0 | 2381 | let impl_items = self.sess.cstore.impl_items(impl_def_id); |
e9174d1e | 2382 | self.impl_items.borrow_mut().insert(impl_def_id, impl_items); |
92a42be0 | 2383 | } |
e9174d1e SL |
2384 | |
2385 | self.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls)); | |
2386 | self.populated_external_types.borrow_mut().insert(type_id); | |
2387 | } | |
2388 | ||
2389 | /// Populates the type context with all the implementations for the given | |
2390 | /// trait if necessary. | |
2391 | pub fn populate_implementations_for_trait_if_necessary(&self, trait_id: DefId) { | |
2392 | if trait_id.is_local() { | |
2393 | return | |
2394 | } | |
2395 | ||
9cc50fc6 SL |
2396 | // The type is not local, hence we are reading this out of |
2397 | // metadata and don't need to track edges. | |
2398 | let _ignore = self.dep_graph.in_ignore(); | |
2399 | ||
e9174d1e SL |
2400 | let def = self.lookup_trait_def(trait_id); |
2401 | if def.flags.get().intersects(TraitFlags::IMPLS_VALID) { | |
2402 | return; | |
2403 | } | |
2404 | ||
2405 | debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def); | |
2406 | ||
92a42be0 | 2407 | if self.sess.cstore.is_defaulted_trait(trait_id) { |
e9174d1e SL |
2408 | self.record_trait_has_default_impl(trait_id); |
2409 | } | |
2410 | ||
92a42be0 SL |
2411 | for impl_def_id in self.sess.cstore.implementations_of_trait(trait_id) { |
2412 | let impl_items = self.sess.cstore.impl_items(impl_def_id); | |
e9174d1e SL |
2413 | let trait_ref = self.impl_trait_ref(impl_def_id).unwrap(); |
2414 | // Record the trait->implementation mapping. | |
2415 | def.record_impl(self, impl_def_id, trait_ref); | |
2416 | ||
2417 | // For any methods that use a default implementation, add them to | |
2418 | // the map. This is a bit unfortunate. | |
2419 | for impl_item_def_id in &impl_items { | |
2420 | let method_def_id = impl_item_def_id.def_id(); | |
b039eaaf SL |
2421 | // load impl items eagerly for convenience |
2422 | // FIXME: we may want to load these lazily | |
2423 | self.impl_or_trait_item(method_def_id); | |
e9174d1e SL |
2424 | } |
2425 | ||
2426 | // Store the implementation info. | |
2427 | self.impl_items.borrow_mut().insert(impl_def_id, impl_items); | |
92a42be0 | 2428 | } |
e9174d1e SL |
2429 | |
2430 | def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID); | |
2431 | } | |
2432 | ||
b039eaaf SL |
2433 | pub fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind { |
2434 | Tables::closure_kind(&self.tables, self, def_id) | |
2435 | } | |
2436 | ||
2437 | pub fn closure_type(&self, | |
2438 | def_id: DefId, | |
2439 | substs: &ClosureSubsts<'tcx>) | |
2440 | -> ty::ClosureTy<'tcx> | |
2441 | { | |
2442 | Tables::closure_type(&self.tables, self, def_id, substs) | |
2443 | } | |
2444 | ||
e9174d1e SL |
2445 | /// Given the def_id of an impl, return the def_id of the trait it implements. |
2446 | /// If it implements no trait, return `None`. | |
2447 | pub fn trait_id_of_impl(&self, def_id: DefId) -> Option<DefId> { | |
2448 | self.impl_trait_ref(def_id).map(|tr| tr.def_id) | |
2449 | } | |
2450 | ||
2451 | /// If the given def ID describes a method belonging to an impl, return the | |
2452 | /// ID of the impl that the method belongs to. Otherwise, return `None`. | |
2453 | pub fn impl_of_method(&self, def_id: DefId) -> Option<DefId> { | |
2454 | if def_id.krate != LOCAL_CRATE { | |
92a42be0 | 2455 | return match self.sess.cstore.impl_or_trait_item(self, def_id).container() { |
e9174d1e SL |
2456 | TraitContainer(_) => None, |
2457 | ImplContainer(def_id) => Some(def_id), | |
2458 | }; | |
2459 | } | |
2460 | match self.impl_or_trait_items.borrow().get(&def_id).cloned() { | |
2461 | Some(trait_item) => { | |
2462 | match trait_item.container() { | |
2463 | TraitContainer(_) => None, | |
2464 | ImplContainer(def_id) => Some(def_id), | |
2465 | } | |
2466 | } | |
2467 | None => None | |
2468 | } | |
2469 | } | |
2470 | ||
2471 | /// If the given def ID describes an item belonging to a trait (either a | |
2472 | /// default method or an implementation of a trait method), return the ID of | |
2473 | /// the trait that the method belongs to. Otherwise, return `None`. | |
2474 | pub fn trait_of_item(&self, def_id: DefId) -> Option<DefId> { | |
2475 | if def_id.krate != LOCAL_CRATE { | |
92a42be0 | 2476 | return self.sess.cstore.trait_of_item(self, def_id); |
e9174d1e SL |
2477 | } |
2478 | match self.impl_or_trait_items.borrow().get(&def_id).cloned() { | |
2479 | Some(impl_or_trait_item) => { | |
2480 | match impl_or_trait_item.container() { | |
2481 | TraitContainer(def_id) => Some(def_id), | |
2482 | ImplContainer(def_id) => self.trait_id_of_impl(def_id), | |
2483 | } | |
2484 | } | |
2485 | None => None | |
2486 | } | |
2487 | } | |
2488 | ||
2489 | /// If the given def ID describes an item belonging to a trait, (either a | |
2490 | /// default method or an implementation of a trait method), return the ID of | |
2491 | /// the method inside trait definition (this means that if the given def ID | |
2492 | /// is already that of the original trait method, then the return value is | |
2493 | /// the same). | |
2494 | /// Otherwise, return `None`. | |
2495 | pub fn trait_item_of_item(&self, def_id: DefId) -> Option<ImplOrTraitItemId> { | |
2496 | let impl_item = match self.impl_or_trait_items.borrow().get(&def_id) { | |
2497 | Some(m) => m.clone(), | |
2498 | None => return None, | |
2499 | }; | |
2500 | let name = impl_item.name(); | |
2501 | match self.trait_of_item(def_id) { | |
2502 | Some(trait_did) => { | |
2503 | self.trait_items(trait_did).iter() | |
2504 | .find(|item| item.name() == name) | |
2505 | .map(|item| item.id()) | |
2506 | } | |
2507 | None => None | |
2508 | } | |
2509 | } | |
2510 | ||
2511 | /// Construct a parameter environment suitable for static contexts or other contexts where there | |
2512 | /// are no free type/lifetime parameters in scope. | |
2513 | pub fn empty_parameter_environment<'a>(&'a self) | |
2514 | -> ParameterEnvironment<'a,'tcx> { | |
9cc50fc6 SL |
2515 | |
2516 | // for an empty parameter environment, there ARE no free | |
2517 | // regions, so it shouldn't matter what we use for the free id | |
2518 | let free_id_outlive = self.region_maps.node_extent(ast::DUMMY_NODE_ID); | |
e9174d1e SL |
2519 | ty::ParameterEnvironment { tcx: self, |
2520 | free_substs: Substs::empty(), | |
2521 | caller_bounds: Vec::new(), | |
2522 | implicit_region_bound: ty::ReEmpty, | |
2523 | selection_cache: traits::SelectionCache::new(), | |
92a42be0 | 2524 | evaluation_cache: traits::EvaluationCache::new(), |
9cc50fc6 | 2525 | free_id_outlive: free_id_outlive } |
e9174d1e SL |
2526 | } |
2527 | ||
2528 | /// Constructs and returns a substitution that can be applied to move from | |
2529 | /// the "outer" view of a type or method to the "inner" view. | |
2530 | /// In general, this means converting from bound parameters to | |
2531 | /// free parameters. Since we currently represent bound/free type | |
2532 | /// parameters in the same way, this only has an effect on regions. | |
2533 | pub fn construct_free_substs(&self, generics: &Generics<'tcx>, | |
9cc50fc6 | 2534 | free_id_outlive: CodeExtent) -> Substs<'tcx> { |
e9174d1e SL |
2535 | // map T => T |
2536 | let mut types = VecPerParamSpace::empty(); | |
2537 | for def in generics.types.as_slice() { | |
2538 | debug!("construct_parameter_environment(): push_types_from_defs: def={:?}", | |
2539 | def); | |
2540 | types.push(def.space, self.mk_param_from_def(def)); | |
2541 | } | |
2542 | ||
e9174d1e SL |
2543 | // map bound 'a => free 'a |
2544 | let mut regions = VecPerParamSpace::empty(); | |
2545 | for def in generics.regions.as_slice() { | |
2546 | let region = | |
2547 | ReFree(FreeRegion { scope: free_id_outlive, | |
2548 | bound_region: BrNamed(def.def_id, def.name) }); | |
2549 | debug!("push_region_params {:?}", region); | |
2550 | regions.push(def.space, region); | |
2551 | } | |
2552 | ||
2553 | Substs { | |
2554 | types: types, | |
2555 | regions: subst::NonerasedRegions(regions) | |
2556 | } | |
2557 | } | |
2558 | ||
9cc50fc6 SL |
2559 | /// See `ParameterEnvironment` struct def'n for details. |
2560 | /// If you were using `free_id: NodeId`, you might try `self.region_maps.item_extent(free_id)` | |
2561 | /// for the `free_id_outlive` parameter. (But note that that is not always quite right.) | |
e9174d1e SL |
2562 | pub fn construct_parameter_environment<'a>(&'a self, |
2563 | span: Span, | |
2564 | generics: &ty::Generics<'tcx>, | |
2565 | generic_predicates: &ty::GenericPredicates<'tcx>, | |
9cc50fc6 | 2566 | free_id_outlive: CodeExtent) |
e9174d1e SL |
2567 | -> ParameterEnvironment<'a, 'tcx> |
2568 | { | |
2569 | // | |
2570 | // Construct the free substs. | |
2571 | // | |
2572 | ||
9cc50fc6 | 2573 | let free_substs = self.construct_free_substs(generics, free_id_outlive); |
e9174d1e SL |
2574 | |
2575 | // | |
2576 | // Compute the bounds on Self and the type parameters. | |
2577 | // | |
2578 | ||
2579 | let bounds = generic_predicates.instantiate(self, &free_substs); | |
2580 | let bounds = self.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds)); | |
2581 | let predicates = bounds.predicates.into_vec(); | |
2582 | ||
e9174d1e SL |
2583 | // Finally, we have to normalize the bounds in the environment, in |
2584 | // case they contain any associated type projections. This process | |
2585 | // can yield errors if the put in illegal associated types, like | |
2586 | // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We | |
2587 | // report these errors right here; this doesn't actually feel | |
2588 | // right to me, because constructing the environment feels like a | |
2589 | // kind of a "idempotent" action, but I'm not sure where would be | |
2590 | // a better place. In practice, we construct environments for | |
2591 | // every fn once during type checking, and we'll abort if there | |
2592 | // are any errors at that point, so after type checking you can be | |
2593 | // sure that this will succeed without errors anyway. | |
2594 | // | |
2595 | ||
2596 | let unnormalized_env = ty::ParameterEnvironment { | |
2597 | tcx: self, | |
2598 | free_substs: free_substs, | |
2599 | implicit_region_bound: ty::ReScope(free_id_outlive), | |
2600 | caller_bounds: predicates, | |
2601 | selection_cache: traits::SelectionCache::new(), | |
92a42be0 | 2602 | evaluation_cache: traits::EvaluationCache::new(), |
9cc50fc6 | 2603 | free_id_outlive: free_id_outlive, |
e9174d1e SL |
2604 | }; |
2605 | ||
9cc50fc6 | 2606 | let cause = traits::ObligationCause::misc(span, free_id_outlive.node_id(&self.region_maps)); |
e9174d1e SL |
2607 | traits::normalize_param_env_or_error(unnormalized_env, cause) |
2608 | } | |
2609 | ||
2610 | pub fn is_method_call(&self, expr_id: NodeId) -> bool { | |
2611 | self.tables.borrow().method_map.contains_key(&MethodCall::expr(expr_id)) | |
2612 | } | |
2613 | ||
2614 | pub fn is_overloaded_autoderef(&self, expr_id: NodeId, autoderefs: u32) -> bool { | |
2615 | self.tables.borrow().method_map.contains_key(&MethodCall::autoderef(expr_id, | |
2616 | autoderefs)) | |
2617 | } | |
2618 | ||
2619 | pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture> { | |
2620 | Some(self.tables.borrow().upvar_capture_map.get(&upvar_id).unwrap().clone()) | |
2621 | } | |
9cc50fc6 SL |
2622 | |
2623 | ||
2624 | pub fn visit_all_items_in_krate<V,F>(&self, | |
2625 | dep_node_fn: F, | |
2626 | visitor: &mut V) | |
2627 | where F: FnMut(DefId) -> DepNode, V: Visitor<'tcx> | |
2628 | { | |
2629 | dep_graph::visit_all_items_in_krate(self, dep_node_fn, visitor); | |
2630 | } | |
e9174d1e SL |
2631 | } |
2632 | ||
2633 | /// The category of explicit self. | |
2634 | #[derive(Clone, Copy, Eq, PartialEq, Debug)] | |
2635 | pub enum ExplicitSelfCategory { | |
9cc50fc6 SL |
2636 | Static, |
2637 | ByValue, | |
2638 | ByReference(Region, hir::Mutability), | |
2639 | ByBox, | |
e9174d1e SL |
2640 | } |
2641 | ||
2642 | /// A free variable referred to in a function. | |
2643 | #[derive(Copy, Clone, RustcEncodable, RustcDecodable)] | |
2644 | pub struct Freevar { | |
2645 | /// The variable being accessed free. | |
7453a54e | 2646 | pub def: Def, |
e9174d1e SL |
2647 | |
2648 | // First span where it is accessed (there can be multiple). | |
2649 | pub span: Span | |
2650 | } | |
2651 | ||
2652 | pub type FreevarMap = NodeMap<Vec<Freevar>>; | |
2653 | ||
2654 | pub type CaptureModeMap = NodeMap<hir::CaptureClause>; | |
2655 | ||
2656 | // Trait method resolution | |
2657 | pub type TraitMap = NodeMap<Vec<DefId>>; | |
2658 | ||
2659 | // Map from the NodeId of a glob import to a list of items which are actually | |
2660 | // imported. | |
2661 | pub type GlobMap = HashMap<NodeId, HashSet<Name>>; | |
2662 | ||
2663 | impl<'tcx> ctxt<'tcx> { | |
2664 | pub fn with_freevars<T, F>(&self, fid: NodeId, f: F) -> T where | |
2665 | F: FnOnce(&[Freevar]) -> T, | |
2666 | { | |
2667 | match self.freevars.borrow().get(&fid) { | |
2668 | None => f(&[]), | |
2669 | Some(d) => f(&d[..]) | |
2670 | } | |
2671 | } | |
2672 | ||
2673 | pub fn make_substs_for_receiver_types(&self, | |
2674 | trait_ref: &ty::TraitRef<'tcx>, | |
2675 | method: &ty::Method<'tcx>) | |
2676 | -> subst::Substs<'tcx> | |
2677 | { | |
2678 | /*! | |
2679 | * Substitutes the values for the receiver's type parameters | |
2680 | * that are found in method, leaving the method's type parameters | |
2681 | * intact. | |
2682 | */ | |
2683 | ||
2684 | let meth_tps: Vec<Ty> = | |
2685 | method.generics.types.get_slice(subst::FnSpace) | |
2686 | .iter() | |
2687 | .map(|def| self.mk_param_from_def(def)) | |
2688 | .collect(); | |
2689 | let meth_regions: Vec<ty::Region> = | |
2690 | method.generics.regions.get_slice(subst::FnSpace) | |
2691 | .iter() | |
2692 | .map(|def| def.to_early_bound_region()) | |
2693 | .collect(); | |
2694 | trait_ref.substs.clone().with_method(meth_tps, meth_regions) | |
2695 | } | |
2696 | } |