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