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