1 // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 #![allow(non_camel_case_types)]
13 pub use self::terr_vstore_kind::*;
14 pub use self::type_err::*;
15 pub use self::BuiltinBound::*;
16 pub use self::InferTy::*;
17 pub use self::InferRegion::*;
18 pub use self::ImplOrTraitItemId::*;
19 pub use self::UnboxedClosureKind::*;
20 pub use self::TraitStore::*;
21 pub use self::ast_ty_to_ty_cache_entry::*;
22 pub use self::Variance::*;
23 pub use self::AutoAdjustment::*;
24 pub use self::Representability::*;
25 pub use self::UnsizeKind::*;
26 pub use self::AutoRef::*;
27 pub use self::ExprKind::*;
28 pub use self::DtorKind::*;
29 pub use self::ExplicitSelfCategory::*;
30 pub use self::FnOutput::*;
31 pub use self::Region::*;
32 pub use self::ImplOrTraitItemContainer::*;
33 pub use self::BorrowKind::*;
34 pub use self::ImplOrTraitItem::*;
35 pub use self::BoundRegion::*;
37 pub use self::IntVarValue::*;
42 use metadata::csearch;
43 use middle::const_eval;
45 use middle::dependency_format;
46 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem};
47 use middle::lang_items::{FnOnceTraitLangItem, TyDescStructLangItem};
48 use middle::mem_categorization as mc;
51 use middle::resolve_lifetime;
52 use middle::stability;
53 use middle::subst::{mod, Subst, Substs, VecPerParamSpace};
57 use middle::ty_fold::{mod, TypeFoldable, TypeFolder, HigherRankedFoldable};
59 use util::ppaux::{note_and_explain_region, bound_region_ptr_to_string};
60 use util::ppaux::{trait_store_to_string, ty_to_string};
61 use util::ppaux::{Repr, UserString};
62 use util::common::{indenter, memoized};
63 use util::nodemap::{NodeMap, NodeSet, DefIdMap, DefIdSet};
64 use util::nodemap::{FnvHashMap, FnvHashSet};
65 use std::borrow::BorrowFrom;
66 use std::cell::{Cell, RefCell};
68 use std::fmt::{mod, Show};
69 use std::hash::{Hash, sip, Writer};
73 use std::collections::hash_map::{Occupied, Vacant};
74 use arena::TypedArena;
76 use syntax::ast::{CrateNum, DefId, FnStyle, Ident, ItemTrait, LOCAL_CRATE};
77 use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
78 use syntax::ast::{Onceness, StmtExpr, StmtSemi, StructField, UnnamedField};
79 use syntax::ast::{Visibility};
80 use syntax::ast_util::{mod, is_local, lit_is_str, local_def, PostExpansionMethod};
81 use syntax::attr::{mod, AttrMetaMethods};
82 use syntax::codemap::Span;
83 use syntax::parse::token::{mod, InternedString};
84 use syntax::{ast, ast_map};
85 use std::collections::enum_set::{EnumSet, CLike};
89 pub const INITIAL_DISCRIMINANT_VALUE: Disr = 0;
93 #[deriving(PartialEq, Eq, Hash)]
94 pub struct field<'tcx> {
99 #[deriving(Clone, Show)]
100 pub enum ImplOrTraitItemContainer {
101 TraitContainer(ast::DefId),
102 ImplContainer(ast::DefId),
105 impl ImplOrTraitItemContainer {
106 pub fn id(&self) -> ast::DefId {
108 TraitContainer(id) => id,
109 ImplContainer(id) => id,
115 pub enum ImplOrTraitItem<'tcx> {
116 MethodTraitItem(Rc<Method<'tcx>>),
117 TypeTraitItem(Rc<AssociatedType>),
120 impl<'tcx> ImplOrTraitItem<'tcx> {
121 fn id(&self) -> ImplOrTraitItemId {
123 MethodTraitItem(ref method) => MethodTraitItemId(method.def_id),
124 TypeTraitItem(ref associated_type) => {
125 TypeTraitItemId(associated_type.def_id)
130 pub fn def_id(&self) -> ast::DefId {
132 MethodTraitItem(ref method) => method.def_id,
133 TypeTraitItem(ref associated_type) => associated_type.def_id,
137 pub fn name(&self) -> ast::Name {
139 MethodTraitItem(ref method) => method.name,
140 TypeTraitItem(ref associated_type) => associated_type.name,
144 pub fn container(&self) -> ImplOrTraitItemContainer {
146 MethodTraitItem(ref method) => method.container,
147 TypeTraitItem(ref associated_type) => associated_type.container,
151 pub fn as_opt_method(&self) -> Option<Rc<Method<'tcx>>> {
153 MethodTraitItem(ref m) => Some((*m).clone()),
154 TypeTraitItem(_) => None
160 pub enum ImplOrTraitItemId {
161 MethodTraitItemId(ast::DefId),
162 TypeTraitItemId(ast::DefId),
165 impl ImplOrTraitItemId {
166 pub fn def_id(&self) -> ast::DefId {
168 MethodTraitItemId(def_id) => def_id,
169 TypeTraitItemId(def_id) => def_id,
174 #[deriving(Clone, Show)]
175 pub struct Method<'tcx> {
177 pub generics: ty::Generics<'tcx>,
178 pub fty: BareFnTy<'tcx>,
179 pub explicit_self: ExplicitSelfCategory,
180 pub vis: ast::Visibility,
181 pub def_id: ast::DefId,
182 pub container: ImplOrTraitItemContainer,
184 // If this method is provided, we need to know where it came from
185 pub provided_source: Option<ast::DefId>
188 impl<'tcx> Method<'tcx> {
189 pub fn new(name: ast::Name,
190 generics: ty::Generics<'tcx>,
192 explicit_self: ExplicitSelfCategory,
193 vis: ast::Visibility,
195 container: ImplOrTraitItemContainer,
196 provided_source: Option<ast::DefId>)
202 explicit_self: explicit_self,
205 container: container,
206 provided_source: provided_source
210 pub fn container_id(&self) -> ast::DefId {
211 match self.container {
212 TraitContainer(id) => id,
213 ImplContainer(id) => id,
219 pub struct AssociatedType {
221 pub vis: ast::Visibility,
222 pub def_id: ast::DefId,
223 pub container: ImplOrTraitItemContainer,
226 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
227 pub struct mt<'tcx> {
229 pub mutbl: ast::Mutability,
232 #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
233 pub enum TraitStore {
236 /// &Trait and &mut Trait
237 RegionTraitStore(Region, ast::Mutability),
240 #[deriving(Clone, Show)]
241 pub struct field_ty {
244 pub vis: ast::Visibility,
245 pub origin: ast::DefId, // The DefId of the struct in which the field is declared.
248 // Contains information needed to resolve types and (in the future) look up
249 // the types of AST nodes.
250 #[deriving(PartialEq, Eq, Hash)]
251 pub struct creader_cache_key {
257 pub enum ast_ty_to_ty_cache_entry<'tcx> {
258 atttce_unresolved, /* not resolved yet */
259 atttce_resolved(Ty<'tcx>) /* resolved to a type, irrespective of region */
262 #[deriving(Clone, PartialEq, Decodable, Encodable)]
263 pub struct ItemVariances {
264 pub types: VecPerParamSpace<Variance>,
265 pub regions: VecPerParamSpace<Variance>,
268 #[deriving(Clone, PartialEq, Decodable, Encodable, Show)]
270 Covariant, // T<A> <: T<B> iff A <: B -- e.g., function return type
271 Invariant, // T<A> <: T<B> iff B == A -- e.g., type of mutable cell
272 Contravariant, // T<A> <: T<B> iff B <: A -- e.g., function param type
273 Bivariant, // T<A> <: T<B> -- e.g., unused type parameter
276 #[deriving(Clone, Show)]
277 pub enum AutoAdjustment<'tcx> {
278 AdjustAddEnv(ty::TraitStore),
279 AdjustDerefRef(AutoDerefRef<'tcx>)
282 #[deriving(Clone, PartialEq, Show)]
283 pub enum UnsizeKind<'tcx> {
284 // [T, ..n] -> [T], the uint field is n.
286 // An unsize coercion applied to the tail field of a struct.
287 // The uint is the index of the type parameter which is unsized.
288 UnsizeStruct(Box<UnsizeKind<'tcx>>, uint),
289 UnsizeVtable(TyTrait<'tcx>, /* the self type of the trait */ Ty<'tcx>)
292 #[deriving(Clone, Show)]
293 pub struct AutoDerefRef<'tcx> {
294 pub autoderefs: uint,
295 pub autoref: Option<AutoRef<'tcx>>
298 #[deriving(Clone, PartialEq, Show)]
299 pub enum AutoRef<'tcx> {
300 /// Convert from T to &T
301 /// The third field allows us to wrap other AutoRef adjustments.
302 AutoPtr(Region, ast::Mutability, Option<Box<AutoRef<'tcx>>>),
304 /// Convert [T, ..n] to [T] (or similar, depending on the kind)
305 AutoUnsize(UnsizeKind<'tcx>),
307 /// Convert Box<[T, ..n]> to Box<[T]> or something similar in a Box.
308 /// With DST and Box a library type, this should be replaced by UnsizeStruct.
309 AutoUnsizeUniq(UnsizeKind<'tcx>),
311 /// Convert from T to *T
312 /// Value to thin pointer
313 /// The second field allows us to wrap other AutoRef adjustments.
314 AutoUnsafe(ast::Mutability, Option<Box<AutoRef<'tcx>>>),
317 // Ugly little helper function. The first bool in the returned tuple is true if
318 // there is an 'unsize to trait object' adjustment at the bottom of the
319 // adjustment. If that is surrounded by an AutoPtr, then we also return the
320 // region of the AutoPtr (in the third argument). The second bool is true if the
321 // adjustment is unique.
322 fn autoref_object_region(autoref: &AutoRef) -> (bool, bool, Option<Region>) {
323 fn unsize_kind_is_object(k: &UnsizeKind) -> bool {
325 &UnsizeVtable(..) => true,
326 &UnsizeStruct(box ref k, _) => unsize_kind_is_object(k),
332 &AutoUnsize(ref k) => (unsize_kind_is_object(k), false, None),
333 &AutoUnsizeUniq(ref k) => (unsize_kind_is_object(k), true, None),
334 &AutoPtr(adj_r, _, Some(box ref autoref)) => {
335 let (b, u, r) = autoref_object_region(autoref);
336 if r.is_some() || u {
342 &AutoUnsafe(_, Some(box ref autoref)) => autoref_object_region(autoref),
343 _ => (false, false, None)
347 // If the adjustment introduces a borrowed reference to a trait object, then
348 // returns the region of the borrowed reference.
349 pub fn adjusted_object_region(adj: &AutoAdjustment) -> Option<Region> {
351 &AdjustDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
352 let (b, _, r) = autoref_object_region(autoref);
363 // Returns true if there is a trait cast at the bottom of the adjustment.
364 pub fn adjust_is_object(adj: &AutoAdjustment) -> bool {
366 &AdjustDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
367 let (b, _, _) = autoref_object_region(autoref);
374 // If possible, returns the type expected from the given adjustment. This is not
375 // possible if the adjustment depends on the type of the adjusted expression.
376 pub fn type_of_adjust<'tcx>(cx: &ctxt<'tcx>, adj: &AutoAdjustment<'tcx>) -> Option<Ty<'tcx>> {
377 fn type_of_autoref<'tcx>(cx: &ctxt<'tcx>, autoref: &AutoRef<'tcx>) -> Option<Ty<'tcx>> {
379 &AutoUnsize(ref k) => match k {
380 &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
381 Some(mk_trait(cx, (*principal).clone(), bounds))
385 &AutoUnsizeUniq(ref k) => match k {
386 &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
387 Some(mk_uniq(cx, mk_trait(cx, (*principal).clone(), bounds)))
391 &AutoPtr(r, m, Some(box ref autoref)) => {
392 match type_of_autoref(cx, autoref) {
393 Some(ty) => Some(mk_rptr(cx, r, mt {mutbl: m, ty: ty})),
397 &AutoUnsafe(m, Some(box ref autoref)) => {
398 match type_of_autoref(cx, autoref) {
399 Some(ty) => Some(mk_ptr(cx, mt {mutbl: m, ty: ty})),
408 &AdjustDerefRef(AutoDerefRef{autoref: Some(ref autoref), ..}) => {
409 type_of_autoref(cx, autoref)
417 /// A restriction that certain types must be the same size. The use of
418 /// `transmute` gives rise to these restrictions.
419 pub struct TransmuteRestriction<'tcx> {
420 /// The span from whence the restriction comes.
422 /// The type being transmuted from.
424 /// The type being transmuted to.
426 /// NodeIf of the transmute intrinsic.
430 /// The data structure to keep track of all the information that typechecker
431 /// generates so that so that it can be reused and doesn't have to be redone
433 pub struct ctxt<'tcx> {
434 /// The arena that types are allocated from.
435 type_arena: &'tcx TypedArena<TyS<'tcx>>,
437 /// Specifically use a speedy hash algorithm for this hash map, it's used
439 // FIXME(eddyb) use a FnvHashSet<InternedTy<'tcx>> when equivalent keys can
440 // queried from a HashSet.
441 interner: RefCell<FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>>,
443 pub def_map: resolve::DefMap,
445 pub named_region_map: resolve_lifetime::NamedRegionMap,
447 pub region_maps: middle::region::RegionMaps,
449 /// Stores the types for various nodes in the AST. Note that this table
450 /// is not guaranteed to be populated until after typeck. See
451 /// typeck::check::fn_ctxt for details.
452 pub node_types: RefCell<NodeMap<Ty<'tcx>>>,
454 /// Stores the type parameters which were substituted to obtain the type
455 /// of this node. This only applies to nodes that refer to entities
456 /// parameterized by type parameters, such as generic fns, types, or
458 pub item_substs: RefCell<NodeMap<ItemSubsts<'tcx>>>,
460 /// Maps from a trait item to the trait item "descriptor"
461 pub impl_or_trait_items: RefCell<DefIdMap<ImplOrTraitItem<'tcx>>>,
463 /// Maps from a trait def-id to a list of the def-ids of its trait items
464 pub trait_item_def_ids: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItemId>>>>,
466 /// A cache for the trait_items() routine
467 pub trait_items_cache: RefCell<DefIdMap<Rc<Vec<ImplOrTraitItem<'tcx>>>>>,
469 pub impl_trait_cache: RefCell<DefIdMap<Option<Rc<ty::TraitRef<'tcx>>>>>,
471 pub trait_refs: RefCell<NodeMap<Rc<TraitRef<'tcx>>>>,
472 pub trait_defs: RefCell<DefIdMap<Rc<TraitDef<'tcx>>>>,
474 /// Maps from node-id of a trait object cast (like `foo as
475 /// Box<Trait>`) to the trait reference.
476 pub object_cast_map: typeck::ObjectCastMap<'tcx>,
478 pub map: ast_map::Map<'tcx>,
479 pub intrinsic_defs: RefCell<DefIdMap<Ty<'tcx>>>,
480 pub freevars: RefCell<FreevarMap>,
481 pub tcache: RefCell<DefIdMap<Polytype<'tcx>>>,
482 pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
483 pub short_names_cache: RefCell<FnvHashMap<Ty<'tcx>, String>>,
484 pub needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
485 pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>,
486 pub ast_ty_to_ty_cache: RefCell<NodeMap<ast_ty_to_ty_cache_entry<'tcx>>>,
487 pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>,
488 pub ty_param_defs: RefCell<NodeMap<TypeParameterDef<'tcx>>>,
489 pub adjustments: RefCell<NodeMap<AutoAdjustment<'tcx>>>,
490 pub normalized_cache: RefCell<FnvHashMap<Ty<'tcx>, Ty<'tcx>>>,
491 pub lang_items: middle::lang_items::LanguageItems,
492 /// A mapping of fake provided method def_ids to the default implementation
493 pub provided_method_sources: RefCell<DefIdMap<ast::DefId>>,
494 pub struct_fields: RefCell<DefIdMap<Rc<Vec<field_ty>>>>,
496 /// Maps from def-id of a type or region parameter to its
497 /// (inferred) variance.
498 pub item_variance_map: RefCell<DefIdMap<Rc<ItemVariances>>>,
500 /// True if the variance has been computed yet; false otherwise.
501 pub variance_computed: Cell<bool>,
503 /// A mapping from the def ID of an enum or struct type to the def ID
504 /// of the method that implements its destructor. If the type is not
505 /// present in this map, it does not have a destructor. This map is
506 /// populated during the coherence phase of typechecking.
507 pub destructor_for_type: RefCell<DefIdMap<ast::DefId>>,
509 /// A method will be in this list if and only if it is a destructor.
510 pub destructors: RefCell<DefIdSet>,
512 /// Maps a trait onto a list of impls of that trait.
513 pub trait_impls: RefCell<DefIdMap<Rc<RefCell<Vec<ast::DefId>>>>>,
515 /// Maps a DefId of a type to a list of its inherent impls.
516 /// Contains implementations of methods that are inherent to a type.
517 /// Methods in these implementations don't need to be exported.
518 pub inherent_impls: RefCell<DefIdMap<Rc<Vec<ast::DefId>>>>,
520 /// Maps a DefId of an impl to a list of its items.
521 /// Note that this contains all of the impls that we know about,
522 /// including ones in other crates. It's not clear that this is the best
524 pub impl_items: RefCell<DefIdMap<Vec<ImplOrTraitItemId>>>,
526 /// Set of used unsafe nodes (functions or blocks). Unsafe nodes not
527 /// present in this set can be warned about.
528 pub used_unsafe: RefCell<NodeSet>,
530 /// Set of nodes which mark locals as mutable which end up getting used at
531 /// some point. Local variable definitions not in this set can be warned
533 pub used_mut_nodes: RefCell<NodeSet>,
535 /// The set of external nominal types whose implementations have been read.
536 /// This is used for lazy resolution of methods.
537 pub populated_external_types: RefCell<DefIdSet>,
539 /// The set of external traits whose implementations have been read. This
540 /// is used for lazy resolution of traits.
541 pub populated_external_traits: RefCell<DefIdSet>,
544 pub upvar_borrow_map: RefCell<UpvarBorrowMap>,
546 /// These two caches are used by const_eval when decoding external statics
547 /// and variants that are found.
548 pub extern_const_statics: RefCell<DefIdMap<ast::NodeId>>,
549 pub extern_const_variants: RefCell<DefIdMap<ast::NodeId>>,
551 pub method_map: typeck::MethodMap<'tcx>,
553 pub dependency_formats: RefCell<dependency_format::Dependencies>,
555 /// Records the type of each unboxed closure. The def ID is the ID of the
556 /// expression defining the unboxed closure.
557 pub unboxed_closures: RefCell<DefIdMap<UnboxedClosure<'tcx>>>,
559 pub node_lint_levels: RefCell<FnvHashMap<(ast::NodeId, lint::LintId),
562 /// The types that must be asserted to be the same size for `transmute`
563 /// to be valid. We gather up these restrictions in the intrinsicck pass
564 /// and check them in trans.
565 pub transmute_restrictions: RefCell<Vec<TransmuteRestriction<'tcx>>>,
567 /// Maps any item's def-id to its stability index.
568 pub stability: RefCell<stability::Index>,
570 /// Maps closures to their capture clauses.
571 pub capture_modes: RefCell<CaptureModeMap>,
573 /// Maps def IDs to true if and only if they're associated types.
574 pub associated_types: RefCell<DefIdMap<bool>>,
576 /// Caches the results of trait selection. This cache is used
577 /// for things that do not have to do with the parameters in scope.
578 pub selection_cache: traits::SelectionCache<'tcx>,
580 /// Caches the representation hints for struct definitions.
581 pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
584 // Flags that we track on types. These flags are propagated upwards
585 // through the type during type construction, so that we can quickly
586 // check whether the type has various kinds of types in it without
587 // recursing over the type itself.
589 flags TypeFlags: u32 {
590 const NO_TYPE_FLAGS = 0b0,
591 const HAS_PARAMS = 0b1,
592 const HAS_SELF = 0b10,
593 const HAS_TY_INFER = 0b100,
594 const HAS_RE_INFER = 0b1000,
595 const HAS_RE_LATE_BOUND = 0b10000,
596 const HAS_REGIONS = 0b100000,
597 const HAS_TY_ERR = 0b1000000,
598 const NEEDS_SUBST = HAS_PARAMS.bits | HAS_SELF.bits | HAS_REGIONS.bits,
603 pub struct TyS<'tcx> {
605 pub flags: TypeFlags,
607 // the maximal depth of any bound regions appearing in this type.
611 impl fmt::Show for TypeFlags {
612 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
613 write!(f, "{}", self.bits)
617 impl<'tcx> PartialEq for TyS<'tcx> {
618 fn eq(&self, other: &TyS<'tcx>) -> bool {
619 (self as *const _) == (other as *const _)
622 impl<'tcx> Eq for TyS<'tcx> {}
624 impl<'tcx, S: Writer> Hash<S> for TyS<'tcx> {
625 fn hash(&self, s: &mut S) {
626 (self as *const _).hash(s)
630 pub type Ty<'tcx> = &'tcx TyS<'tcx>;
632 /// An entry in the type interner.
633 pub struct InternedTy<'tcx> {
637 // NB: An InternedTy compares and hashes as a sty.
638 impl<'tcx> PartialEq for InternedTy<'tcx> {
639 fn eq(&self, other: &InternedTy<'tcx>) -> bool {
640 self.ty.sty == other.ty.sty
643 impl<'tcx> Eq for InternedTy<'tcx> {}
645 impl<'tcx, S: Writer> Hash<S> for InternedTy<'tcx> {
646 fn hash(&self, s: &mut S) {
651 impl<'tcx> BorrowFrom<InternedTy<'tcx>> for sty<'tcx> {
652 fn borrow_from<'a>(ty: &'a InternedTy<'tcx>) -> &'a sty<'tcx> {
657 pub fn type_has_params(ty: Ty) -> bool {
658 ty.flags.intersects(HAS_PARAMS)
660 pub fn type_has_self(ty: Ty) -> bool {
661 ty.flags.intersects(HAS_SELF)
663 pub fn type_has_ty_infer(ty: Ty) -> bool {
664 ty.flags.intersects(HAS_TY_INFER)
666 pub fn type_needs_infer(ty: Ty) -> bool {
667 ty.flags.intersects(HAS_TY_INFER | HAS_RE_INFER)
670 pub fn type_has_late_bound_regions(ty: Ty) -> bool {
671 ty.flags.intersects(HAS_RE_LATE_BOUND)
674 /// An "escaping region" is a bound region whose binder is not part of `t`.
676 /// So, for example, consider a type like the following, which has two binders:
678 /// for<'a> fn(x: for<'b> fn(&'a int, &'b int))
679 /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
680 /// ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope
682 /// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the
683 /// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
684 /// fn type*, that type has an escaping region: `'a`.
686 /// Note that what I'm calling an "escaping region" is often just called a "free region". However,
687 /// we already use the term "free region". It refers to the regions that we use to represent bound
688 /// regions on a fn definition while we are typechecking its body.
690 /// To clarify, conceptually there is no particular difference between an "escaping" region and a
691 /// "free" region. However, there is a big difference in practice. Basically, when "entering" a
692 /// binding level, one is generally required to do some sort of processing to a bound region, such
693 /// as replacing it with a fresh/skolemized region, or making an entry in the environment to
694 /// represent the scope to which it is attached, etc. An escaping region represents a bound region
695 /// for which this processing has not yet been done.
696 pub fn type_has_escaping_regions(ty: Ty) -> bool {
697 type_escapes_depth(ty, 0)
700 pub fn type_escapes_depth(ty: Ty, depth: uint) -> bool {
701 ty.region_depth > depth
704 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
705 pub struct BareFnTy<'tcx> {
706 pub fn_style: ast::FnStyle,
708 pub sig: FnSig<'tcx>,
711 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
712 pub struct ClosureTy<'tcx> {
713 pub fn_style: ast::FnStyle,
714 pub onceness: ast::Onceness,
715 pub store: TraitStore,
716 pub bounds: ExistentialBounds,
717 pub sig: FnSig<'tcx>,
721 #[deriving(Clone, PartialEq, Eq, Hash)]
722 pub enum FnOutput<'tcx> {
723 FnConverging(Ty<'tcx>),
727 impl<'tcx> FnOutput<'tcx> {
728 pub fn unwrap(self) -> Ty<'tcx> {
730 ty::FnConverging(t) => t,
731 ty::FnDiverging => unreachable!()
737 * Signature of a function type, which I have arbitrarily
738 * decided to use to refer to the input/output types.
740 * - `inputs` is the list of arguments and their modes.
741 * - `output` is the return type.
742 * - `variadic` indicates whether this is a varidic function. (only true for foreign fns)
744 * Note that a `FnSig` introduces a level of region binding, to
745 * account for late-bound parameters that appear in the types of the
746 * fn's arguments or the fn's return type.
748 #[deriving(Clone, PartialEq, Eq, Hash)]
749 pub struct FnSig<'tcx> {
750 pub inputs: Vec<Ty<'tcx>>,
751 pub output: FnOutput<'tcx>,
755 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
757 pub space: subst::ParamSpace,
763 * A [De Bruijn index][dbi] is a standard means of representing
764 * regions (and perhaps later types) in a higher-ranked setting. In
765 * particular, imagine a type like this:
767 * for<'a> fn(for<'b> fn(&'b int, &'a int), &'a char)
770 * | +------------+ 1 | |
772 * +--------------------------------+ 2 |
774 * +------------------------------------------+ 1
776 * In this type, there are two binders (the outer fn and the inner
777 * fn). We need to be able to determine, for any given region, which
778 * fn type it is bound by, the inner or the outer one. There are
779 * various ways you can do this, but a De Bruijn index is one of the
780 * more convenient and has some nice properties. The basic idea is to
781 * count the number of binders, inside out. Some examples should help
782 * clarify what I mean.
784 * Let's start with the reference type `&'b int` that is the first
785 * argument to the inner function. This region `'b` is assigned a De
786 * Bruijn index of 1, meaning "the innermost binder" (in this case, a
787 * fn). The region `'a` that appears in the second argument type (`&'a
788 * int`) would then be assigned a De Bruijn index of 2, meaning "the
789 * second-innermost binder". (These indices are written on the arrays
792 * What is interesting is that De Bruijn index attached to a particular
793 * variable will vary depending on where it appears. For example,
794 * the final type `&'a char` also refers to the region `'a` declared on
795 * the outermost fn. But this time, this reference is not nested within
796 * any other binders (i.e., it is not an argument to the inner fn, but
797 * rather the outer one). Therefore, in this case, it is assigned a
798 * De Bruijn index of 1, because the innermost binder in that location
801 * [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
803 #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
804 pub struct DebruijnIndex {
805 // We maintain the invariant that this is never 0. So 1 indicates
806 // the innermost binder. To ensure this, create with `DebruijnIndex::new`.
810 /// Representation of regions:
811 #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
813 // Region bound in a type or fn declaration which will be
814 // substituted 'early' -- that is, at the same time when type
815 // parameters are substituted.
816 ReEarlyBound(/* param id */ ast::NodeId,
821 // Region bound in a function scope, which will be substituted when the
822 // function is called.
823 ReLateBound(DebruijnIndex, BoundRegion),
825 /// When checking a function body, the types of all arguments and so forth
826 /// that refer to bound region parameters are modified to refer to free
827 /// region parameters.
830 /// A concrete region naming some expression within the current function.
831 ReScope(region::CodeExtent),
833 /// Static data that has an "infinite" lifetime. Top in the region lattice.
836 /// A region variable. Should not exist after typeck.
837 ReInfer(InferRegion),
839 /// Empty lifetime is for data that is never accessed.
840 /// Bottom in the region lattice. We treat ReEmpty somewhat
841 /// specially; at least right now, we do not generate instances of
842 /// it during the GLB computations, but rather
843 /// generate an error instead. This is to improve error messages.
844 /// The only way to get an instance of ReEmpty is to have a region
845 /// variable with no constraints.
850 * Upvars do not get their own node-id. Instead, we use the pair of
851 * the original var id (that is, the root variable that is referenced
852 * by the upvar) and the id of the closure expression.
854 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
856 pub var_id: ast::NodeId,
857 pub closure_expr_id: ast::NodeId,
860 #[deriving(Clone, PartialEq, Eq, Hash, Show, Encodable, Decodable)]
861 pub enum BorrowKind {
862 /// Data must be immutable and is aliasable.
865 /// Data must be immutable but not aliasable. This kind of borrow
866 /// cannot currently be expressed by the user and is used only in
867 /// implicit closure bindings. It is needed when you the closure
868 /// is borrowing or mutating a mutable referent, e.g.:
870 /// let x: &mut int = ...;
871 /// let y = || *x += 5;
873 /// If we were to try to translate this closure into a more explicit
874 /// form, we'd encounter an error with the code as written:
876 /// struct Env { x: & &mut int }
877 /// let x: &mut int = ...;
878 /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
879 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
881 /// This is then illegal because you cannot mutate a `&mut` found
882 /// in an aliasable location. To solve, you'd have to translate with
883 /// an `&mut` borrow:
885 /// struct Env { x: & &mut int }
886 /// let x: &mut int = ...;
887 /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
888 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
890 /// Now the assignment to `**env.x` is legal, but creating a
891 /// mutable pointer to `x` is not because `x` is not mutable. We
892 /// could fix this by declaring `x` as `let mut x`. This is ok in
893 /// user code, if awkward, but extra weird for closures, since the
894 /// borrow is hidden.
896 /// So we introduce a "unique imm" borrow -- the referent is
897 /// immutable, but not aliasable. This solves the problem. For
898 /// simplicity, we don't give users the way to express this
899 /// borrow, it's just used when translating closures.
902 /// Data is mutable and not aliasable.
907 * Information describing the borrowing of an upvar. This is computed
908 * during `typeck`, specifically by `regionck`. The general idea is
909 * that the compiler analyses treat closures like:
911 * let closure: &'e fn() = || {
912 * x = 1; // upvar x is assigned to
913 * use(y); // upvar y is read
914 * foo(&z); // upvar z is borrowed immutably
917 * as if they were "desugared" to something loosely like:
919 * struct Vars<'x,'y,'z> { x: &'x mut int,
922 * let closure: &'e fn() = {
928 * let env: &'e mut Vars<'x,'y,'z> = &mut Vars { x: &'x mut x,
934 * This is basically what happens at runtime. The closure is basically
935 * an existentially quantified version of the `(env, f)` pair.
937 * This data structure indicates the region and mutability of a single
938 * one of the `x...z` borrows.
940 * It may not be obvious why each borrowed variable gets its own
941 * lifetime (in the desugared version of the example, these are indicated
942 * by the lifetime parameters `'x`, `'y`, and `'z` in the `Vars` definition).
943 * Each such lifetime must encompass the lifetime `'e` of the closure itself,
944 * but need not be identical to it. The reason that this makes sense:
946 * - Callers are only permitted to invoke the closure, and hence to
947 * use the pointers, within the lifetime `'e`, so clearly `'e` must
948 * be a sublifetime of `'x...'z`.
949 * - The closure creator knows which upvars were borrowed by the closure
950 * and thus `x...z` will be reserved for `'x...'z` respectively.
951 * - Through mutation, the borrowed upvars can actually escape
952 * the closure, so sometimes it is necessary for them to be larger
953 * than the closure lifetime itself.
955 #[deriving(PartialEq, Clone, Encodable, Decodable, Show)]
956 pub struct UpvarBorrow {
957 pub kind: BorrowKind,
958 pub region: ty::Region,
961 pub type UpvarBorrowMap = FnvHashMap<UpvarId, UpvarBorrow>;
964 pub fn is_bound(&self) -> bool {
966 ty::ReEarlyBound(..) => true,
967 ty::ReLateBound(..) => true,
972 pub fn escapes_depth(&self, depth: uint) -> bool {
974 ty::ReLateBound(debruijn, _) => debruijn.depth > depth,
980 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
981 /// A "free" region `fr` can be interpreted as "some region
982 /// at least as big as the scope `fr.scope`".
983 pub struct FreeRegion {
984 pub scope: region::CodeExtent,
985 pub bound_region: BoundRegion
988 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
989 pub enum BoundRegion {
990 /// An anonymous region parameter for a given fn (&T)
993 /// Named region parameters for functions (a in &'a T)
995 /// The def-id is needed to distinguish free regions in
996 /// the event of shadowing.
997 BrNamed(ast::DefId, ast::Name),
999 /// Fresh bound identifiers created during GLB computations.
1002 // Anonymous region for the implicit env pointer parameter
1008 pub fn mk_prim_t<'tcx>(primitive: &'tcx TyS<'static>) -> Ty<'tcx> {
1009 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
1010 unsafe { &*(primitive as *const _ as *const TyS<'tcx>) }
1013 // Do not change these from static to const, interning types requires
1014 // the primitives to have a significant address.
1015 macro_rules! def_prim_tys(
1016 ($($name:ident -> $sty:expr;)*) => (
1017 $(#[inline] pub fn $name<'tcx>() -> Ty<'tcx> {
1018 static PRIM_TY: TyS<'static> = TyS {
1020 flags: NO_TYPE_FLAGS,
1031 mk_int -> ty_int(ast::TyI);
1032 mk_i8 -> ty_int(ast::TyI8);
1033 mk_i16 -> ty_int(ast::TyI16);
1034 mk_i32 -> ty_int(ast::TyI32);
1035 mk_i64 -> ty_int(ast::TyI64);
1036 mk_uint -> ty_uint(ast::TyU);
1037 mk_u8 -> ty_uint(ast::TyU8);
1038 mk_u16 -> ty_uint(ast::TyU16);
1039 mk_u32 -> ty_uint(ast::TyU32);
1040 mk_u64 -> ty_uint(ast::TyU64);
1041 mk_f32 -> ty_float(ast::TyF32);
1042 mk_f64 -> ty_float(ast::TyF64);
1046 pub fn mk_err<'tcx>() -> Ty<'tcx> {
1047 static TY_ERR: TyS<'static> = TyS {
1055 // NB: If you change this, you'll probably want to change the corresponding
1056 // AST structure in libsyntax/ast.rs as well.
1057 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
1058 pub enum sty<'tcx> {
1062 ty_uint(ast::UintTy),
1063 ty_float(ast::FloatTy),
1064 /// Substs here, possibly against intuition, *may* contain `ty_param`s.
1065 /// That is, even after substitution it is possible that there are type
1066 /// variables. This happens when the `ty_enum` corresponds to an enum
1067 /// definition and not a concrete use of it. To get the correct `ty_enum`
1068 /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in
1069 /// the `ast_ty_to_ty_cache`. This is probably true for `ty_struct` as
1071 ty_enum(DefId, Substs<'tcx>),
1074 ty_vec(Ty<'tcx>, Option<uint>), // Second field is length.
1076 ty_rptr(Region, mt<'tcx>),
1077 ty_bare_fn(BareFnTy<'tcx>),
1078 ty_closure(Box<ClosureTy<'tcx>>),
1079 ty_trait(Box<TyTrait<'tcx>>),
1080 ty_struct(DefId, Substs<'tcx>),
1081 ty_unboxed_closure(DefId, Region, Substs<'tcx>),
1082 ty_tup(Vec<Ty<'tcx>>),
1084 ty_param(ParamTy), // type parameter
1085 ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value
1086 // and its size. Only ever used in trans. It is not necessary
1087 // earlier since we don't need to distinguish a DST with its
1088 // size (e.g., in a deref) vs a DST with the size elsewhere (
1089 // e.g., in a field).
1091 ty_infer(InferTy), // something used only during inference/typeck
1092 ty_err, // Also only used during inference/typeck, to represent
1093 // the type of an erroneous expression (helps cut down
1094 // on non-useful type error messages)
1097 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
1098 pub struct TyTrait<'tcx> {
1099 // Principal trait reference.
1100 pub principal: TraitRef<'tcx>, // would use Rc<TraitRef>, but it runs afoul of some static rules
1101 pub bounds: ExistentialBounds
1105 * A complete reference to a trait. These take numerous guises in syntax,
1106 * but perhaps the most recognizable form is in a where clause:
1110 * This would be represented by a trait-reference where the def-id is the
1111 * def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
1112 * `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
1114 * Trait references also appear in object types like `Foo<U>`, but in
1115 * that case the `Self` parameter is absent from the substitutions.
1117 * Note that a `TraitRef` introduces a level of region binding, to
1118 * account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
1119 * U>` or higher-ranked object types.
1121 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
1122 pub struct TraitRef<'tcx> {
1124 pub substs: Substs<'tcx>,
1128 * Binder serves as a synthetic binder for lifetimes. It is used when
1129 * we wish to replace the escaping higher-ranked lifetimes in a type
1130 * or something else that is not itself a binder (this is because the
1131 * `replace_late_bound_regions` function replaces all lifetimes bound
1132 * by the binder supplied to it; but a type is not a binder, so you
1133 * must introduce an artificial one).
1135 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
1136 pub struct Binder<T> {
1140 pub fn bind<T>(value: T) -> Binder<T> {
1141 Binder { value: value }
1144 #[deriving(Clone, PartialEq)]
1145 pub enum IntVarValue {
1146 IntType(ast::IntTy),
1147 UintType(ast::UintTy),
1150 #[deriving(Clone, Show)]
1151 pub enum terr_vstore_kind {
1158 #[deriving(Clone, Show)]
1159 pub struct expected_found<T> {
1164 // Data structures used in type unification
1165 #[deriving(Clone, Show)]
1166 pub enum type_err<'tcx> {
1168 terr_fn_style_mismatch(expected_found<FnStyle>),
1169 terr_onceness_mismatch(expected_found<Onceness>),
1170 terr_abi_mismatch(expected_found<abi::Abi>),
1172 terr_sigil_mismatch(expected_found<TraitStore>),
1173 terr_box_mutability,
1174 terr_ptr_mutability,
1175 terr_ref_mutability,
1176 terr_vec_mutability,
1177 terr_tuple_size(expected_found<uint>),
1178 terr_fixed_array_size(expected_found<uint>),
1179 terr_ty_param_size(expected_found<uint>),
1181 terr_regions_does_not_outlive(Region, Region),
1182 terr_regions_not_same(Region, Region),
1183 terr_regions_no_overlap(Region, Region),
1184 terr_regions_insufficiently_polymorphic(BoundRegion, Region),
1185 terr_regions_overly_polymorphic(BoundRegion, Region),
1186 terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
1187 terr_sorts(expected_found<Ty<'tcx>>),
1188 terr_integer_as_char,
1189 terr_int_mismatch(expected_found<IntVarValue>),
1190 terr_float_mismatch(expected_found<ast::FloatTy>),
1191 terr_traits(expected_found<ast::DefId>),
1192 terr_builtin_bounds(expected_found<BuiltinBounds>),
1193 terr_variadic_mismatch(expected_found<bool>),
1195 terr_convergence_mismatch(expected_found<bool>)
1198 /// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
1199 /// as well as the existential type parameter in an object type.
1200 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
1201 pub struct ParamBounds<'tcx> {
1202 pub region_bounds: Vec<ty::Region>,
1203 pub builtin_bounds: BuiltinBounds,
1204 pub trait_bounds: Vec<Rc<TraitRef<'tcx>>>
1207 /// Bounds suitable for an existentially quantified type parameter
1208 /// such as those that appear in object types or closure types. The
1209 /// major difference between this case and `ParamBounds` is that
1210 /// general purpose trait bounds are omitted and there must be
1211 /// *exactly one* region.
1212 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
1213 pub struct ExistentialBounds {
1214 pub region_bound: ty::Region,
1215 pub builtin_bounds: BuiltinBounds
1218 pub type BuiltinBounds = EnumSet<BuiltinBound>;
1220 #[deriving(Clone, Encodable, PartialEq, Eq, Decodable, Hash, Show)]
1222 pub enum BuiltinBound {
1229 pub fn empty_builtin_bounds() -> BuiltinBounds {
1233 pub fn all_builtin_bounds() -> BuiltinBounds {
1234 let mut set = EnumSet::new();
1235 set.insert(BoundSend);
1236 set.insert(BoundSized);
1237 set.insert(BoundSync);
1241 /// An existential bound that does not implement any traits.
1242 pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds {
1243 ty::ExistentialBounds { region_bound: r,
1244 builtin_bounds: empty_builtin_bounds() }
1247 impl CLike for BuiltinBound {
1248 fn to_uint(&self) -> uint {
1251 fn from_uint(v: uint) -> BuiltinBound {
1252 unsafe { mem::transmute(v) }
1256 #[deriving(Clone, PartialEq, Eq, Hash)]
1261 #[deriving(Clone, PartialEq, Eq, Hash)]
1266 #[deriving(Clone, PartialEq, Eq, Hash)]
1267 pub struct FloatVid {
1271 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
1272 pub struct RegionVid {
1276 #[deriving(Clone, PartialEq, Eq, Hash)]
1283 // FIXME -- once integral fallback is impl'd, we should remove
1284 // this type. It's only needed to prevent spurious errors for
1285 // integers whose type winds up never being constrained.
1286 SkolemizedIntTy(uint),
1289 #[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)]
1290 pub enum InferRegion {
1292 ReSkolemized(uint, BoundRegion)
1295 impl cmp::PartialEq for InferRegion {
1296 fn eq(&self, other: &InferRegion) -> bool {
1297 match ((*self), *other) {
1298 (ReVar(rva), ReVar(rvb)) => {
1301 (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
1307 fn ne(&self, other: &InferRegion) -> bool {
1308 !((*self) == (*other))
1312 impl fmt::Show for TyVid {
1313 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
1314 write!(f, "_#{}t", self.index)
1318 impl fmt::Show for IntVid {
1319 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1320 write!(f, "_#{}i", self.index)
1324 impl fmt::Show for FloatVid {
1325 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1326 write!(f, "_#{}f", self.index)
1330 impl fmt::Show for RegionVid {
1331 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1332 write!(f, "'_#{}r", self.index)
1336 impl<'tcx> fmt::Show for FnSig<'tcx> {
1337 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1338 // grr, without tcx not much we can do.
1343 impl fmt::Show for InferTy {
1344 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1346 TyVar(ref v) => v.fmt(f),
1347 IntVar(ref v) => v.fmt(f),
1348 FloatVar(ref v) => v.fmt(f),
1349 SkolemizedTy(v) => write!(f, "SkolemizedTy({})", v),
1350 SkolemizedIntTy(v) => write!(f, "SkolemizedIntTy({})", v),
1355 impl fmt::Show for IntVarValue {
1356 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1358 IntType(ref v) => v.fmt(f),
1359 UintType(ref v) => v.fmt(f),
1364 #[deriving(Clone, Show)]
1365 pub struct TypeParameterDef<'tcx> {
1366 pub name: ast::Name,
1367 pub def_id: ast::DefId,
1368 pub space: subst::ParamSpace,
1370 pub associated_with: Option<ast::DefId>,
1371 pub bounds: ParamBounds<'tcx>,
1372 pub default: Option<Ty<'tcx>>,
1375 #[deriving(Encodable, Decodable, Clone, Show)]
1376 pub struct RegionParameterDef {
1377 pub name: ast::Name,
1378 pub def_id: ast::DefId,
1379 pub space: subst::ParamSpace,
1381 pub bounds: Vec<ty::Region>,
1384 /// Information about the type/lifetime parameters associated with an
1385 /// item or method. Analogous to ast::Generics.
1386 #[deriving(Clone, Show)]
1387 pub struct Generics<'tcx> {
1388 pub types: VecPerParamSpace<TypeParameterDef<'tcx>>,
1389 pub regions: VecPerParamSpace<RegionParameterDef>,
1392 impl<'tcx> Generics<'tcx> {
1393 pub fn empty() -> Generics<'tcx> {
1394 Generics { types: VecPerParamSpace::empty(),
1395 regions: VecPerParamSpace::empty() }
1398 pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
1399 !self.types.is_empty_in(space)
1402 pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
1403 !self.regions.is_empty_in(space)
1406 pub fn to_bounds(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>)
1407 -> GenericBounds<'tcx> {
1409 types: self.types.map(|d| d.bounds.subst(tcx, substs)),
1410 regions: self.regions.map(|d| d.bounds.subst(tcx, substs)),
1416 * Represents the bounds declared on a particular set of type
1417 * parameters. Should eventually be generalized into a flag list of
1418 * where clauses. You can obtain a `GenericBounds` list from a
1419 * `Generics` by using the `to_bounds` method. Note that this method
1420 * reflects an important semantic invariant of `GenericBounds`: while
1421 * the bounds in a `Generics` are expressed in terms of the bound type
1422 * parameters of the impl/trait/whatever, a `GenericBounds` instance
1423 * represented a set of bounds for some particular instantiation,
1424 * meaning that the generic parameters have been substituted with
1429 * struct Foo<T,U:Bar<T>> { ... }
1431 * Here, the `Generics` for `Foo` would contain a list of bounds like
1432 * `[[], [U:Bar<T>]]`. Now if there were some particular reference
1433 * like `Foo<int,uint>`, then the `GenericBounds` would be `[[],
1434 * [uint:Bar<int>]]`.
1436 #[deriving(Clone, Show)]
1437 pub struct GenericBounds<'tcx> {
1438 pub types: VecPerParamSpace<ParamBounds<'tcx>>,
1439 pub regions: VecPerParamSpace<Vec<Region>>,
1442 impl<'tcx> GenericBounds<'tcx> {
1443 pub fn empty() -> GenericBounds<'tcx> {
1444 GenericBounds { types: VecPerParamSpace::empty(),
1445 regions: VecPerParamSpace::empty() }
1448 pub fn has_escaping_regions(&self) -> bool {
1449 self.types.any(|pb| pb.trait_bounds.iter().any(|tr| tr.has_escaping_regions())) ||
1450 self.regions.any(|rs| rs.iter().any(|r| r.escapes_depth(0)))
1454 impl<'tcx> TraitRef<'tcx> {
1455 pub fn new(def_id: ast::DefId, substs: Substs<'tcx>) -> TraitRef<'tcx> {
1456 TraitRef { def_id: def_id, substs: substs }
1459 pub fn self_ty(&self) -> Ty<'tcx> {
1460 self.substs.self_ty().unwrap()
1463 pub fn input_types(&self) -> &[Ty<'tcx>] {
1464 // Select only the "input types" from a trait-reference. For
1465 // now this is all the types that appear in the
1466 // trait-reference, but it should eventually exclude
1467 // associated types.
1468 self.substs.types.as_slice()
1471 pub fn has_escaping_regions(&self) -> bool {
1472 self.substs.has_regions_escaping_depth(1)
1475 pub fn has_bound_regions(&self) -> bool {
1476 self.substs.has_regions_escaping_depth(0)
1480 /// When type checking, we use the `ParameterEnvironment` to track
1481 /// details about the type/lifetime parameters that are in scope.
1482 /// It primarily stores the bounds information.
1484 /// Note: This information might seem to be redundant with the data in
1485 /// `tcx.ty_param_defs`, but it is not. That table contains the
1486 /// parameter definitions from an "outside" perspective, but this
1487 /// struct will contain the bounds for a parameter as seen from inside
1488 /// the function body. Currently the only real distinction is that
1489 /// bound lifetime parameters are replaced with free ones, but in the
1490 /// future I hope to refine the representation of types so as to make
1491 /// more distinctions clearer.
1492 pub struct ParameterEnvironment<'tcx> {
1493 /// A substitution that can be applied to move from
1494 /// the "outer" view of a type or method to the "inner" view.
1495 /// In general, this means converting from bound parameters to
1496 /// free parameters. Since we currently represent bound/free type
1497 /// parameters in the same way, this only has an effect on regions.
1498 pub free_substs: Substs<'tcx>,
1500 /// Bounds on the various type parameters
1501 pub bounds: VecPerParamSpace<ParamBounds<'tcx>>,
1503 /// Each type parameter has an implicit region bound that
1504 /// indicates it must outlive at least the function body (the user
1505 /// may specify stronger requirements). This field indicates the
1506 /// region of the callee.
1507 pub implicit_region_bound: ty::Region,
1509 /// Obligations that the caller must satisfy. This is basically
1510 /// the set of bounds on the in-scope type parameters, translated
1511 /// into Obligations.
1513 /// Note: This effectively *duplicates* the `bounds` array for
1515 pub caller_obligations: VecPerParamSpace<traits::Obligation<'tcx>>,
1517 /// Caches the results of trait selection. This cache is used
1518 /// for things that have to do with the parameters in scope.
1519 pub selection_cache: traits::SelectionCache<'tcx>,
1522 impl<'tcx> ParameterEnvironment<'tcx> {
1523 pub fn for_item(cx: &ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'tcx> {
1524 match cx.map.find(id) {
1525 Some(ast_map::NodeImplItem(ref impl_item)) => {
1527 ast::MethodImplItem(ref method) => {
1528 let method_def_id = ast_util::local_def(id);
1529 match ty::impl_or_trait_item(cx, method_def_id) {
1530 MethodTraitItem(ref method_ty) => {
1531 let method_generics = &method_ty.generics;
1532 construct_parameter_environment(
1536 method.pe_body().id)
1538 TypeTraitItem(_) => {
1540 .bug("ParameterEnvironment::from_item(): \
1541 can't create a parameter environment \
1542 for type trait items")
1546 ast::TypeImplItem(_) => {
1547 cx.sess.bug("ParameterEnvironment::from_item(): \
1548 can't create a parameter environment \
1549 for type impl items")
1553 Some(ast_map::NodeTraitItem(trait_method)) => {
1554 match *trait_method {
1555 ast::RequiredMethod(ref required) => {
1556 cx.sess.span_bug(required.span,
1557 "ParameterEnvironment::from_item():
1558 can't create a parameter \
1559 environment for required trait \
1562 ast::ProvidedMethod(ref method) => {
1563 let method_def_id = ast_util::local_def(id);
1564 match ty::impl_or_trait_item(cx, method_def_id) {
1565 MethodTraitItem(ref method_ty) => {
1566 let method_generics = &method_ty.generics;
1567 construct_parameter_environment(
1571 method.pe_body().id)
1573 TypeTraitItem(_) => {
1575 .bug("ParameterEnvironment::from_item(): \
1576 can't create a parameter environment \
1577 for type trait items")
1581 ast::TypeTraitItem(_) => {
1582 cx.sess.bug("ParameterEnvironment::from_item(): \
1583 can't create a parameter environment \
1584 for type trait items")
1588 Some(ast_map::NodeItem(item)) => {
1590 ast::ItemFn(_, _, _, _, ref body) => {
1591 // We assume this is a function.
1592 let fn_def_id = ast_util::local_def(id);
1593 let fn_pty = ty::lookup_item_type(cx, fn_def_id);
1595 construct_parameter_environment(cx,
1601 ast::ItemStruct(..) |
1603 ast::ItemConst(..) |
1604 ast::ItemStatic(..) => {
1605 let def_id = ast_util::local_def(id);
1606 let pty = ty::lookup_item_type(cx, def_id);
1607 construct_parameter_environment(cx, item.span,
1611 cx.sess.span_bug(item.span,
1612 "ParameterEnvironment::from_item():
1613 can't create a parameter \
1614 environment for this kind of item")
1619 cx.sess.bug(format!("ParameterEnvironment::from_item(): \
1620 `{}` is not an item",
1621 cx.map.node_to_string(id)).as_slice())
1629 /// - `generics`: the set of type parameters and their bounds
1630 /// - `ty`: the base types, which may reference the parameters defined
1632 #[deriving(Clone, Show)]
1633 pub struct Polytype<'tcx> {
1634 pub generics: Generics<'tcx>,
1638 /// As `Polytype` but for a trait ref.
1639 pub struct TraitDef<'tcx> {
1640 /// Generic type definitions. Note that `Self` is listed in here
1641 /// as having a single bound, the trait itself (e.g., in the trait
1642 /// `Eq`, there is a single bound `Self : Eq`). This is so that
1643 /// default methods get to assume that the `Self` parameters
1644 /// implements the trait.
1645 pub generics: Generics<'tcx>,
1647 /// The "supertrait" bounds.
1648 pub bounds: ParamBounds<'tcx>,
1649 pub trait_ref: Rc<ty::TraitRef<'tcx>>,
1652 /// Records the substitutions used to translate the polytype for an
1653 /// item into the monotype of an item reference.
1655 pub struct ItemSubsts<'tcx> {
1656 pub substs: Substs<'tcx>,
1659 /// Records information about each unboxed closure.
1661 pub struct UnboxedClosure<'tcx> {
1662 /// The type of the unboxed closure.
1663 pub closure_type: ClosureTy<'tcx>,
1664 /// The kind of unboxed closure this is.
1665 pub kind: UnboxedClosureKind,
1668 #[deriving(Clone, PartialEq, Eq, Show)]
1669 pub enum UnboxedClosureKind {
1670 FnUnboxedClosureKind,
1671 FnMutUnboxedClosureKind,
1672 FnOnceUnboxedClosureKind,
1675 impl UnboxedClosureKind {
1676 pub fn trait_did(&self, cx: &ctxt) -> ast::DefId {
1677 let result = match *self {
1678 FnUnboxedClosureKind => cx.lang_items.require(FnTraitLangItem),
1679 FnMutUnboxedClosureKind => {
1680 cx.lang_items.require(FnMutTraitLangItem)
1682 FnOnceUnboxedClosureKind => {
1683 cx.lang_items.require(FnOnceTraitLangItem)
1687 Ok(trait_did) => trait_did,
1688 Err(err) => cx.sess.fatal(err.as_slice()),
1693 pub fn mk_ctxt<'tcx>(s: Session,
1694 type_arena: &'tcx TypedArena<TyS<'tcx>>,
1695 dm: resolve::DefMap,
1696 named_region_map: resolve_lifetime::NamedRegionMap,
1697 map: ast_map::Map<'tcx>,
1698 freevars: RefCell<FreevarMap>,
1699 capture_modes: RefCell<CaptureModeMap>,
1700 region_maps: middle::region::RegionMaps,
1701 lang_items: middle::lang_items::LanguageItems,
1702 stability: stability::Index) -> ctxt<'tcx> {
1704 type_arena: type_arena,
1705 interner: RefCell::new(FnvHashMap::new()),
1706 named_region_map: named_region_map,
1707 item_variance_map: RefCell::new(DefIdMap::new()),
1708 variance_computed: Cell::new(false),
1711 region_maps: region_maps,
1712 node_types: RefCell::new(FnvHashMap::new()),
1713 item_substs: RefCell::new(NodeMap::new()),
1714 trait_refs: RefCell::new(NodeMap::new()),
1715 trait_defs: RefCell::new(DefIdMap::new()),
1716 object_cast_map: RefCell::new(NodeMap::new()),
1718 intrinsic_defs: RefCell::new(DefIdMap::new()),
1720 tcache: RefCell::new(DefIdMap::new()),
1721 rcache: RefCell::new(FnvHashMap::new()),
1722 short_names_cache: RefCell::new(FnvHashMap::new()),
1723 needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()),
1724 tc_cache: RefCell::new(FnvHashMap::new()),
1725 ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
1726 enum_var_cache: RefCell::new(DefIdMap::new()),
1727 impl_or_trait_items: RefCell::new(DefIdMap::new()),
1728 trait_item_def_ids: RefCell::new(DefIdMap::new()),
1729 trait_items_cache: RefCell::new(DefIdMap::new()),
1730 impl_trait_cache: RefCell::new(DefIdMap::new()),
1731 ty_param_defs: RefCell::new(NodeMap::new()),
1732 adjustments: RefCell::new(NodeMap::new()),
1733 normalized_cache: RefCell::new(FnvHashMap::new()),
1734 lang_items: lang_items,
1735 provided_method_sources: RefCell::new(DefIdMap::new()),
1736 struct_fields: RefCell::new(DefIdMap::new()),
1737 destructor_for_type: RefCell::new(DefIdMap::new()),
1738 destructors: RefCell::new(DefIdSet::new()),
1739 trait_impls: RefCell::new(DefIdMap::new()),
1740 inherent_impls: RefCell::new(DefIdMap::new()),
1741 impl_items: RefCell::new(DefIdMap::new()),
1742 used_unsafe: RefCell::new(NodeSet::new()),
1743 used_mut_nodes: RefCell::new(NodeSet::new()),
1744 populated_external_types: RefCell::new(DefIdSet::new()),
1745 populated_external_traits: RefCell::new(DefIdSet::new()),
1746 upvar_borrow_map: RefCell::new(FnvHashMap::new()),
1747 extern_const_statics: RefCell::new(DefIdMap::new()),
1748 extern_const_variants: RefCell::new(DefIdMap::new()),
1749 method_map: RefCell::new(FnvHashMap::new()),
1750 dependency_formats: RefCell::new(FnvHashMap::new()),
1751 unboxed_closures: RefCell::new(DefIdMap::new()),
1752 node_lint_levels: RefCell::new(FnvHashMap::new()),
1753 transmute_restrictions: RefCell::new(Vec::new()),
1754 stability: RefCell::new(stability),
1755 capture_modes: capture_modes,
1756 associated_types: RefCell::new(DefIdMap::new()),
1757 selection_cache: traits::SelectionCache::new(),
1758 repr_hint_cache: RefCell::new(DefIdMap::new()),
1762 // Type constructors
1764 // Interns a type/name combination, stores the resulting box in cx.interner,
1765 // and returns the box as cast to an unsafe ptr (see comments for Ty above).
1766 pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: sty<'tcx>) -> Ty<'tcx> {
1767 // Check for primitive types.
1769 ty_err => return mk_err(),
1770 ty_bool => return mk_bool(),
1771 ty_int(i) => return mk_mach_int(i),
1772 ty_uint(u) => return mk_mach_uint(u),
1773 ty_float(f) => return mk_mach_float(f),
1774 ty_char => return mk_char(),
1778 match cx.interner.borrow().get(&st) {
1779 Some(ty) => return *ty,
1783 let flags = FlagComputation::for_sty(&st);
1785 let ty = cx.type_arena.alloc(TyS {
1788 region_depth: flags.depth,
1791 cx.interner.borrow_mut().insert(InternedTy { ty: ty }, ty);
1796 struct FlagComputation {
1799 // maximum depth of any bound region that we have seen thus far
1803 impl FlagComputation {
1804 fn new() -> FlagComputation {
1805 FlagComputation { flags: NO_TYPE_FLAGS, depth: 0 }
1808 fn for_sty(st: &sty) -> FlagComputation {
1809 let mut result = FlagComputation::new();
1814 fn add_flags(&mut self, flags: TypeFlags) {
1815 self.flags = self.flags | flags;
1818 fn add_depth(&mut self, depth: uint) {
1819 if depth > self.depth {
1824 /// Adds the flags/depth from a set of types that appear within the current type, but within a
1826 fn add_bound_computation(&mut self, computation: &FlagComputation) {
1827 self.add_flags(computation.flags);
1829 // The types that contributed to `computation` occured within
1830 // a region binder, so subtract one from the region depth
1831 // within when adding the depth to `self`.
1832 let depth = computation.depth;
1834 self.add_depth(depth - 1);
1838 fn add_sty(&mut self, st: &sty) {
1848 // You might think that we could just return ty_err for
1849 // any type containing ty_err as a component, and get
1850 // rid of the HAS_TY_ERR flag -- likewise for ty_bot (with
1851 // the exception of function types that return bot).
1852 // But doing so caused sporadic memory corruption, and
1853 // neither I (tjc) nor nmatsakis could figure out why,
1854 // so we're doing it this way.
1856 self.add_flags(HAS_TY_ERR)
1859 &ty_param(ref p) => {
1860 if p.space == subst::SelfSpace {
1861 self.add_flags(HAS_SELF);
1863 self.add_flags(HAS_PARAMS);
1867 &ty_unboxed_closure(_, ref region, ref substs) => {
1868 self.add_region(*region);
1869 self.add_substs(substs);
1873 self.add_flags(HAS_TY_INFER)
1876 &ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
1877 self.add_substs(substs);
1880 &ty_trait(box TyTrait { ref principal, ref bounds }) => {
1881 let mut computation = FlagComputation::new();
1882 computation.add_substs(&principal.substs);
1883 self.add_bound_computation(&computation);
1885 self.add_bounds(bounds);
1888 &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
1896 &ty_rptr(r, ref m) => {
1901 &ty_tup(ref ts) => {
1905 &ty_bare_fn(ref f) => {
1906 self.add_fn_sig(&f.sig);
1909 &ty_closure(ref f) => {
1911 RegionTraitStore(r, _) => {
1916 self.add_fn_sig(&f.sig);
1917 self.add_bounds(&f.bounds);
1922 fn add_ty(&mut self, ty: Ty) {
1923 self.add_flags(ty.flags);
1924 self.add_depth(ty.region_depth);
1927 fn add_tys(&mut self, tys: &[Ty]) {
1928 for &ty in tys.iter() {
1933 fn add_fn_sig(&mut self, fn_sig: &FnSig) {
1934 let mut computation = FlagComputation::new();
1936 computation.add_tys(fn_sig.inputs[]);
1938 if let ty::FnConverging(output) = fn_sig.output {
1939 computation.add_ty(output);
1942 self.add_bound_computation(&computation);
1945 fn add_region(&mut self, r: Region) {
1946 self.add_flags(HAS_REGIONS);
1948 ty::ReInfer(_) => { self.add_flags(HAS_RE_INFER); }
1949 ty::ReLateBound(debruijn, _) => {
1950 self.add_flags(HAS_RE_LATE_BOUND);
1951 self.add_depth(debruijn.depth);
1957 fn add_substs(&mut self, substs: &Substs) {
1958 self.add_tys(substs.types.as_slice());
1959 match substs.regions {
1960 subst::ErasedRegions => {}
1961 subst::NonerasedRegions(ref regions) => {
1962 for &r in regions.iter() {
1969 fn add_bounds(&mut self, bounds: &ExistentialBounds) {
1970 self.add_region(bounds.region_bound);
1974 pub fn mk_mach_int<'tcx>(tm: ast::IntTy) -> Ty<'tcx> {
1976 ast::TyI => mk_int(),
1977 ast::TyI8 => mk_i8(),
1978 ast::TyI16 => mk_i16(),
1979 ast::TyI32 => mk_i32(),
1980 ast::TyI64 => mk_i64(),
1984 pub fn mk_mach_uint<'tcx>(tm: ast::UintTy) -> Ty<'tcx> {
1986 ast::TyU => mk_uint(),
1987 ast::TyU8 => mk_u8(),
1988 ast::TyU16 => mk_u16(),
1989 ast::TyU32 => mk_u32(),
1990 ast::TyU64 => mk_u64(),
1994 pub fn mk_mach_float<'tcx>(tm: ast::FloatTy) -> Ty<'tcx> {
1996 ast::TyF32 => mk_f32(),
1997 ast::TyF64 => mk_f64(),
2001 pub fn mk_str<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
2005 pub fn mk_str_slice<'tcx>(cx: &ctxt<'tcx>, r: Region, m: ast::Mutability) -> Ty<'tcx> {
2008 ty: mk_t(cx, ty_str),
2013 pub fn mk_enum<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: Substs<'tcx>) -> Ty<'tcx> {
2014 // take a copy of substs so that we own the vectors inside
2015 mk_t(cx, ty_enum(did, substs))
2018 pub fn mk_uniq<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_uniq(ty)) }
2020 pub fn mk_ptr<'tcx>(cx: &ctxt<'tcx>, tm: mt<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_ptr(tm)) }
2022 pub fn mk_rptr<'tcx>(cx: &ctxt<'tcx>, r: Region, tm: mt<'tcx>) -> Ty<'tcx> {
2023 mk_t(cx, ty_rptr(r, tm))
2026 pub fn mk_mut_rptr<'tcx>(cx: &ctxt<'tcx>, r: Region, ty: Ty<'tcx>) -> Ty<'tcx> {
2027 mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutMutable})
2029 pub fn mk_imm_rptr<'tcx>(cx: &ctxt<'tcx>, r: Region, ty: Ty<'tcx>) -> Ty<'tcx> {
2030 mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutImmutable})
2033 pub fn mk_mut_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2034 mk_ptr(cx, mt {ty: ty, mutbl: ast::MutMutable})
2037 pub fn mk_imm_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2038 mk_ptr(cx, mt {ty: ty, mutbl: ast::MutImmutable})
2041 pub fn mk_nil_ptr<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
2042 mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::MutImmutable})
2045 pub fn mk_vec<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, sz: Option<uint>) -> Ty<'tcx> {
2046 mk_t(cx, ty_vec(ty, sz))
2049 pub fn mk_slice<'tcx>(cx: &ctxt<'tcx>, r: Region, tm: mt<'tcx>) -> Ty<'tcx> {
2052 ty: mk_vec(cx, tm.ty, None),
2057 pub fn mk_tup<'tcx>(cx: &ctxt<'tcx>, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
2058 mk_t(cx, ty_tup(ts))
2061 pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
2062 mk_tup(cx, Vec::new())
2065 pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, fty: ClosureTy<'tcx>) -> Ty<'tcx> {
2066 mk_t(cx, ty_closure(box fty))
2069 pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, fty: BareFnTy<'tcx>) -> Ty<'tcx> {
2070 mk_t(cx, ty_bare_fn(fty))
2073 pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
2074 input_tys: &[Ty<'tcx>],
2075 output: Ty<'tcx>) -> Ty<'tcx> {
2076 let input_args = input_tys.iter().map(|ty| *ty).collect();
2079 fn_style: ast::NormalFn,
2083 output: ty::FnConverging(output),
2090 pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
2091 principal: ty::TraitRef<'tcx>,
2092 bounds: ExistentialBounds)
2094 // take a copy of substs so that we own the vectors inside
2095 let inner = box TyTrait {
2096 principal: principal,
2099 mk_t(cx, ty_trait(inner))
2102 pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId,
2103 substs: Substs<'tcx>) -> Ty<'tcx> {
2104 // take a copy of substs so that we own the vectors inside
2105 mk_t(cx, ty_struct(struct_id, substs))
2108 pub fn mk_unboxed_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId,
2109 region: Region, substs: Substs<'tcx>)
2111 mk_t(cx, ty_unboxed_closure(closure_id, region, substs))
2114 pub fn mk_var<'tcx>(cx: &ctxt<'tcx>, v: TyVid) -> Ty<'tcx> {
2115 mk_infer(cx, TyVar(v))
2118 pub fn mk_int_var<'tcx>(cx: &ctxt<'tcx>, v: IntVid) -> Ty<'tcx> {
2119 mk_infer(cx, IntVar(v))
2122 pub fn mk_float_var<'tcx>(cx: &ctxt<'tcx>, v: FloatVid) -> Ty<'tcx> {
2123 mk_infer(cx, FloatVar(v))
2126 pub fn mk_infer<'tcx>(cx: &ctxt<'tcx>, it: InferTy) -> Ty<'tcx> {
2127 mk_t(cx, ty_infer(it))
2130 pub fn mk_param<'tcx>(cx: &ctxt<'tcx>, space: subst::ParamSpace,
2131 n: uint, k: DefId) -> Ty<'tcx> {
2132 mk_t(cx, ty_param(ParamTy { space: space, idx: n, def_id: k }))
2135 pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) -> Ty<'tcx> {
2136 mk_param(cx, subst::SelfSpace, 0, did)
2139 pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'tcx> {
2140 mk_param(cx, def.space, def.index, def.def_id)
2143 pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
2145 pub fn walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>|) {
2146 maybe_walk_ty(ty, |ty| { f(ty); true });
2149 pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) {
2154 ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
2155 ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
2156 ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
2157 ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
2158 maybe_walk_ty(tm.ty, f);
2160 ty_trait(box TyTrait { ref principal, .. }) => {
2161 for subty in principal.substs.types.iter() {
2162 maybe_walk_ty(*subty, |x| f(x));
2165 ty_enum(_, ref substs) |
2166 ty_struct(_, ref substs) |
2167 ty_unboxed_closure(_, _, ref substs) => {
2168 for subty in substs.types.iter() {
2169 maybe_walk_ty(*subty, |x| f(x));
2172 ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
2173 ty_bare_fn(ref ft) => {
2174 for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
2175 if let ty::FnConverging(output) = ft.sig.output {
2176 maybe_walk_ty(output, f);
2179 ty_closure(ref ft) => {
2180 for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
2181 if let ty::FnConverging(output) = ft.sig.output {
2182 maybe_walk_ty(output, f);
2188 // Folds types from the bottom up.
2189 pub fn fold_ty<'tcx>(cx: &ctxt<'tcx>, t0: Ty<'tcx>,
2190 fldop: |Ty<'tcx>| -> Ty<'tcx>)
2192 let mut f = ty_fold::BottomUpFolder {tcx: cx, fldop: fldop};
2197 pub fn new(space: subst::ParamSpace,
2201 ParamTy { space: space, idx: index, def_id: def_id }
2204 pub fn for_self(trait_def_id: ast::DefId) -> ParamTy {
2205 ParamTy::new(subst::SelfSpace, 0, trait_def_id)
2208 pub fn for_def(def: &TypeParameterDef) -> ParamTy {
2209 ParamTy::new(def.space, def.index, def.def_id)
2212 pub fn to_ty<'tcx>(self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
2213 ty::mk_param(tcx, self.space, self.idx, self.def_id)
2216 pub fn is_self(&self) -> bool {
2217 self.space == subst::SelfSpace && self.idx == 0
2221 impl<'tcx> ItemSubsts<'tcx> {
2222 pub fn empty() -> ItemSubsts<'tcx> {
2223 ItemSubsts { substs: Substs::empty() }
2226 pub fn is_noop(&self) -> bool {
2227 self.substs.is_noop()
2231 impl<'tcx> ParamBounds<'tcx> {
2232 pub fn empty() -> ParamBounds<'tcx> {
2234 builtin_bounds: empty_builtin_bounds(),
2235 trait_bounds: Vec::new(),
2236 region_bounds: Vec::new(),
2243 pub fn type_is_nil(ty: Ty) -> bool {
2245 ty_tup(ref tys) => tys.is_empty(),
2250 pub fn type_is_error(ty: Ty) -> bool {
2251 ty.flags.intersects(HAS_TY_ERR)
2254 pub fn type_needs_subst(ty: Ty) -> bool {
2255 ty.flags.intersects(NEEDS_SUBST)
2258 pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
2259 tref.substs.types.any(|&ty| type_is_error(ty))
2262 pub fn type_is_ty_var(ty: Ty) -> bool {
2264 ty_infer(TyVar(_)) => true,
2269 pub fn type_is_bool(ty: Ty) -> bool { ty.sty == ty_bool }
2271 pub fn type_is_self(ty: Ty) -> bool {
2273 ty_param(ref p) => p.space == subst::SelfSpace,
2278 fn type_is_slice(ty: Ty) -> bool {
2280 ty_ptr(mt) | ty_rptr(_, mt) => match mt.ty.sty {
2281 ty_vec(_, None) | ty_str => true,
2288 pub fn type_is_vec(ty: Ty) -> bool {
2291 ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..}) |
2292 ty_uniq(ty) => match ty.sty {
2293 ty_vec(_, None) => true,
2300 pub fn type_is_structural(ty: Ty) -> bool {
2302 ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
2303 ty_vec(_, Some(_)) | ty_unboxed_closure(..) => true,
2304 _ => type_is_slice(ty) | type_is_trait(ty)
2308 pub fn type_is_simd(cx: &ctxt, ty: Ty) -> bool {
2310 ty_struct(did, _) => lookup_simd(cx, did),
2315 pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2317 ty_vec(ty, _) => ty,
2318 ty_str => mk_mach_uint(ast::TyU8),
2319 ty_open(ty) => sequence_element_type(cx, ty),
2320 _ => cx.sess.bug(format!("sequence_element_type called on non-sequence value: {}",
2321 ty_to_string(cx, ty)).as_slice()),
2325 pub fn simd_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2327 ty_struct(did, ref substs) => {
2328 let fields = lookup_struct_fields(cx, did);
2329 lookup_field_type(cx, did, fields[0].id, substs)
2331 _ => panic!("simd_type called on invalid type")
2335 pub fn simd_size(cx: &ctxt, ty: Ty) -> uint {
2337 ty_struct(did, _) => {
2338 let fields = lookup_struct_fields(cx, did);
2341 _ => panic!("simd_size called on invalid type")
2345 pub fn type_is_region_ptr(ty: Ty) -> bool {
2347 ty_rptr(..) => true,
2352 pub fn type_is_unsafe_ptr(ty: Ty) -> bool {
2354 ty_ptr(_) => return true,
2359 pub fn type_is_unique(ty: Ty) -> bool {
2361 ty_uniq(_) => match ty.sty {
2362 ty_trait(..) => false,
2369 pub fn type_is_fat_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2371 ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..})
2372 | ty_uniq(ty) if !type_is_sized(cx, ty) => true,
2378 A scalar type is one that denotes an atomic datum, with no sub-components.
2379 (A ty_ptr is scalar because it represents a non-managed pointer, so its
2380 contents are abstract to rustc.)
2382 pub fn type_is_scalar(ty: Ty) -> bool {
2384 ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
2385 ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) |
2386 ty_bare_fn(..) | ty_ptr(_) => true,
2387 ty_tup(ref tys) if tys.is_empty() => true,
2392 /// Returns true if this type is a floating point type and false otherwise.
2393 pub fn type_is_floating_point(ty: Ty) -> bool {
2395 ty_float(_) => true,
2400 pub fn type_needs_drop<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2401 type_contents(cx, ty).needs_drop(cx)
2404 // Some things don't need cleanups during unwinding because the
2405 // task can free them all at once later. Currently only things
2406 // that only contain scalars and shared boxes can avoid unwind
2408 pub fn type_needs_unwind_cleanup<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2409 return memoized(&cx.needs_unwind_cleanup_cache, ty, |ty| {
2410 type_needs_unwind_cleanup_(cx, ty, &mut FnvHashSet::new())
2413 fn type_needs_unwind_cleanup_<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>,
2414 tycache: &mut FnvHashSet<Ty<'tcx>>) -> bool {
2415 // Prevent infinite recursion
2416 if !tycache.insert(ty) {
2420 let mut needs_unwind_cleanup = false;
2421 maybe_walk_ty(ty, |ty| {
2422 needs_unwind_cleanup |= match ty.sty {
2423 ty_bool | ty_int(_) | ty_uint(_) |
2424 ty_float(_) | ty_tup(_) | ty_ptr(_) => false,
2426 ty_enum(did, ref substs) =>
2427 enum_variants(cx, did).iter().any(|v|
2428 v.args.iter().any(|aty| {
2429 let t = aty.subst(cx, substs);
2430 type_needs_unwind_cleanup_(cx, t, tycache)
2436 !needs_unwind_cleanup
2438 needs_unwind_cleanup
2443 * Type contents is how the type checker reasons about kinds.
2444 * They track what kinds of things are found within a type. You can
2445 * think of them as kind of an "anti-kind". They track the kinds of values
2446 * and thinks that are contained in types. Having a larger contents for
2447 * a type tends to rule that type *out* from various kinds. For example,
2448 * a type that contains a reference is not sendable.
2450 * The reason we compute type contents and not kinds is that it is
2451 * easier for me (nmatsakis) to think about what is contained within
2452 * a type than to think about what is *not* contained within a type.
2455 pub struct TypeContents {
2459 macro_rules! def_type_content_sets(
2460 (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
2461 #[allow(non_snake_case)]
2463 use middle::ty::TypeContents;
2465 #[allow(non_upper_case_globals)]
2466 pub const $name: TypeContents = TypeContents { bits: $bits };
2472 def_type_content_sets!(
2474 None = 0b0000_0000__0000_0000__0000,
2476 // Things that are interior to the value (first nibble):
2477 InteriorUnsized = 0b0000_0000__0000_0000__0001,
2478 InteriorUnsafe = 0b0000_0000__0000_0000__0010,
2479 // InteriorAll = 0b00000000__00000000__1111,
2481 // Things that are owned by the value (second and third nibbles):
2482 OwnsOwned = 0b0000_0000__0000_0001__0000,
2483 OwnsDtor = 0b0000_0000__0000_0010__0000,
2484 OwnsManaged /* see [1] below */ = 0b0000_0000__0000_0100__0000,
2485 OwnsAffine = 0b0000_0000__0000_1000__0000,
2486 OwnsAll = 0b0000_0000__1111_1111__0000,
2488 // Things that are reachable by the value in any way (fourth nibble):
2489 ReachesBorrowed = 0b0000_0010__0000_0000__0000,
2490 // ReachesManaged /* see [1] below */ = 0b0000_0100__0000_0000__0000,
2491 ReachesMutable = 0b0000_1000__0000_0000__0000,
2492 ReachesFfiUnsafe = 0b0010_0000__0000_0000__0000,
2493 ReachesAll = 0b0011_1111__0000_0000__0000,
2495 // Things that cause values to *move* rather than *copy*. This
2496 // is almost the same as the `Copy` trait, but for managed
2497 // data -- atm, we consider managed data to copy, not move,
2498 // but it does not impl Copy as a pure memcpy is not good
2500 Moves = 0b0000_0000__0000_1011__0000,
2502 // Things that mean drop glue is necessary
2503 NeedsDrop = 0b0000_0000__0000_0111__0000,
2505 // Things that prevent values from being considered sized
2506 Nonsized = 0b0000_0000__0000_0000__0001,
2508 // Things that make values considered not POD (would be same
2509 // as `Moves`, but for the fact that managed data `@` is
2510 // not considered POD)
2511 Noncopy = 0b0000_0000__0000_1111__0000,
2513 // Bits to set when a managed value is encountered
2515 // [1] Do not set the bits TC::OwnsManaged or
2516 // TC::ReachesManaged directly, instead reference
2517 // TC::Managed to set them both at once.
2518 Managed = 0b0000_0100__0000_0100__0000,
2521 All = 0b1111_1111__1111_1111__1111
2526 pub fn when(&self, cond: bool) -> TypeContents {
2527 if cond {*self} else {TC::None}
2530 pub fn intersects(&self, tc: TypeContents) -> bool {
2531 (self.bits & tc.bits) != 0
2534 pub fn owns_managed(&self) -> bool {
2535 self.intersects(TC::OwnsManaged)
2538 pub fn owns_owned(&self) -> bool {
2539 self.intersects(TC::OwnsOwned)
2542 pub fn is_sized(&self, _: &ctxt) -> bool {
2543 !self.intersects(TC::Nonsized)
2546 pub fn interior_unsafe(&self) -> bool {
2547 self.intersects(TC::InteriorUnsafe)
2550 pub fn interior_unsized(&self) -> bool {
2551 self.intersects(TC::InteriorUnsized)
2554 pub fn moves_by_default(&self, _: &ctxt) -> bool {
2555 self.intersects(TC::Moves)
2558 pub fn needs_drop(&self, _: &ctxt) -> bool {
2559 self.intersects(TC::NeedsDrop)
2562 /// Includes only those bits that still apply when indirected through a `Box` pointer
2563 pub fn owned_pointer(&self) -> TypeContents {
2565 *self & (TC::OwnsAll | TC::ReachesAll))
2568 /// Includes only those bits that still apply when indirected through a reference (`&`)
2569 pub fn reference(&self, bits: TypeContents) -> TypeContents {
2571 *self & TC::ReachesAll)
2574 /// Includes only those bits that still apply when indirected through a managed pointer (`@`)
2575 pub fn managed_pointer(&self) -> TypeContents {
2577 *self & TC::ReachesAll)
2580 /// Includes only those bits that still apply when indirected through an unsafe pointer (`*`)
2581 pub fn unsafe_pointer(&self) -> TypeContents {
2582 *self & TC::ReachesAll
2585 pub fn union<T>(v: &[T], f: |&T| -> TypeContents) -> TypeContents {
2586 v.iter().fold(TC::None, |tc, ty| tc | f(ty))
2589 pub fn has_dtor(&self) -> bool {
2590 self.intersects(TC::OwnsDtor)
2594 impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
2595 fn bitor(&self, other: &TypeContents) -> TypeContents {
2596 TypeContents {bits: self.bits | other.bits}
2600 impl ops::BitAnd<TypeContents,TypeContents> for TypeContents {
2601 fn bitand(&self, other: &TypeContents) -> TypeContents {
2602 TypeContents {bits: self.bits & other.bits}
2606 impl ops::Sub<TypeContents,TypeContents> for TypeContents {
2607 fn sub(&self, other: &TypeContents) -> TypeContents {
2608 TypeContents {bits: self.bits & !other.bits}
2612 impl fmt::Show for TypeContents {
2613 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2614 write!(f, "TypeContents({:b})", self.bits)
2618 pub fn type_interior_is_unsafe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2619 type_contents(cx, ty).interior_unsafe()
2622 pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
2623 return memoized(&cx.tc_cache, ty, |ty| {
2624 tc_ty(cx, ty, &mut FnvHashMap::new())
2627 fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
2629 cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
2631 // Subtle: Note that we are *not* using cx.tc_cache here but rather a
2632 // private cache for this walk. This is needed in the case of cyclic
2635 // struct List { next: Box<Option<List>>, ... }
2637 // When computing the type contents of such a type, we wind up deeply
2638 // recursing as we go. So when we encounter the recursive reference
2639 // to List, we temporarily use TC::None as its contents. Later we'll
2640 // patch up the cache with the correct value, once we've computed it
2641 // (this is basically a co-inductive process, if that helps). So in
2642 // the end we'll compute TC::OwnsOwned, in this case.
2644 // The problem is, as we are doing the computation, we will also
2645 // compute an *intermediate* contents for, e.g., Option<List> of
2646 // TC::None. This is ok during the computation of List itself, but if
2647 // we stored this intermediate value into cx.tc_cache, then later
2648 // requests for the contents of Option<List> would also yield TC::None
2649 // which is incorrect. This value was computed based on the crutch
2650 // value for the type contents of list. The correct value is
2651 // TC::OwnsOwned. This manifested as issue #4821.
2652 match cache.get(&ty) {
2653 Some(tc) => { return *tc; }
2656 match cx.tc_cache.borrow().get(&ty) { // Must check both caches!
2657 Some(tc) => { return *tc; }
2660 cache.insert(ty, TC::None);
2662 let result = match ty.sty {
2663 // uint and int are ffi-unsafe
2664 ty_uint(ast::TyU) | ty_int(ast::TyI) => {
2665 TC::ReachesFfiUnsafe
2668 // Scalar and unique types are sendable, and durable
2669 ty_infer(ty::SkolemizedIntTy(_)) |
2670 ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
2671 ty_bare_fn(_) | ty::ty_char => {
2675 ty_closure(ref c) => {
2676 closure_contents(cx, &**c) | TC::ReachesFfiUnsafe
2680 TC::ReachesFfiUnsafe | match typ.sty {
2681 ty_str => TC::OwnsOwned,
2682 _ => tc_ty(cx, typ, cache).owned_pointer(),
2686 ty_trait(box TyTrait { bounds, .. }) => {
2687 object_contents(cx, bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
2691 tc_ty(cx, mt.ty, cache).unsafe_pointer()
2694 ty_rptr(r, ref mt) => {
2695 TC::ReachesFfiUnsafe | match mt.ty.sty {
2696 ty_str => borrowed_contents(r, ast::MutImmutable),
2697 ty_vec(..) => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
2698 _ => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
2702 ty_vec(ty, Some(_)) => {
2703 tc_ty(cx, ty, cache)
2706 ty_vec(ty, None) => {
2707 tc_ty(cx, ty, cache) | TC::Nonsized
2709 ty_str => TC::Nonsized,
2711 ty_struct(did, ref substs) => {
2712 let flds = struct_fields(cx, did, substs);
2714 TypeContents::union(flds.as_slice(),
2715 |f| tc_mt(cx, f.mt, cache));
2717 if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) {
2718 res = res | TC::ReachesFfiUnsafe;
2721 if ty::has_dtor(cx, did) {
2722 res = res | TC::OwnsDtor;
2724 apply_lang_items(cx, did, res)
2727 ty_unboxed_closure(did, r, ref substs) => {
2728 // FIXME(#14449): `borrowed_contents` below assumes `&mut`
2730 let upvars = unboxed_closure_upvars(cx, did, substs);
2731 TypeContents::union(upvars.as_slice(),
2732 |f| tc_ty(cx, f.ty, cache)) |
2733 borrowed_contents(r, MutMutable)
2736 ty_tup(ref tys) => {
2737 TypeContents::union(tys.as_slice(),
2738 |ty| tc_ty(cx, *ty, cache))
2741 ty_enum(did, ref substs) => {
2742 let variants = substd_enum_variants(cx, did, substs);
2744 TypeContents::union(variants.as_slice(), |variant| {
2745 TypeContents::union(variant.args.as_slice(),
2747 tc_ty(cx, *arg_ty, cache)
2751 if ty::has_dtor(cx, did) {
2752 res = res | TC::OwnsDtor;
2755 if variants.len() != 0 {
2756 let repr_hints = lookup_repr_hints(cx, did);
2757 if repr_hints.len() > 1 {
2758 // this is an error later on, but this type isn't safe
2759 res = res | TC::ReachesFfiUnsafe;
2762 match repr_hints.as_slice().get(0) {
2763 Some(h) => if !h.is_ffi_safe() {
2764 res = res | TC::ReachesFfiUnsafe;
2768 res = res | TC::ReachesFfiUnsafe;
2770 // We allow ReprAny enums if they are eligible for
2771 // the nullable pointer optimization and the
2772 // contained type is an `extern fn`
2774 if variants.len() == 2 {
2775 let mut data_idx = 0;
2777 if variants[0].args.len() == 0 {
2781 if variants[data_idx].args.len() == 1 {
2782 match variants[data_idx].args[0].sty {
2783 ty_bare_fn(..) => { res = res - TC::ReachesFfiUnsafe; }
2793 apply_lang_items(cx, did, res)
2797 // We only ever ask for the kind of types that are defined in
2798 // the current crate; therefore, the only type parameters that
2799 // could be in scope are those defined in the current crate.
2800 // If this assertion fails, it is likely because of a
2801 // failure of the cross-crate inlining code to translate a
2803 assert_eq!(p.def_id.krate, ast::LOCAL_CRATE);
2805 let ty_param_defs = cx.ty_param_defs.borrow();
2806 let tp_def = &(*ty_param_defs)[p.def_id.node];
2807 kind_bounds_to_contents(
2809 tp_def.bounds.builtin_bounds,
2810 tp_def.bounds.trait_bounds.as_slice())
2814 // This occurs during coherence, but shouldn't occur at other
2820 let result = tc_ty(cx, ty, cache);
2821 assert!(!result.is_sized(cx))
2822 result.unsafe_pointer() | TC::Nonsized
2826 cx.sess.bug("asked to compute contents of error type");
2830 cache.insert(ty, result);
2834 fn tc_mt<'tcx>(cx: &ctxt<'tcx>,
2836 cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
2838 let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable);
2839 mc | tc_ty(cx, mt.ty, cache)
2842 fn apply_lang_items(cx: &ctxt,
2847 if Some(did) == cx.lang_items.managed_bound() {
2849 } else if Some(did) == cx.lang_items.no_copy_bound() {
2851 } else if Some(did) == cx.lang_items.unsafe_type() {
2852 tc | TC::InteriorUnsafe
2858 /// Type contents due to containing a reference with the region `region` and borrow kind `bk`
2859 fn borrowed_contents(region: ty::Region,
2860 mutbl: ast::Mutability)
2862 let b = match mutbl {
2863 ast::MutMutable => TC::ReachesMutable | TC::OwnsAffine,
2864 ast::MutImmutable => TC::None,
2866 b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
2869 fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents {
2870 // Closure contents are just like trait contents, but with potentially
2872 let st = object_contents(cx, cty.bounds);
2874 let st = match cty.store {
2878 RegionTraitStore(r, mutbl) => {
2879 st.reference(borrowed_contents(r, mutbl))
2883 // This also prohibits "@once fn" from being copied, which allows it to
2884 // be called. Neither way really makes much sense.
2885 let ot = match cty.onceness {
2886 ast::Once => TC::OwnsAffine,
2887 ast::Many => TC::None,
2893 fn object_contents(cx: &ctxt,
2894 bounds: ExistentialBounds)
2896 // These are the type contents of the (opaque) interior
2897 kind_bounds_to_contents(cx, bounds.builtin_bounds, &[])
2900 fn kind_bounds_to_contents<'tcx>(cx: &ctxt<'tcx>,
2901 bounds: BuiltinBounds,
2902 traits: &[Rc<TraitRef<'tcx>>])
2904 let _i = indenter();
2905 let mut tc = TC::All;
2906 each_inherited_builtin_bound(cx, bounds, traits, |bound| {
2907 tc = tc - match bound {
2908 BoundSync | BoundSend => TC::None,
2909 BoundSized => TC::Nonsized,
2910 BoundCopy => TC::Noncopy,
2915 // Iterates over all builtin bounds on the type parameter def, including
2916 // those inherited from traits with builtin-kind-supertraits.
2917 fn each_inherited_builtin_bound<'tcx>(cx: &ctxt<'tcx>,
2918 bounds: BuiltinBounds,
2919 traits: &[Rc<TraitRef<'tcx>>],
2920 f: |BuiltinBound|) {
2921 for bound in bounds.iter() {
2925 each_bound_trait_and_supertraits(cx, traits, |trait_ref| {
2926 let trait_def = lookup_trait_def(cx, trait_ref.def_id);
2927 for bound in trait_def.bounds.builtin_bounds.iter() {
2936 pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2937 type_contents(cx, ty).moves_by_default(cx)
2940 pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2941 !type_contents(cx, ty).intersects(TC::ReachesFfiUnsafe)
2944 // True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2945 pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
2946 fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
2947 r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
2948 debug!("type_requires({}, {})?",
2949 ::util::ppaux::ty_to_string(cx, r_ty),
2950 ::util::ppaux::ty_to_string(cx, ty));
2952 let r = r_ty == ty || subtypes_require(cx, seen, r_ty, ty);
2954 debug!("type_requires({}, {})? {}",
2955 ::util::ppaux::ty_to_string(cx, r_ty),
2956 ::util::ppaux::ty_to_string(cx, ty),
2961 fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
2962 r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
2963 debug!("subtypes_require({}, {})?",
2964 ::util::ppaux::ty_to_string(cx, r_ty),
2965 ::util::ppaux::ty_to_string(cx, ty));
2967 let r = match ty.sty {
2968 // fixed length vectors need special treatment compared to
2969 // normal vectors, since they don't necessarily have the
2970 // possibility to have length zero.
2971 ty_vec(_, Some(0)) => false, // don't need no contents
2972 ty_vec(ty, Some(_)) => type_requires(cx, seen, r_ty, ty),
2985 ty_vec(_, None) => {
2988 ty_uniq(typ) | ty_open(typ) => {
2989 type_requires(cx, seen, r_ty, typ)
2991 ty_rptr(_, ref mt) => {
2992 type_requires(cx, seen, r_ty, mt.ty)
2996 false // unsafe ptrs can always be NULL
3003 ty_struct(ref did, _) if seen.contains(did) => {
3007 ty_struct(did, ref substs) => {
3009 let fields = struct_fields(cx, did, substs);
3010 let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
3011 seen.pop().unwrap();
3015 ty_unboxed_closure(did, _, ref substs) => {
3016 let upvars = unboxed_closure_upvars(cx, did, substs);
3017 upvars.iter().any(|f| type_requires(cx, seen, r_ty, f.ty))
3021 ts.iter().any(|ty| type_requires(cx, seen, r_ty, *ty))
3024 ty_enum(ref did, _) if seen.contains(did) => {
3028 ty_enum(did, ref substs) => {
3030 let vs = enum_variants(cx, did);
3031 let r = !vs.is_empty() && vs.iter().all(|variant| {
3032 variant.args.iter().any(|aty| {
3033 let sty = aty.subst(cx, substs);
3034 type_requires(cx, seen, r_ty, sty)
3037 seen.pop().unwrap();
3042 debug!("subtypes_require({}, {})? {}",
3043 ::util::ppaux::ty_to_string(cx, r_ty),
3044 ::util::ppaux::ty_to_string(cx, ty),
3050 let mut seen = Vec::new();
3051 !subtypes_require(cx, &mut seen, r_ty, r_ty)
3054 /// Describes whether a type is representable. For types that are not
3055 /// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
3056 /// distinguish between types that are recursive with themselves and types that
3057 /// contain a different recursive type. These cases can therefore be treated
3058 /// differently when reporting errors.
3060 /// The ordering of the cases is significant. They are sorted so that cmp::max
3061 /// will keep the "more erroneous" of two values.
3062 #[deriving(PartialOrd, Ord, Eq, PartialEq, Show)]
3063 pub enum Representability {
3069 /// Check whether a type is representable. This means it cannot contain unboxed
3070 /// structural recursion. This check is needed for structs and enums.
3071 pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
3072 -> Representability {
3074 // Iterate until something non-representable is found
3075 fn find_nonrepresentable<'tcx, It: Iterator<Ty<'tcx>>>(cx: &ctxt<'tcx>, sp: Span,
3076 seen: &mut Vec<Ty<'tcx>>,
3078 -> Representability {
3079 iter.fold(Representable,
3080 |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty)))
3083 fn are_inner_types_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
3084 seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
3085 -> Representability {
3088 find_nonrepresentable(cx, sp, seen, ts.iter().map(|ty| *ty))
3090 // Fixed-length vectors.
3091 // FIXME(#11924) Behavior undecided for zero-length vectors.
3092 ty_vec(ty, Some(_)) => {
3093 is_type_structurally_recursive(cx, sp, seen, ty)
3095 ty_struct(did, ref substs) => {
3096 let fields = struct_fields(cx, did, substs);
3097 find_nonrepresentable(cx, sp, seen, fields.iter().map(|f| f.mt.ty))
3099 ty_enum(did, ref substs) => {
3100 let vs = enum_variants(cx, did);
3101 let iter = vs.iter()
3102 .flat_map(|variant| { variant.args.iter() })
3103 .map(|aty| { aty.subst_spanned(cx, substs, Some(sp)) });
3105 find_nonrepresentable(cx, sp, seen, iter)
3107 ty_unboxed_closure(did, _, ref substs) => {
3108 let upvars = unboxed_closure_upvars(cx, did, substs);
3109 find_nonrepresentable(cx, sp, seen, upvars.iter().map(|f| f.ty))
3115 fn same_struct_or_enum_def_id(ty: Ty, did: DefId) -> bool {
3117 ty_struct(ty_did, _) | ty_enum(ty_did, _) => {
3124 fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
3125 match (&a.sty, &b.sty) {
3126 (&ty_struct(did_a, ref substs_a), &ty_struct(did_b, ref substs_b)) |
3127 (&ty_enum(did_a, ref substs_a), &ty_enum(did_b, ref substs_b)) => {
3132 let types_a = substs_a.types.get_slice(subst::TypeSpace);
3133 let types_b = substs_b.types.get_slice(subst::TypeSpace);
3135 let pairs = types_a.iter().zip(types_b.iter());
3137 pairs.all(|(&a, &b)| same_type(a, b))
3145 // Does the type `ty` directly (without indirection through a pointer)
3146 // contain any types on stack `seen`?
3147 fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
3148 seen: &mut Vec<Ty<'tcx>>,
3149 ty: Ty<'tcx>) -> Representability {
3150 debug!("is_type_structurally_recursive: {}",
3151 ::util::ppaux::ty_to_string(cx, ty));
3154 ty_struct(did, _) | ty_enum(did, _) => {
3156 // Iterate through stack of previously seen types.
3157 let mut iter = seen.iter();
3159 // The first item in `seen` is the type we are actually curious about.
3160 // We want to return SelfRecursive if this type contains itself.
3161 // It is important that we DON'T take generic parameters into account
3162 // for this check, so that Bar<T> in this example counts as SelfRecursive:
3165 // struct Bar<T> { x: Bar<Foo> }
3168 Some(&seen_type) => {
3169 if same_struct_or_enum_def_id(seen_type, did) {
3170 debug!("SelfRecursive: {} contains {}",
3171 ::util::ppaux::ty_to_string(cx, seen_type),
3172 ::util::ppaux::ty_to_string(cx, ty));
3173 return SelfRecursive;
3179 // We also need to know whether the first item contains other types that
3180 // are structurally recursive. If we don't catch this case, we will recurse
3181 // infinitely for some inputs.
3183 // It is important that we DO take generic parameters into account here,
3184 // so that code like this is considered SelfRecursive, not ContainsRecursive:
3186 // struct Foo { Option<Option<Foo>> }
3188 for &seen_type in iter {
3189 if same_type(ty, seen_type) {
3190 debug!("ContainsRecursive: {} contains {}",
3191 ::util::ppaux::ty_to_string(cx, seen_type),
3192 ::util::ppaux::ty_to_string(cx, ty));
3193 return ContainsRecursive;
3198 // For structs and enums, track all previously seen types by pushing them
3199 // onto the 'seen' stack.
3201 let out = are_inner_types_recursive(cx, sp, seen, ty);
3206 // No need to push in other cases.
3207 are_inner_types_recursive(cx, sp, seen, ty)
3212 debug!("is_type_representable: {}",
3213 ::util::ppaux::ty_to_string(cx, ty));
3215 // To avoid a stack overflow when checking an enum variant or struct that
3216 // contains a different, structurally recursive type, maintain a stack
3217 // of seen types and check recursion for each of them (issues #3008, #3779).
3218 let mut seen: Vec<Ty> = Vec::new();
3219 let r = is_type_structurally_recursive(cx, sp, &mut seen, ty);
3220 debug!("is_type_representable: {} is {}",
3221 ::util::ppaux::ty_to_string(cx, ty), r);
3225 pub fn type_is_trait(ty: Ty) -> bool {
3226 type_trait_info(ty).is_some()
3229 pub fn type_trait_info<'tcx>(ty: Ty<'tcx>) -> Option<&'tcx TyTrait<'tcx>> {
3231 ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match ty.sty {
3232 ty_trait(ref t) => Some(&**t),
3235 ty_trait(ref t) => Some(&**t),
3240 pub fn type_is_integral(ty: Ty) -> bool {
3242 ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
3247 pub fn type_is_skolemized(ty: Ty) -> bool {
3249 ty_infer(SkolemizedTy(_)) => true,
3250 ty_infer(SkolemizedIntTy(_)) => true,
3255 pub fn type_is_uint(ty: Ty) -> bool {
3257 ty_infer(IntVar(_)) | ty_uint(ast::TyU) => true,
3262 pub fn type_is_char(ty: Ty) -> bool {
3269 pub fn type_is_bare_fn(ty: Ty) -> bool {
3271 ty_bare_fn(..) => true,
3276 pub fn type_is_fp(ty: Ty) -> bool {
3278 ty_infer(FloatVar(_)) | ty_float(_) => true,
3283 pub fn type_is_numeric(ty: Ty) -> bool {
3284 return type_is_integral(ty) || type_is_fp(ty);
3287 pub fn type_is_signed(ty: Ty) -> bool {
3294 pub fn type_is_machine(ty: Ty) -> bool {
3296 ty_int(ast::TyI) | ty_uint(ast::TyU) => false,
3297 ty_int(..) | ty_uint(..) | ty_float(..) => true,
3302 // Is the type's representation size known at compile time?
3303 pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
3304 type_contents(cx, ty).is_sized(cx)
3307 pub fn lltype_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
3310 _ => type_contents(cx, ty).is_sized(cx)
3314 // Return the smallest part of `ty` which is unsized. Fails if `ty` is sized.
3315 // 'Smallest' here means component of the static representation of the type; not
3316 // the size of an object at runtime.
3317 pub fn unsized_part_of_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
3319 ty_str | ty_trait(..) | ty_vec(..) => ty,
3320 ty_struct(def_id, ref substs) => {
3321 let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
3322 .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
3323 // Exactly one of the fields must be unsized.
3324 assert!(unsized_fields.len() == 1)
3326 unsized_part_of_type(cx, unsized_fields[0])
3329 assert!(type_is_sized(cx, ty),
3330 "unsized_part_of_type failed even though ty is unsized");
3331 panic!("called unsized_part_of_type with sized ty");
3336 // Whether a type is enum like, that is an enum type with only nullary
3338 pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool {
3340 ty_enum(did, _) => {
3341 let variants = enum_variants(cx, did);
3342 if variants.len() == 0 {
3345 variants.iter().all(|v| v.args.len() == 0)
3352 // Returns the type and mutability of *ty.
3354 // The parameter `explicit` indicates if this is an *explicit* dereference.
3355 // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
3356 pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
3361 mutbl: ast::MutImmutable,
3364 ty_rptr(_, mt) => Some(mt),
3365 ty_ptr(mt) if explicit => Some(mt),
3370 pub fn close_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
3372 ty_open(ty) => mk_rptr(cx, ReStatic, mt {ty: ty, mutbl:ast::MutImmutable}),
3373 _ => cx.sess.bug(format!("Trying to close a non-open type {}",
3374 ty_to_string(cx, ty)).as_slice())
3378 pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
3381 ty_rptr(_, mt) |ty_ptr(mt) => mt.ty,
3386 // Extract the unsized type in an open type (or just return ty if it is not open).
3387 pub fn unopen_type<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
3394 // Returns the type of ty[i]
3395 pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
3397 ty_vec(ty, _) => Some(ty),
3402 // Returns the type of elements contained within an 'array-like' type.
3403 // This is exactly the same as the above, except it supports strings,
3404 // which can't actually be indexed.
3405 pub fn array_element_ty<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
3407 ty_vec(ty, _) => Some(ty),
3408 ty_str => Some(mk_u8()),
3413 /// Returns the type of element at index `i` in tuple or tuple-like type `t`.
3414 /// For an enum `t`, `variant` is None only if `t` is a univariant enum.
3415 pub fn positional_element_ty<'tcx>(cx: &ctxt<'tcx>,
3418 variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
3420 match (&ty.sty, variant) {
3421 (&ty_tup(ref v), None) => v.as_slice().get(i).map(|&t| t),
3424 (&ty_struct(def_id, ref substs), None) => lookup_struct_fields(cx, def_id)
3426 .map(|&t|lookup_item_type(cx, t.id).ty.subst(cx, substs)),
3428 (&ty_enum(def_id, ref substs), Some(variant_def_id)) => {
3429 let variant_info = enum_variant_with_id(cx, def_id, variant_def_id);
3430 variant_info.args.as_slice().get(i).map(|t|t.subst(cx, substs))
3433 (&ty_enum(def_id, ref substs), None) => {
3434 assert!(enum_is_univariant(cx, def_id));
3435 let enum_variants = enum_variants(cx, def_id);
3436 let variant_info = &(*enum_variants)[0];
3437 variant_info.args.as_slice().get(i).map(|t|t.subst(cx, substs))
3444 /// Returns the type of element at field `n` in struct or struct-like type `t`.
3445 /// For an enum `t`, `variant` must be some def id.
3446 pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
3449 variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
3451 match (&ty.sty, variant) {
3452 (&ty_struct(def_id, ref substs), None) => {
3453 let r = lookup_struct_fields(cx, def_id);
3454 r.iter().find(|f| f.name == n)
3455 .map(|&f| lookup_field_type(cx, def_id, f.id, substs))
3457 (&ty_enum(def_id, ref substs), Some(variant_def_id)) => {
3458 let variant_info = enum_variant_with_id(cx, def_id, variant_def_id);
3459 variant_info.arg_names.as_ref()
3460 .expect("must have struct enum variant if accessing a named fields")
3461 .iter().zip(variant_info.args.iter())
3462 .find(|&(ident, _)| ident.name == n)
3463 .map(|(_ident, arg_t)| arg_t.subst(cx, substs))
3469 pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
3470 -> Rc<ty::TraitRef<'tcx>> {
3471 match cx.trait_refs.borrow().get(&id) {
3472 Some(ty) => ty.clone(),
3473 None => cx.sess.bug(
3474 format!("node_id_to_trait_ref: no trait ref for node `{}`",
3475 cx.map.node_to_string(id)).as_slice())
3479 pub fn try_node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Option<Ty<'tcx>> {
3480 cx.node_types.borrow().get(&id).cloned()
3483 pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> {
3484 match try_node_id_to_type(cx, id) {
3486 None => cx.sess.bug(
3487 format!("node_id_to_type: no type for node `{}`",
3488 cx.map.node_to_string(id)).as_slice())
3492 pub fn node_id_to_type_opt<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Option<Ty<'tcx>> {
3493 match cx.node_types.borrow().get(&id) {
3494 Some(&ty) => Some(ty),
3499 pub fn node_id_item_substs<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> ItemSubsts<'tcx> {
3500 match cx.item_substs.borrow().get(&id) {
3501 None => ItemSubsts::empty(),
3502 Some(ts) => ts.clone(),
3506 pub fn fn_is_variadic(fty: Ty) -> bool {
3508 ty_bare_fn(ref f) => f.sig.variadic,
3509 ty_closure(ref f) => f.sig.variadic,
3511 panic!("fn_is_variadic() called on non-fn type: {}", s)
3516 pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx FnSig<'tcx> {
3518 ty_bare_fn(ref f) => &f.sig,
3519 ty_closure(ref f) => &f.sig,
3521 panic!("ty_fn_sig() called on non-fn type: {}", s)
3526 /// Returns the ABI of the given function.
3527 pub fn ty_fn_abi(fty: Ty) -> abi::Abi {
3529 ty_bare_fn(ref f) => f.abi,
3530 ty_closure(ref f) => f.abi,
3531 _ => panic!("ty_fn_abi() called on non-fn type"),
3535 // Type accessors for substructures of types
3536 pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> &'tcx [Ty<'tcx>] {
3537 ty_fn_sig(fty).inputs.as_slice()
3540 pub fn ty_closure_store(fty: Ty) -> TraitStore {
3542 ty_closure(ref f) => f.store,
3543 ty_unboxed_closure(..) => {
3544 // Close enough for the purposes of all the callers of this
3545 // function (which is soon to be deprecated anyhow).
3549 panic!("ty_closure_store() called on non-closure type: {}", s)
3554 pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> {
3556 ty_bare_fn(ref f) => f.sig.output,
3557 ty_closure(ref f) => f.sig.output,
3559 panic!("ty_fn_ret() called on non-fn type: {}", s)
3564 pub fn is_fn_ty(fty: Ty) -> bool {
3566 ty_bare_fn(_) => true,
3567 ty_closure(_) => true,
3572 pub fn ty_region(tcx: &ctxt,
3580 format!("ty_region() invoked on an inappropriate ty: {}",
3586 pub fn free_region_from_def(free_id: ast::NodeId, def: &RegionParameterDef)
3589 ty::ReFree(ty::FreeRegion { scope: region::CodeExtent::from_node_id(free_id),
3590 bound_region: ty::BrNamed(def.def_id,
3594 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
3595 // doesn't provide type parameter substitutions.
3596 pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> {
3597 return node_id_to_type(cx, pat.id);
3601 // Returns the type of an expression as a monotype.
3603 // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
3604 // some cases, we insert `AutoAdjustment` annotations such as auto-deref or
3605 // auto-ref. The type returned by this function does not consider such
3606 // adjustments. See `expr_ty_adjusted()` instead.
3608 // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
3609 // ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
3610 // instead of "fn(ty) -> T with T = int".
3611 pub fn expr_ty<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> {
3612 return node_id_to_type(cx, expr.id);
3615 pub fn expr_ty_opt<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Option<Ty<'tcx>> {
3616 return node_id_to_type_opt(cx, expr.id);
3619 /// Returns the type of `expr`, considering any `AutoAdjustment`
3620 /// entry recorded for that expression.
3622 /// It would almost certainly be better to store the adjusted ty in with
3623 /// the `AutoAdjustment`, but I opted not to do this because it would
3624 /// require serializing and deserializing the type and, although that's not
3625 /// hard to do, I just hate that code so much I didn't want to touch it
3626 /// unless it was to fix it properly, which seemed a distraction from the
3627 /// task at hand! -nmatsakis
3628 pub fn expr_ty_adjusted<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> {
3629 adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr),
3630 cx.adjustments.borrow().get(&expr.id),
3631 |method_call| cx.method_map.borrow().get(&method_call).map(|method| method.ty))
3634 pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
3635 match cx.map.find(id) {
3636 Some(ast_map::NodeExpr(e)) => {
3640 cx.sess.bug(format!("Node id {} is not an expr: {}",
3645 cx.sess.bug(format!("Node id {} is not present \
3646 in the node map", id).as_slice());
3651 pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
3652 match cx.map.find(id) {
3653 Some(ast_map::NodeLocal(pat)) => {
3655 ast::PatIdent(_, ref path1, _) => {
3656 token::get_ident(path1.node)
3660 format!("Variable id {} maps to {}, not local",
3667 cx.sess.bug(format!("Variable id {} maps to {}, not local",
3674 /// See `expr_ty_adjusted`
3675 pub fn adjust_ty<'tcx>(cx: &ctxt<'tcx>,
3677 expr_id: ast::NodeId,
3678 unadjusted_ty: Ty<'tcx>,
3679 adjustment: Option<&AutoAdjustment<'tcx>>,
3680 method_type: |typeck::MethodCall| -> Option<Ty<'tcx>>)
3683 match unadjusted_ty.sty {
3684 ty_err => return unadjusted_ty,
3688 return match adjustment {
3689 Some(adjustment) => {
3691 AdjustAddEnv(store) => {
3692 match unadjusted_ty.sty {
3693 ty::ty_bare_fn(ref b) => {
3694 let bounds = ty::ExistentialBounds {
3695 region_bound: ReStatic,
3696 builtin_bounds: all_builtin_bounds(),
3701 ty::ClosureTy {fn_style: b.fn_style,
3702 onceness: ast::Many,
3710 format!("add_env adjustment on non-bare-fn: \
3717 AdjustDerefRef(ref adj) => {
3718 let mut adjusted_ty = unadjusted_ty;
3720 if !ty::type_is_error(adjusted_ty) {
3721 for i in range(0, adj.autoderefs) {
3722 let method_call = typeck::MethodCall::autoderef(expr_id, i);
3723 match method_type(method_call) {
3724 Some(method_ty) => {
3725 if let ty::FnConverging(result_type) = ty_fn_ret(method_ty) {
3726 adjusted_ty = result_type;
3731 match deref(adjusted_ty, true) {
3732 Some(mt) => { adjusted_ty = mt.ty; }
3736 format!("the {}th autoderef failed: \
3739 ty_to_string(cx, adjusted_ty))
3746 adjust_ty_for_autoref(cx, span, adjusted_ty, adj.autoref.as_ref())
3750 None => unadjusted_ty
3754 pub fn adjust_ty_for_autoref<'tcx>(cx: &ctxt<'tcx>,
3757 autoref: Option<&AutoRef<'tcx>>)
3763 Some(&AutoPtr(r, m, ref a)) => {
3764 let adjusted_ty = match a {
3765 &Some(box ref a) => adjust_ty_for_autoref(cx, span, ty, Some(a)),
3774 Some(&AutoUnsafe(m, ref a)) => {
3775 let adjusted_ty = match a {
3776 &Some(box ref a) => adjust_ty_for_autoref(cx, span, ty, Some(a)),
3779 mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
3782 Some(&AutoUnsize(ref k)) => unsize_ty(cx, ty, k, span),
3784 Some(&AutoUnsizeUniq(ref k)) => ty::mk_uniq(cx, unsize_ty(cx, ty, k, span)),
3788 // Take a sized type and a sizing adjustment and produce an unsized version of
3790 pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
3792 kind: &UnsizeKind<'tcx>,
3796 &UnsizeLength(len) => match ty.sty {
3797 ty_vec(ty, Some(n)) => {
3799 mk_vec(cx, ty, None)
3801 _ => cx.sess.span_bug(span,
3802 format!("UnsizeLength with bad sty: {}",
3803 ty_to_string(cx, ty)).as_slice())
3805 &UnsizeStruct(box ref k, tp_index) => match ty.sty {
3806 ty_struct(did, ref substs) => {
3807 let ty_substs = substs.types.get_slice(subst::TypeSpace);
3808 let new_ty = unsize_ty(cx, ty_substs[tp_index], k, span);
3809 let mut unsized_substs = substs.clone();
3810 unsized_substs.types.get_mut_slice(subst::TypeSpace)[tp_index] = new_ty;
3811 mk_struct(cx, did, unsized_substs)
3813 _ => cx.sess.span_bug(span,
3814 format!("UnsizeStruct with bad sty: {}",
3815 ty_to_string(cx, ty)).as_slice())
3817 &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
3818 mk_trait(cx, (*principal).clone(), bounds)
3823 pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
3824 match tcx.def_map.borrow().get(&expr.id) {
3827 tcx.sess.span_bug(expr.span, format!(
3828 "no def-map entry for expr {}", expr.id).as_slice());
3833 pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool {
3834 match expr_kind(tcx, e) {
3836 RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
3840 /// We categorize expressions into three kinds. The distinction between
3841 /// lvalue/rvalue is fundamental to the language. The distinction between the
3842 /// two kinds of rvalues is an artifact of trans which reflects how we will
3843 /// generate code for that kind of expression. See trans/expr.rs for more
3852 pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
3853 if tcx.method_map.borrow().contains_key(&typeck::MethodCall::expr(expr.id)) {
3854 // Overloaded operations are generally calls, and hence they are
3855 // generated via DPS, but there are a few exceptions:
3856 return match expr.node {
3857 // `a += b` has a unit result.
3858 ast::ExprAssignOp(..) => RvalueStmtExpr,
3860 // the deref method invoked for `*a` always yields an `&T`
3861 ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
3863 // the index method invoked for `a[i]` always yields an `&T`
3864 ast::ExprIndex(..) => LvalueExpr,
3866 // the slice method invoked for `a[..]` always yields an `&T`
3867 ast::ExprSlice(..) => LvalueExpr,
3869 // `for` loops are statements
3870 ast::ExprForLoop(..) => RvalueStmtExpr,
3872 // in the general case, result could be any type, use DPS
3878 ast::ExprPath(..) => {
3879 match resolve_expr(tcx, expr) {
3880 def::DefVariant(tid, vid, _) => {
3881 let variant_info = enum_variant_with_id(tcx, tid, vid);
3882 if variant_info.args.len() > 0u {
3891 def::DefStruct(_) => {
3892 match expr_ty(tcx, expr).sty {
3893 ty_bare_fn(..) => RvalueDatumExpr,
3898 // Special case: A unit like struct's constructor must be called without () at the
3899 // end (like `UnitStruct`) which means this is an ExprPath to a DefFn. But in case
3900 // of unit structs this is should not be interpreted as function pointer but as
3901 // call to the constructor.
3902 def::DefFn(_, true) => RvalueDpsExpr,
3904 // Fn pointers are just scalar values.
3905 def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => RvalueDatumExpr,
3907 // Note: there is actually a good case to be made that
3908 // DefArg's, particularly those of immediate type, ought to
3909 // considered rvalues.
3910 def::DefStatic(..) |
3912 def::DefLocal(..) => LvalueExpr,
3914 def::DefConst(..) => RvalueDatumExpr,
3919 format!("uncategorized def for expr {}: {}",
3926 ast::ExprUnary(ast::UnDeref, _) |
3927 ast::ExprField(..) |
3928 ast::ExprTupField(..) |
3929 ast::ExprIndex(..) |
3930 ast::ExprSlice(..) => {
3935 ast::ExprMethodCall(..) |
3936 ast::ExprStruct(..) |
3939 ast::ExprMatch(..) |
3940 ast::ExprClosure(..) |
3942 ast::ExprBlock(..) |
3943 ast::ExprRepeat(..) |
3944 ast::ExprVec(..) => {
3948 ast::ExprIfLet(..) => {
3949 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3951 ast::ExprWhileLet(..) => {
3952 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3955 ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
3959 ast::ExprCast(..) => {
3960 match tcx.node_types.borrow().get(&expr.id) {
3962 if type_is_trait(ty) {
3969 // Technically, it should not happen that the expr is not
3970 // present within the table. However, it DOES happen
3971 // during type check, because the final types from the
3972 // expressions are not yet recorded in the tcx. At that
3973 // time, though, we are only interested in knowing lvalue
3974 // vs rvalue. It would be better to base this decision on
3975 // the AST type in cast node---but (at the time of this
3976 // writing) it's not easy to distinguish casts to traits
3977 // from other casts based on the AST. This should be
3978 // easier in the future, when casts to traits
3979 // would like @Foo, Box<Foo>, or &Foo.
3985 ast::ExprBreak(..) |
3986 ast::ExprAgain(..) |
3988 ast::ExprWhile(..) |
3990 ast::ExprAssign(..) |
3991 ast::ExprInlineAsm(..) |
3992 ast::ExprAssignOp(..) |
3993 ast::ExprForLoop(..) => {
3997 ast::ExprLit(_) | // Note: LitStr is carved out above
3998 ast::ExprUnary(..) |
3999 ast::ExprAddrOf(..) |
4000 ast::ExprBinary(..) => {
4004 ast::ExprBox(ref place, _) => {
4005 // Special case `Box<T>` for now:
4006 let definition = match tcx.def_map.borrow().get(&place.id) {
4008 None => panic!("no def for place"),
4010 let def_id = definition.def_id();
4011 if tcx.lang_items.exchange_heap() == Some(def_id) {
4018 ast::ExprParen(ref e) => expr_kind(tcx, &**e),
4020 ast::ExprMac(..) => {
4023 "macro expression remains after expansion");
4028 pub fn stmt_node_id(s: &ast::Stmt) -> ast::NodeId {
4030 ast::StmtDecl(_, id) | StmtExpr(_, id) | StmtSemi(_, id) => {
4033 ast::StmtMac(..) => panic!("unexpanded macro in trans")
4037 pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
4040 for f in fields.iter() { if f.name == name { return i; } i += 1u; }
4041 tcx.sess.bug(format!(
4042 "no field named `{}` found in the list of fields `{}`",
4043 token::get_name(name),
4045 .map(|f| token::get_name(f.name).get().to_string())
4046 .collect::<Vec<String>>()).as_slice());
4049 pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem])
4051 trait_items.iter().position(|m| m.name() == id)
4054 pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
4056 ty_bool | ty_char | ty_int(_) |
4057 ty_uint(_) | ty_float(_) | ty_str => {
4058 ::util::ppaux::ty_to_string(cx, ty)
4060 ty_tup(ref tys) if tys.is_empty() => ::util::ppaux::ty_to_string(cx, ty),
4062 ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
4063 ty_uniq(_) => "box".to_string(),
4064 ty_vec(_, Some(n)) => format!("array of {} elements", n),
4065 ty_vec(_, None) => "slice".to_string(),
4066 ty_ptr(_) => "*-ptr".to_string(),
4067 ty_rptr(_, _) => "&-ptr".to_string(),
4068 ty_bare_fn(_) => "extern fn".to_string(),
4069 ty_closure(_) => "fn".to_string(),
4070 ty_trait(ref inner) => {
4071 format!("trait {}", item_path_str(cx, inner.principal.def_id))
4073 ty_struct(id, _) => {
4074 format!("struct {}", item_path_str(cx, id))
4076 ty_unboxed_closure(..) => "closure".to_string(),
4077 ty_tup(_) => "tuple".to_string(),
4078 ty_infer(TyVar(_)) => "inferred type".to_string(),
4079 ty_infer(IntVar(_)) => "integral variable".to_string(),
4080 ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
4081 ty_infer(SkolemizedTy(_)) => "skolemized type".to_string(),
4082 ty_infer(SkolemizedIntTy(_)) => "skolemized integral type".to_string(),
4083 ty_param(ref p) => {
4084 if p.space == subst::SelfSpace {
4087 "type parameter".to_string()
4090 ty_err => "type error".to_string(),
4091 ty_open(_) => "opened DST".to_string(),
4095 /// Explains the source of a type err in a short, human readable way. This is meant to be placed
4096 /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
4097 /// afterwards to present additional details, particularly when it comes to lifetime-related
4099 pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String {
4100 fn tstore_to_closure(s: &TraitStore) -> String {
4102 &UniqTraitStore => "proc".to_string(),
4103 &RegionTraitStore(..) => "closure".to_string()
4108 terr_cyclic_ty => "cyclic type of infinite size".to_string(),
4109 terr_mismatch => "types differ".to_string(),
4110 terr_fn_style_mismatch(values) => {
4111 format!("expected {} fn, found {} fn",
4112 values.expected.to_string(),
4113 values.found.to_string())
4115 terr_abi_mismatch(values) => {
4116 format!("expected {} fn, found {} fn",
4117 values.expected.to_string(),
4118 values.found.to_string())
4120 terr_onceness_mismatch(values) => {
4121 format!("expected {} fn, found {} fn",
4122 values.expected.to_string(),
4123 values.found.to_string())
4125 terr_sigil_mismatch(values) => {
4126 format!("expected {}, found {}",
4127 tstore_to_closure(&values.expected),
4128 tstore_to_closure(&values.found))
4130 terr_mutability => "values differ in mutability".to_string(),
4131 terr_box_mutability => {
4132 "boxed values differ in mutability".to_string()
4134 terr_vec_mutability => "vectors differ in mutability".to_string(),
4135 terr_ptr_mutability => "pointers differ in mutability".to_string(),
4136 terr_ref_mutability => "references differ in mutability".to_string(),
4137 terr_ty_param_size(values) => {
4138 format!("expected a type with {} type params, \
4139 found one with {} type params",
4143 terr_fixed_array_size(values) => {
4144 format!("expected an array with a fixed size of {} elements, \
4145 found one with {} elements",
4149 terr_tuple_size(values) => {
4150 format!("expected a tuple with {} elements, \
4151 found one with {} elements",
4156 "incorrect number of function parameters".to_string()
4158 terr_regions_does_not_outlive(..) => {
4159 "lifetime mismatch".to_string()
4161 terr_regions_not_same(..) => {
4162 "lifetimes are not the same".to_string()
4164 terr_regions_no_overlap(..) => {
4165 "lifetimes do not intersect".to_string()
4167 terr_regions_insufficiently_polymorphic(br, _) => {
4168 format!("expected bound lifetime parameter {}, \
4169 found concrete lifetime",
4170 bound_region_ptr_to_string(cx, br))
4172 terr_regions_overly_polymorphic(br, _) => {
4173 format!("expected concrete lifetime, \
4174 found bound lifetime parameter {}",
4175 bound_region_ptr_to_string(cx, br))
4177 terr_trait_stores_differ(_, ref values) => {
4178 format!("trait storage differs: expected `{}`, found `{}`",
4179 trait_store_to_string(cx, (*values).expected),
4180 trait_store_to_string(cx, (*values).found))
4182 terr_sorts(values) => {
4183 // A naive approach to making sure that we're not reporting silly errors such as:
4184 // (expected closure, found closure).
4185 let expected_str = ty_sort_string(cx, values.expected);
4186 let found_str = ty_sort_string(cx, values.found);
4187 if expected_str == found_str {
4188 format!("expected {}, found a different {}", expected_str, found_str)
4190 format!("expected {}, found {}", expected_str, found_str)
4193 terr_traits(values) => {
4194 format!("expected trait `{}`, found trait `{}`",
4195 item_path_str(cx, values.expected),
4196 item_path_str(cx, values.found))
4198 terr_builtin_bounds(values) => {
4199 if values.expected.is_empty() {
4200 format!("expected no bounds, found `{}`",
4201 values.found.user_string(cx))
4202 } else if values.found.is_empty() {
4203 format!("expected bounds `{}`, found no bounds",
4204 values.expected.user_string(cx))
4206 format!("expected bounds `{}`, found bounds `{}`",
4207 values.expected.user_string(cx),
4208 values.found.user_string(cx))
4211 terr_integer_as_char => {
4212 "expected an integral type, found `char`".to_string()
4214 terr_int_mismatch(ref values) => {
4215 format!("expected `{}`, found `{}`",
4216 values.expected.to_string(),
4217 values.found.to_string())
4219 terr_float_mismatch(ref values) => {
4220 format!("expected `{}`, found `{}`",
4221 values.expected.to_string(),
4222 values.found.to_string())
4224 terr_variadic_mismatch(ref values) => {
4225 format!("expected {} fn, found {} function",
4226 if values.expected { "variadic" } else { "non-variadic" },
4227 if values.found { "variadic" } else { "non-variadic" })
4229 terr_convergence_mismatch(ref values) => {
4230 format!("expected {} fn, found {} function",
4231 if values.expected { "converging" } else { "diverging" },
4232 if values.found { "converging" } else { "diverging" })
4237 pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) {
4239 terr_regions_does_not_outlive(subregion, superregion) => {
4240 note_and_explain_region(cx, "", subregion, "...");
4241 note_and_explain_region(cx, "...does not necessarily outlive ",
4244 terr_regions_not_same(region1, region2) => {
4245 note_and_explain_region(cx, "", region1, "...");
4246 note_and_explain_region(cx, "...is not the same lifetime as ",
4249 terr_regions_no_overlap(region1, region2) => {
4250 note_and_explain_region(cx, "", region1, "...");
4251 note_and_explain_region(cx, "...does not overlap ",
4254 terr_regions_insufficiently_polymorphic(_, conc_region) => {
4255 note_and_explain_region(cx,
4256 "concrete lifetime that was found is ",
4259 terr_regions_overly_polymorphic(_, conc_region) => {
4260 note_and_explain_region(cx,
4261 "expected concrete lifetime is ",
4268 pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
4269 cx.provided_method_sources.borrow().get(&id).map(|x| *x)
4272 pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
4273 -> Vec<Rc<Method<'tcx>>> {
4275 match cx.map.find(id.node) {
4276 Some(ast_map::NodeItem(item)) => {
4278 ItemTrait(_, _, _, ref ms) => {
4280 ast_util::split_trait_methods(ms.as_slice());
4283 match impl_or_trait_item(
4285 ast_util::local_def(m.id)) {
4286 MethodTraitItem(m) => m,
4287 TypeTraitItem(_) => {
4288 cx.sess.bug("provided_trait_methods(): \
4289 split_trait_methods() put \
4290 associated types in the \
4291 provided method bucket?!")
4297 cx.sess.bug(format!("provided_trait_methods: `{}` is \
4304 cx.sess.bug(format!("provided_trait_methods: `{}` is not a \
4310 csearch::get_provided_trait_methods(cx, id)
4314 /// Helper for looking things up in the various maps that are populated during typeck::collect
4315 /// (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc). All of these share the pattern that if the
4316 /// id is local, it should have been loaded into the map by the `typeck::collect` phase. If the
4317 /// def-id is external, then we have to go consult the crate loading code (and cache the result for
4319 fn lookup_locally_or_in_crate_store<V:Clone>(
4322 map: &mut DefIdMap<V>,
4323 load_external: || -> V) -> V {
4324 match map.get(&def_id).cloned() {
4325 Some(v) => { return v; }
4329 if def_id.krate == ast::LOCAL_CRATE {
4330 panic!("No def'n found for {} in tcx.{}", def_id, descr);
4332 let v = load_external();
4333 map.insert(def_id, v.clone());
4337 pub fn trait_item<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId, idx: uint)
4338 -> ImplOrTraitItem<'tcx> {
4339 let method_def_id = (*ty::trait_item_def_ids(cx, trait_did))[idx].def_id();
4340 impl_or_trait_item(cx, method_def_id)
4343 pub fn trait_items<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId)
4344 -> Rc<Vec<ImplOrTraitItem<'tcx>>> {
4345 let mut trait_items = cx.trait_items_cache.borrow_mut();
4346 match trait_items.get(&trait_did).cloned() {
4347 Some(trait_items) => trait_items,
4349 let def_ids = ty::trait_item_def_ids(cx, trait_did);
4350 let items: Rc<Vec<ImplOrTraitItem>> =
4351 Rc::new(def_ids.iter()
4352 .map(|d| impl_or_trait_item(cx, d.def_id()))
4354 trait_items.insert(trait_did, items.clone());
4360 pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
4361 -> ImplOrTraitItem<'tcx> {
4362 lookup_locally_or_in_crate_store("impl_or_trait_items",
4364 &mut *cx.impl_or_trait_items
4367 csearch::get_impl_or_trait_item(cx, id)
4371 /// Returns true if the given ID refers to an associated type and false if it
4372 /// refers to anything else.
4373 pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
4374 memoized(&cx.associated_types, id, |id: ast::DefId| {
4375 if id.krate == ast::LOCAL_CRATE {
4376 match cx.impl_or_trait_items.borrow().get(&id) {
4379 TypeTraitItem(_) => true,
4380 MethodTraitItem(_) => false,
4386 csearch::is_associated_type(&cx.sess.cstore, id)
4391 /// Returns the parameter index that the given associated type corresponds to.
4392 pub fn associated_type_parameter_index(cx: &ctxt,
4393 trait_def: &TraitDef,
4394 associated_type_id: ast::DefId)
4396 for type_parameter_def in trait_def.generics.types.iter() {
4397 if type_parameter_def.def_id == associated_type_id {
4398 return type_parameter_def.index
4401 cx.sess.bug("couldn't find associated type parameter index")
4404 #[deriving(PartialEq, Eq)]
4405 pub struct AssociatedTypeInfo {
4406 pub def_id: ast::DefId,
4408 pub name: ast::Name,
4411 impl PartialOrd for AssociatedTypeInfo {
4412 fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option<Ordering> {
4413 Some(self.index.cmp(&other.index))
4417 impl Ord for AssociatedTypeInfo {
4418 fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering {
4419 self.index.cmp(&other.index)
4423 pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
4424 -> Rc<Vec<ImplOrTraitItemId>> {
4425 lookup_locally_or_in_crate_store("trait_item_def_ids",
4427 &mut *cx.trait_item_def_ids.borrow_mut(),
4429 Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
4433 pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
4434 -> Option<Rc<TraitRef<'tcx>>> {
4435 memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
4436 if id.krate == ast::LOCAL_CRATE {
4437 debug!("(impl_trait_ref) searching for trait impl {}", id);
4438 match cx.map.find(id.node) {
4439 Some(ast_map::NodeItem(item)) => {
4441 ast::ItemImpl(_, ref opt_trait, _, _) => {
4444 Some(ty::node_id_to_trait_ref(cx, t.ref_id))
4455 csearch::get_impl_trait(cx, id)
4460 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
4461 let def = *tcx.def_map.borrow()
4463 .expect("no def-map entry for trait");
4467 pub fn try_add_builtin_trait(
4469 trait_def_id: ast::DefId,
4470 builtin_bounds: &mut EnumSet<BuiltinBound>)
4473 //! Checks whether `trait_ref` refers to one of the builtin
4474 //! traits, like `Send`, and adds the corresponding
4475 //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
4476 //! is a builtin trait.
4478 match tcx.lang_items.to_builtin_kind(trait_def_id) {
4479 Some(bound) => { builtin_bounds.insert(bound); true }
4484 pub fn ty_to_def_id(ty: Ty) -> Option<ast::DefId> {
4487 Some(tt.principal.def_id),
4490 ty_unboxed_closure(id, _, _) =>
4499 pub struct VariantInfo<'tcx> {
4500 pub args: Vec<Ty<'tcx>>,
4501 pub arg_names: Option<Vec<ast::Ident>>,
4502 pub ctor_ty: Option<Ty<'tcx>>,
4503 pub name: ast::Name,
4509 impl<'tcx> VariantInfo<'tcx> {
4511 /// Creates a new VariantInfo from the corresponding ast representation.
4513 /// Does not do any caching of the value in the type context.
4514 pub fn from_ast_variant(cx: &ctxt<'tcx>,
4515 ast_variant: &ast::Variant,
4516 discriminant: Disr) -> VariantInfo<'tcx> {
4517 let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
4519 match ast_variant.node.kind {
4520 ast::TupleVariantKind(ref args) => {
4521 let arg_tys = if args.len() > 0 {
4522 ty_fn_args(ctor_ty).iter().map(|a| *a).collect()
4527 return VariantInfo {
4530 ctor_ty: Some(ctor_ty),
4531 name: ast_variant.node.name.name,
4532 id: ast_util::local_def(ast_variant.node.id),
4533 disr_val: discriminant,
4534 vis: ast_variant.node.vis
4537 ast::StructVariantKind(ref struct_def) => {
4539 let fields: &[StructField] = struct_def.fields.as_slice();
4541 assert!(fields.len() > 0);
4543 let arg_tys = struct_def.fields.iter()
4544 .map(|field| node_id_to_type(cx, field.node.id)).collect();
4545 let arg_names = fields.iter().map(|field| {
4546 match field.node.kind {
4547 NamedField(ident, _) => ident,
4548 UnnamedField(..) => cx.sess.bug(
4549 "enum_variants: all fields in struct must have a name")
4553 return VariantInfo {
4555 arg_names: Some(arg_names),
4557 name: ast_variant.node.name.name,
4558 id: ast_util::local_def(ast_variant.node.id),
4559 disr_val: discriminant,
4560 vis: ast_variant.node.vis
4567 pub fn substd_enum_variants<'tcx>(cx: &ctxt<'tcx>,
4569 substs: &Substs<'tcx>)
4570 -> Vec<Rc<VariantInfo<'tcx>>> {
4571 enum_variants(cx, id).iter().map(|variant_info| {
4572 let substd_args = variant_info.args.iter()
4573 .map(|aty| aty.subst(cx, substs)).collect::<Vec<_>>();
4575 let substd_ctor_ty = variant_info.ctor_ty.subst(cx, substs);
4577 Rc::new(VariantInfo {
4579 ctor_ty: substd_ctor_ty,
4580 ..(**variant_info).clone()
4585 pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String {
4586 with_path(cx, id, |path| ast_map::path_to_string(path)).to_string()
4591 TraitDtor(DefId, bool)
4595 pub fn is_present(&self) -> bool {
4597 TraitDtor(..) => true,
4602 pub fn has_drop_flag(&self) -> bool {
4605 &TraitDtor(_, flag) => flag
4610 /* If struct_id names a struct with a dtor, return Some(the dtor's id).
4611 Otherwise return none. */
4612 pub fn ty_dtor(cx: &ctxt, struct_id: DefId) -> DtorKind {
4613 match cx.destructor_for_type.borrow().get(&struct_id) {
4614 Some(&method_def_id) => {
4615 let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag");
4617 TraitDtor(method_def_id, flag)
4623 pub fn has_dtor(cx: &ctxt, struct_id: DefId) -> bool {
4624 cx.destructor_for_type.borrow().contains_key(&struct_id)
4627 pub fn with_path<T>(cx: &ctxt, id: ast::DefId, f: |ast_map::PathElems| -> T) -> T {
4628 if id.krate == ast::LOCAL_CRATE {
4629 cx.map.with_path(id.node, f)
4631 f(ast_map::Values(csearch::get_item_path(cx, id).iter()).chain(None))
4635 pub fn enum_is_univariant(cx: &ctxt, id: ast::DefId) -> bool {
4636 enum_variants(cx, id).len() == 1
4639 pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool {
4641 ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
4646 pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
4647 -> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
4648 memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
4649 if ast::LOCAL_CRATE != id.krate {
4650 Rc::new(csearch::get_enum_variants(cx, id))
4653 Although both this code and check_enum_variants in typeck/check
4654 call eval_const_expr, it should never get called twice for the same
4655 expr, since check_enum_variants also updates the enum_var_cache
4657 match cx.map.get(id.node) {
4658 ast_map::NodeItem(ref item) => {
4660 ast::ItemEnum(ref enum_definition, _) => {
4661 let mut last_discriminant: Option<Disr> = None;
4662 Rc::new(enum_definition.variants.iter().map(|variant| {
4664 let mut discriminant = match last_discriminant {
4665 Some(val) => val + 1,
4666 None => INITIAL_DISCRIMINANT_VALUE
4669 match variant.node.disr_expr {
4671 match const_eval::eval_const_expr_partial(cx, &**e) {
4672 Ok(const_eval::const_int(val)) => {
4673 discriminant = val as Disr
4675 Ok(const_eval::const_uint(val)) => {
4676 discriminant = val as Disr
4681 "expected signed integer constant");
4686 format!("expected constant: {}",
4693 last_discriminant = Some(discriminant);
4694 Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
4699 cx.sess.bug("enum_variants: id not bound to an enum")
4703 _ => cx.sess.bug("enum_variants: id not bound to an enum")
4709 // Returns information about the enum variant with the given ID:
4710 pub fn enum_variant_with_id<'tcx>(cx: &ctxt<'tcx>,
4711 enum_id: ast::DefId,
4712 variant_id: ast::DefId)
4713 -> Rc<VariantInfo<'tcx>> {
4714 enum_variants(cx, enum_id).iter()
4715 .find(|variant| variant.id == variant_id)
4716 .expect("enum_variant_with_id(): no variant exists with that ID")
4721 // If the given item is in an external crate, looks up its type and adds it to
4722 // the type cache. Returns the type parameters and type.
4723 pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>,
4726 lookup_locally_or_in_crate_store(
4727 "tcache", did, &mut *cx.tcache.borrow_mut(),
4728 || csearch::get_type(cx, did))
4731 /// Given the did of a trait, returns its canonical trait ref.
4732 pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
4733 -> Rc<ty::TraitDef<'tcx>> {
4734 memoized(&cx.trait_defs, did, |did: DefId| {
4735 assert!(did.krate != ast::LOCAL_CRATE);
4736 Rc::new(csearch::get_trait_def(cx, did))
4740 /// Given a reference to a trait, returns the bounds declared on the
4741 /// trait, with appropriate substitutions applied.
4742 pub fn bounds_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>,
4743 trait_ref: &TraitRef<'tcx>)
4744 -> ty::ParamBounds<'tcx>
4746 let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
4748 debug!("bounds_for_trait_ref(trait_def={}, trait_ref={})",
4749 trait_def.repr(tcx), trait_ref.repr(tcx));
4751 // The interaction between HRTB and supertraits is not entirely
4752 // obvious. Let me walk you (and myself) through an example.
4754 // Let's start with an easy case. Consider two traits:
4756 // trait Foo<'a> : Bar<'a,'a> { }
4757 // trait Bar<'b,'c> { }
4759 // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then
4760 // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we
4761 // knew that `Foo<'x>` (for any 'x) then we also know that
4762 // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
4763 // normal substitution.
4765 // In terms of why this is sound, the idea is that whenever there
4766 // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
4767 // holds. So if there is an impl of `T:Foo<'a>` that applies to
4768 // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
4771 // Another example to be careful of is this:
4773 // trait Foo1<'a> : for<'b> Bar1<'a,'b> { }
4774 // trait Bar1<'b,'c> { }
4776 // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know?
4777 // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The
4778 // reason is similar to the previous example: any impl of
4779 // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So
4780 // basically we would want to collapse the bound lifetimes from
4781 // the input (`trait_ref`) and the supertraits.
4783 // To achieve this in practice is fairly straightforward. Let's
4784 // consider the more complicated scenario:
4786 // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x`
4787 // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`,
4788 // where both `'x` and `'b` would have a DB index of 1.
4789 // The substitution from the input trait-ref is therefore going to be
4790 // `'a => 'x` (where `'x` has a DB index of 1).
4791 // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
4792 // early-bound parameter and `'b' is a late-bound parameter with a
4794 // - If we replace `'a` with `'x` from the input, it too will have
4795 // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
4796 // just as we wanted.
4798 // There is only one catch. If we just apply the substitution `'a
4799 // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
4800 // adjust the DB index because we substituting into a binder (it
4801 // tries to be so smart...) resulting in `for<'x> for<'b>
4802 // Bar1<'x,'b>` (we have no syntax for this, so use your
4803 // imagination). Basically the 'x will have DB index of 2 and 'b
4804 // will have DB index of 1. Not quite what we want. So we apply
4805 // the substitution to the *contents* of the trait reference,
4806 // rather than the trait reference itself (put another way, the
4807 // substitution code expects equal binding levels in the values
4808 // from the substitution and the value being substituted into, and
4809 // this trick achieves that).
4811 // Carefully avoid the binder introduced by each trait-ref by
4812 // substituting over the substs, not the trait-refs themselves,
4813 // thus achieving the "collapse" described in the big comment
4815 let trait_bounds: Vec<_> =
4816 trait_def.bounds.trait_bounds
4818 .map(|bound_trait_ref| {
4819 ty::TraitRef::new(bound_trait_ref.def_id,
4820 bound_trait_ref.substs.subst(tcx, &trait_ref.substs))
4822 .map(|bound_trait_ref| Rc::new(bound_trait_ref))
4825 debug!("bounds_for_trait_ref: trait_bounds={}",
4826 trait_bounds.repr(tcx));
4828 // The region bounds and builtin bounds do not currently introduce
4829 // binders so we can just substitute in a straightforward way here.
4831 trait_def.bounds.region_bounds.subst(tcx, &trait_ref.substs);
4832 let builtin_bounds =
4833 trait_def.bounds.builtin_bounds.subst(tcx, &trait_ref.substs);
4836 trait_bounds: trait_bounds,
4837 region_bounds: region_bounds,
4838 builtin_bounds: builtin_bounds,
4842 /// Iterate over attributes of a definition.
4843 // (This should really be an iterator, but that would require csearch and
4844 // decoder to use iterators instead of higher-order functions.)
4845 pub fn each_attr(tcx: &ctxt, did: DefId, f: |&ast::Attribute| -> bool) -> bool {
4847 let item = tcx.map.expect_item(did.node);
4848 item.attrs.iter().all(|attr| f(attr))
4850 info!("getting foreign attrs");
4851 let mut cont = true;
4852 csearch::get_item_attrs(&tcx.sess.cstore, did, |attrs| {
4854 cont = attrs.iter().all(|attr| f(attr));
4862 /// Determine whether an item is annotated with an attribute
4863 pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
4864 let mut found = false;
4865 each_attr(tcx, did, |item| {
4866 if item.check_name(attr) {
4876 /// Determine whether an item is annotated with `#[repr(packed)]`
4877 pub fn lookup_packed(tcx: &ctxt, did: DefId) -> bool {
4878 lookup_repr_hints(tcx, did).contains(&attr::ReprPacked)
4881 /// Determine whether an item is annotated with `#[simd]`
4882 pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
4883 has_attr(tcx, did, "simd")
4886 /// Obtain the representation annotation for a struct definition.
4887 pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
4888 memoized(&tcx.repr_hint_cache, did, |did: DefId| {
4889 Rc::new(if did.krate == LOCAL_CRATE {
4890 let mut acc = Vec::new();
4891 ty::each_attr(tcx, did, |meta| {
4892 acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(),
4898 csearch::get_repr_attrs(&tcx.sess.cstore, did)
4903 // Look up a field ID, whether or not it's local
4904 // Takes a list of type substs in case the struct is generic
4905 pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>,
4908 substs: &Substs<'tcx>)
4910 let ty = if id.krate == ast::LOCAL_CRATE {
4911 node_id_to_type(tcx, id.node)
4913 let mut tcache = tcx.tcache.borrow_mut();
4914 let pty = match tcache.entry(id) {
4915 Occupied(entry) => entry.into_mut(),
4916 Vacant(entry) => entry.set(csearch::get_field_type(tcx, struct_id, id)),
4920 ty.subst(tcx, substs)
4923 // Look up the list of field names and IDs for a given struct.
4924 // Panics if the id is not bound to a struct.
4925 pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
4926 if did.krate == ast::LOCAL_CRATE {
4927 let struct_fields = cx.struct_fields.borrow();
4928 match struct_fields.get(&did) {
4929 Some(fields) => (**fields).clone(),
4932 format!("ID not mapped to struct fields: {}",
4933 cx.map.node_to_string(did.node)).as_slice());
4937 csearch::get_struct_fields(&cx.sess.cstore, did)
4941 pub fn is_tuple_struct(cx: &ctxt, did: ast::DefId) -> bool {
4942 let fields = lookup_struct_fields(cx, did);
4943 !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field)
4946 // Returns a list of fields corresponding to the struct's items. trans uses
4947 // this. Takes a list of substs with which to instantiate field types.
4948 pub fn struct_fields<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &Substs<'tcx>)
4949 -> Vec<field<'tcx>> {
4950 lookup_struct_fields(cx, did).iter().map(|f| {
4954 ty: lookup_field_type(cx, did, f.id, substs),
4961 // Returns a list of fields corresponding to the tuple's items. trans uses
4963 pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
4964 v.iter().enumerate().map(|(i, &f)| {
4966 name: token::intern(i.to_string().as_slice()),
4975 pub struct UnboxedClosureUpvar<'tcx> {
4981 // Returns a list of `UnboxedClosureUpvar`s for each upvar.
4982 pub fn unboxed_closure_upvars<'tcx>(tcx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &Substs<'tcx>)
4983 -> Vec<UnboxedClosureUpvar<'tcx>> {
4984 // Presently an unboxed closure type cannot "escape" out of a
4985 // function, so we will only encounter ones that originated in the
4986 // local crate or were inlined into it along with some function.
4987 // This may change if abstract return types of some sort are
4989 assert!(closure_id.krate == ast::LOCAL_CRATE);
4990 let capture_mode = tcx.capture_modes.borrow()[closure_id.node].clone();
4991 match tcx.freevars.borrow().get(&closure_id.node) {
4993 Some(ref freevars) => {
4994 freevars.iter().map(|freevar| {
4995 let freevar_def_id = freevar.def.def_id();
4996 let freevar_ty = node_id_to_type(tcx, freevar_def_id.node);
4997 let mut freevar_ty = freevar_ty.subst(tcx, substs);
4998 if capture_mode == ast::CaptureByRef {
4999 let borrow = tcx.upvar_borrow_map.borrow()[ty::UpvarId {
5000 var_id: freevar_def_id.node,
5001 closure_expr_id: closure_id.node
5003 freevar_ty = mk_rptr(tcx, borrow.region, ty::mt {
5005 mutbl: borrow.kind.to_mutbl_lossy()
5008 UnboxedClosureUpvar {
5018 pub fn is_binopable<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, op: ast::BinOp) -> bool {
5019 #![allow(non_upper_case_globals)]
5020 static tycat_other: int = 0;
5021 static tycat_bool: int = 1;
5022 static tycat_char: int = 2;
5023 static tycat_int: int = 3;
5024 static tycat_float: int = 4;
5025 static tycat_raw_ptr: int = 6;
5027 static opcat_add: int = 0;
5028 static opcat_sub: int = 1;
5029 static opcat_mult: int = 2;
5030 static opcat_shift: int = 3;
5031 static opcat_rel: int = 4;
5032 static opcat_eq: int = 5;
5033 static opcat_bit: int = 6;
5034 static opcat_logic: int = 7;
5035 static opcat_mod: int = 8;
5037 fn opcat(op: ast::BinOp) -> int {
5039 ast::BiAdd => opcat_add,
5040 ast::BiSub => opcat_sub,
5041 ast::BiMul => opcat_mult,
5042 ast::BiDiv => opcat_mult,
5043 ast::BiRem => opcat_mod,
5044 ast::BiAnd => opcat_logic,
5045 ast::BiOr => opcat_logic,
5046 ast::BiBitXor => opcat_bit,
5047 ast::BiBitAnd => opcat_bit,
5048 ast::BiBitOr => opcat_bit,
5049 ast::BiShl => opcat_shift,
5050 ast::BiShr => opcat_shift,
5051 ast::BiEq => opcat_eq,
5052 ast::BiNe => opcat_eq,
5053 ast::BiLt => opcat_rel,
5054 ast::BiLe => opcat_rel,
5055 ast::BiGe => opcat_rel,
5056 ast::BiGt => opcat_rel
5060 fn tycat<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> int {
5061 if type_is_simd(cx, ty) {
5062 return tycat(cx, simd_type(cx, ty))
5065 ty_char => tycat_char,
5066 ty_bool => tycat_bool,
5067 ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
5068 ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
5069 ty_ptr(_) => tycat_raw_ptr,
5074 static t: bool = true;
5075 static f: bool = false;
5078 // +, -, *, shift, rel, ==, bit, logic, mod
5079 /*other*/ [f, f, f, f, f, f, f, f, f],
5080 /*bool*/ [f, f, f, f, t, t, t, t, f],
5081 /*char*/ [f, f, f, f, t, t, f, f, f],
5082 /*int*/ [t, t, t, t, t, t, t, f, t],
5083 /*float*/ [t, t, t, f, t, t, f, f, f],
5084 /*bot*/ [t, t, t, t, t, t, t, t, t],
5085 /*raw ptr*/ [f, f, f, f, t, t, f, f, f]];
5087 return tbl[tycat(cx, ty) as uint ][opcat(op) as uint];
5090 /// Returns an equivalent type with all the typedefs and self regions removed.
5091 pub fn normalize_ty<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
5092 let u = TypeNormalizer(cx).fold_ty(ty);
5095 struct TypeNormalizer<'a, 'tcx: 'a>(&'a ctxt<'tcx>);
5097 impl<'a, 'tcx> TypeFolder<'tcx> for TypeNormalizer<'a, 'tcx> {
5098 fn tcx(&self) -> &ctxt<'tcx> { let TypeNormalizer(c) = *self; c }
5100 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
5101 match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
5106 let t_norm = ty_fold::super_fold_ty(self, ty);
5107 self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
5111 fn fold_region(&mut self, _: ty::Region) -> ty::Region {
5115 fn fold_substs(&mut self,
5116 substs: &subst::Substs<'tcx>)
5117 -> subst::Substs<'tcx> {
5118 subst::Substs { regions: subst::ErasedRegions,
5119 types: substs.types.fold_with(self) }
5122 fn fold_fn_sig(&mut self,
5123 sig: &ty::FnSig<'tcx>)
5124 -> ty::FnSig<'tcx> {
5125 // The binder-id is only relevant to bound regions, which
5126 // are erased at trans time.
5128 inputs: sig.inputs.fold_with(self),
5129 output: sig.output.fold_with(self),
5130 variadic: sig.variadic,
5136 // Returns the repeat count for a repeating vector expression.
5137 pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
5138 match const_eval::eval_const_expr_partial(tcx, count_expr) {
5140 let found = match val {
5141 const_eval::const_uint(count) => return count as uint,
5142 const_eval::const_int(count) if count >= 0 => return count as uint,
5143 const_eval::const_int(_) =>
5145 const_eval::const_float(_) =>
5147 const_eval::const_str(_) =>
5149 const_eval::const_bool(_) =>
5151 const_eval::const_binary(_) =>
5154 tcx.sess.span_err(count_expr.span, format!(
5155 "expected positive integer for repeat count, found {}",
5159 let found = match count_expr.node {
5160 ast::ExprPath(ast::Path {
5164 }) if segments.len() == 1 =>
5167 "non-constant expression"
5169 tcx.sess.span_err(count_expr.span, format!(
5170 "expected constant integer for repeat count, found {}",
5177 // Iterate over a type parameter's bounded traits and any supertraits
5178 // of those traits, ignoring kinds.
5179 // Here, the supertraits are the transitive closure of the supertrait
5180 // relation on the supertraits from each bounded trait's constraint
5182 pub fn each_bound_trait_and_supertraits<'tcx>(tcx: &ctxt<'tcx>,
5183 bounds: &[Rc<TraitRef<'tcx>>],
5184 f: |Rc<TraitRef<'tcx>>| -> bool)
5187 for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
5188 if !f(bound_trait_ref) {
5195 /// Given a type which must meet the builtin bounds and trait bounds, returns a set of lifetimes
5196 /// which the type must outlive.
5198 /// Requires that trait definitions have been processed.
5199 pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
5200 region_bounds: &[ty::Region],
5201 builtin_bounds: BuiltinBounds,
5202 trait_bounds: &[Rc<TraitRef<'tcx>>])
5205 let mut all_bounds = Vec::new();
5207 debug!("required_region_bounds(builtin_bounds={}, trait_bounds={})",
5208 builtin_bounds.repr(tcx),
5209 trait_bounds.repr(tcx));
5211 all_bounds.push_all(region_bounds);
5213 push_region_bounds(&[],
5217 debug!("from builtin bounds: all_bounds={}", all_bounds.repr(tcx));
5219 each_bound_trait_and_supertraits(
5223 let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref);
5224 push_region_bounds(bounds.region_bounds.as_slice(),
5225 bounds.builtin_bounds,
5227 debug!("from {}: bounds={} all_bounds={}",
5228 trait_ref.repr(tcx),
5230 all_bounds.repr(tcx));
5236 fn push_region_bounds(region_bounds: &[ty::Region],
5237 builtin_bounds: ty::BuiltinBounds,
5238 all_bounds: &mut Vec<ty::Region>) {
5239 all_bounds.push_all(region_bounds.as_slice());
5241 if builtin_bounds.contains(&ty::BoundSend) {
5242 all_bounds.push(ty::ReStatic);
5247 pub fn get_tydesc_ty<'tcx>(tcx: &ctxt<'tcx>) -> Result<Ty<'tcx>, String> {
5248 tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| {
5249 tcx.intrinsic_defs.borrow().get(&tydesc_lang_item).cloned()
5250 .expect("Failed to resolve TyDesc")
5254 pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
5255 lookup_locally_or_in_crate_store(
5256 "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
5257 || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
5260 /// Records a trait-to-implementation mapping.
5261 pub fn record_trait_implementation(tcx: &ctxt,
5262 trait_def_id: DefId,
5263 impl_def_id: DefId) {
5264 match tcx.trait_impls.borrow().get(&trait_def_id) {
5265 Some(impls_for_trait) => {
5266 impls_for_trait.borrow_mut().push(impl_def_id);
5271 tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
5274 /// Populates the type context with all the implementations for the given type
5276 pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
5277 type_id: ast::DefId) {
5278 if type_id.krate == LOCAL_CRATE {
5281 if tcx.populated_external_types.borrow().contains(&type_id) {
5285 let mut inherent_impls = Vec::new();
5286 csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
5288 let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
5291 // Record the trait->implementation mappings, if applicable.
5292 let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
5293 for trait_ref in associated_traits.iter() {
5294 record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
5297 // For any methods that use a default implementation, add them to
5298 // the map. This is a bit unfortunate.
5299 for impl_item_def_id in impl_items.iter() {
5300 let method_def_id = impl_item_def_id.def_id();
5301 match impl_or_trait_item(tcx, method_def_id) {
5302 MethodTraitItem(method) => {
5303 for &source in method.provided_source.iter() {
5304 tcx.provided_method_sources
5306 .insert(method_def_id, source);
5309 TypeTraitItem(_) => {}
5313 // Store the implementation info.
5314 tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
5316 // If this is an inherent implementation, record it.
5317 if associated_traits.is_none() {
5318 inherent_impls.push(impl_def_id);
5322 tcx.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
5323 tcx.populated_external_types.borrow_mut().insert(type_id);
5326 /// Populates the type context with all the implementations for the given
5327 /// trait if necessary.
5328 pub fn populate_implementations_for_trait_if_necessary(
5330 trait_id: ast::DefId) {
5331 if trait_id.krate == LOCAL_CRATE {
5334 if tcx.populated_external_traits.borrow().contains(&trait_id) {
5338 csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
5339 |implementation_def_id| {
5340 let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
5342 // Record the trait->implementation mapping.
5343 record_trait_implementation(tcx, trait_id, implementation_def_id);
5345 // For any methods that use a default implementation, add them to
5346 // the map. This is a bit unfortunate.
5347 for impl_item_def_id in impl_items.iter() {
5348 let method_def_id = impl_item_def_id.def_id();
5349 match impl_or_trait_item(tcx, method_def_id) {
5350 MethodTraitItem(method) => {
5351 for &source in method.provided_source.iter() {
5352 tcx.provided_method_sources
5354 .insert(method_def_id, source);
5357 TypeTraitItem(_) => {}
5361 // Store the implementation info.
5362 tcx.impl_items.borrow_mut().insert(implementation_def_id, impl_items);
5365 tcx.populated_external_traits.borrow_mut().insert(trait_id);
5368 /// Given the def_id of an impl, return the def_id of the trait it implements.
5369 /// If it implements no trait, return `None`.
5370 pub fn trait_id_of_impl(tcx: &ctxt,
5371 def_id: ast::DefId) -> Option<ast::DefId> {
5372 let node = match tcx.map.find(def_id.node) {
5377 ast_map::NodeItem(item) => {
5379 ast::ItemImpl(_, Some(ref trait_ref), _, _) => {
5380 Some(node_id_to_trait_ref(tcx, trait_ref.ref_id).def_id)
5389 /// If the given def ID describes a method belonging to an impl, return the
5390 /// ID of the impl that the method belongs to. Otherwise, return `None`.
5391 pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
5392 -> Option<ast::DefId> {
5393 if def_id.krate != LOCAL_CRATE {
5394 return match csearch::get_impl_or_trait_item(tcx,
5395 def_id).container() {
5396 TraitContainer(_) => None,
5397 ImplContainer(def_id) => Some(def_id),
5400 match tcx.impl_or_trait_items.borrow().get(&def_id).cloned() {
5401 Some(trait_item) => {
5402 match trait_item.container() {
5403 TraitContainer(_) => None,
5404 ImplContainer(def_id) => Some(def_id),
5411 /// If the given def ID describes an item belonging to a trait (either a
5412 /// default method or an implementation of a trait method), return the ID of
5413 /// the trait that the method belongs to. Otherwise, return `None`.
5414 pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option<ast::DefId> {
5415 if def_id.krate != LOCAL_CRATE {
5416 return csearch::get_trait_of_item(&tcx.sess.cstore, def_id, tcx);
5418 match tcx.impl_or_trait_items.borrow().get(&def_id).cloned() {
5419 Some(impl_or_trait_item) => {
5420 match impl_or_trait_item.container() {
5421 TraitContainer(def_id) => Some(def_id),
5422 ImplContainer(def_id) => trait_id_of_impl(tcx, def_id),
5429 /// If the given def ID describes an item belonging to a trait, (either a
5430 /// default method or an implementation of a trait method), return the ID of
5431 /// the method inside trait definition (this means that if the given def ID
5432 /// is already that of the original trait method, then the return value is
5434 /// Otherwise, return `None`.
5435 pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
5436 -> Option<ImplOrTraitItemId> {
5437 let impl_item = match tcx.impl_or_trait_items.borrow().get(&def_id) {
5438 Some(m) => m.clone(),
5439 None => return None,
5441 let name = impl_item.name();
5442 match trait_of_item(tcx, def_id) {
5443 Some(trait_did) => {
5444 let trait_items = ty::trait_items(tcx, trait_did);
5446 .position(|m| m.name() == name)
5447 .map(|idx| ty::trait_item(tcx, trait_did, idx).id())
5453 /// Creates a hash of the type `Ty` which will be the same no matter what crate
5454 /// context it's calculated within. This is used by the `type_id` intrinsic.
5455 pub fn hash_crate_independent(tcx: &ctxt, ty: Ty, svh: &Svh) -> u64 {
5456 let mut state = sip::SipState::new();
5457 macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } );
5458 macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } );
5460 let region = |_state: &mut sip::SipState, r: Region| {
5470 tcx.sess.bug("non-static region found when hashing a type")
5474 let did = |state: &mut sip::SipState, did: DefId| {
5475 let h = if ast_util::is_local(did) {
5478 tcx.sess.cstore.get_crate_hash(did.krate)
5480 h.as_str().hash(state);
5481 did.node.hash(state);
5483 let mt = |state: &mut sip::SipState, mt: mt| {
5484 mt.mutbl.hash(state);
5486 ty::walk_ty(ty, |ty| {
5488 ty_bool => byte!(2),
5489 ty_char => byte!(3),
5512 ty_vec(_, Some(n)) => {
5516 ty_vec(_, None) => {
5525 region(&mut state, r);
5528 ty_bare_fn(ref b) => {
5533 ty_closure(ref c) => {
5539 UniqTraitStore => byte!(0),
5540 RegionTraitStore(r, m) => {
5542 region(&mut state, r);
5543 assert_eq!(m, ast::MutMutable);
5547 ty_trait(box TyTrait { ref principal, bounds }) => {
5549 did(&mut state, principal.def_id);
5552 ty_struct(d, _) => {
5556 ty_tup(ref inner) => {
5563 did(&mut state, p.def_id);
5565 ty_open(_) => byte!(22),
5566 ty_infer(_) => unreachable!(),
5567 ty_err => byte!(23),
5568 ty_unboxed_closure(d, r, _) => {
5571 region(&mut state, r);
5580 pub fn to_string(self) -> &'static str {
5583 Contravariant => "-",
5590 /// Construct a parameter environment suitable for static contexts or other contexts where there
5591 /// are no free type/lifetime parameters in scope.
5592 pub fn empty_parameter_environment<'tcx>() -> ParameterEnvironment<'tcx> {
5593 ty::ParameterEnvironment { free_substs: Substs::empty(),
5594 bounds: VecPerParamSpace::empty(),
5595 caller_obligations: VecPerParamSpace::empty(),
5596 implicit_region_bound: ty::ReEmpty,
5597 selection_cache: traits::SelectionCache::new(), }
5600 /// See `ParameterEnvironment` struct def'n for details
5601 pub fn construct_parameter_environment<'tcx>(
5604 generics: &ty::Generics<'tcx>,
5605 free_id: ast::NodeId)
5606 -> ParameterEnvironment<'tcx>
5610 // Construct the free substs.
5614 let mut types = VecPerParamSpace::empty();
5615 for &space in subst::ParamSpace::all().iter() {
5616 push_types_from_defs(tcx, &mut types, space,
5617 generics.types.get_slice(space));
5620 // map bound 'a => free 'a
5621 let mut regions = VecPerParamSpace::empty();
5622 for &space in subst::ParamSpace::all().iter() {
5623 push_region_params(&mut regions, space, free_id,
5624 generics.regions.get_slice(space));
5627 let free_substs = Substs {
5629 regions: subst::NonerasedRegions(regions)
5632 let free_id_scope = region::CodeExtent::from_node_id(free_id);
5635 // Compute the bounds on Self and the type parameters.
5638 let bounds = generics.to_bounds(tcx, &free_substs);
5639 let bounds = liberate_late_bound_regions(tcx, free_id_scope, &bind(bounds)).value;
5640 let obligations = traits::obligations_for_generics(tcx,
5641 traits::ObligationCause::misc(span),
5643 &free_substs.types);
5644 let type_bounds = bounds.types.subst(tcx, &free_substs);
5647 // Compute region bounds. For now, these relations are stored in a
5648 // global table on the tcx, so just enter them there. I'm not
5649 // crazy about this scheme, but it's convenient, at least.
5652 for &space in subst::ParamSpace::all().iter() {
5653 record_region_bounds(tcx, space, &free_substs, bounds.regions.get_slice(space));
5657 debug!("construct_parameter_environment: free_id={} free_subst={} \
5658 obligations={} type_bounds={}",
5660 free_substs.repr(tcx),
5661 obligations.repr(tcx),
5662 type_bounds.repr(tcx));
5664 return ty::ParameterEnvironment {
5665 free_substs: free_substs,
5666 bounds: bounds.types,
5667 implicit_region_bound: ty::ReScope(free_id_scope),
5668 caller_obligations: obligations,
5669 selection_cache: traits::SelectionCache::new(),
5672 fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
5673 space: subst::ParamSpace,
5674 free_id: ast::NodeId,
5675 region_params: &[RegionParameterDef])
5677 for r in region_params.iter() {
5678 regions.push(space, ty::free_region_from_def(free_id, r));
5682 fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
5683 types: &mut subst::VecPerParamSpace<Ty<'tcx>>,
5684 space: subst::ParamSpace,
5685 defs: &[TypeParameterDef<'tcx>]) {
5686 for (i, def) in defs.iter().enumerate() {
5687 debug!("construct_parameter_environment(): push_types_from_defs: \
5688 space={} def={} index={}",
5692 let ty = ty::mk_param(tcx, space, i, def.def_id);
5693 types.push(space, ty);
5697 fn record_region_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
5698 space: subst::ParamSpace,
5699 free_substs: &Substs<'tcx>,
5700 bound_sets: &[Vec<ty::Region>]) {
5701 for (subst_region, bound_set) in
5702 free_substs.regions().get_slice(space).iter().zip(
5705 // For each region parameter 'subst...
5706 for bound_region in bound_set.iter() {
5707 // Which is declared with a bound like 'subst:'bound...
5708 match (subst_region, bound_region) {
5709 (&ty::ReFree(subst_fr), &ty::ReFree(bound_fr)) => {
5710 // Record that 'subst outlives 'bound. Or, put
5711 // another way, 'bound <= 'subst.
5712 tcx.region_maps.relate_free_regions(bound_fr, subst_fr);
5715 // All named regions are instantiated with free regions.
5717 format!("record_region_bounds: \
5718 non free region: {} / {}",
5719 subst_region.repr(tcx),
5720 bound_region.repr(tcx)).as_slice());
5729 pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
5731 ast::MutMutable => MutBorrow,
5732 ast::MutImmutable => ImmBorrow,
5736 /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow
5737 /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a
5738 /// mutability that is stronger than necessary so that it at least *would permit* the borrow in
5740 pub fn to_mutbl_lossy(self) -> ast::Mutability {
5742 MutBorrow => ast::MutMutable,
5743 ImmBorrow => ast::MutImmutable,
5745 // We have no type corresponding to a unique imm borrow, so
5746 // use `&mut`. It gives all the capabilities of an `&uniq`
5747 // and hence is a safe "over approximation".
5748 UniqueImmBorrow => ast::MutMutable,
5752 pub fn to_user_str(&self) -> &'static str {
5754 MutBorrow => "mutable",
5755 ImmBorrow => "immutable",
5756 UniqueImmBorrow => "uniquely immutable",
5761 impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> {
5762 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
5766 fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
5767 Ok(ty::node_id_to_type(self, id))
5770 fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<Ty<'tcx>> {
5771 self.method_map.borrow().get(&method_call).map(|method| method.ty)
5774 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
5778 fn is_method_call(&self, id: ast::NodeId) -> bool {
5779 self.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
5782 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
5783 self.region_maps.temporary_scope(rvalue_id)
5786 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
5787 self.upvar_borrow_map.borrow()[upvar_id].clone()
5790 fn capture_mode(&self, closure_expr_id: ast::NodeId)
5791 -> ast::CaptureClause {
5792 self.capture_modes.borrow()[closure_expr_id].clone()
5795 fn unboxed_closures<'a>(&'a self)
5796 -> &'a RefCell<DefIdMap<UnboxedClosure<'tcx>>> {
5797 &self.unboxed_closures
5801 /// The category of explicit self.
5802 #[deriving(Clone, Eq, PartialEq, Show)]
5803 pub enum ExplicitSelfCategory {
5804 StaticExplicitSelfCategory,
5805 ByValueExplicitSelfCategory,
5806 ByReferenceExplicitSelfCategory(Region, ast::Mutability),
5807 ByBoxExplicitSelfCategory,
5810 /// Pushes all the lifetimes in the given type onto the given list. A
5811 /// "lifetime in a type" is a lifetime specified by a reference or a lifetime
5812 /// in a list of type substitutions. This does *not* traverse into nominal
5813 /// types, nor does it resolve fictitious types.
5814 pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
5818 ty_rptr(region, _) => {
5819 accumulator.push(region)
5821 ty_trait(ref t) => {
5822 accumulator.push_all(t.principal.substs.regions().as_slice());
5824 ty_enum(_, ref substs) |
5825 ty_struct(_, ref substs) => {
5826 accum_substs(accumulator, substs);
5828 ty_closure(ref closure_ty) => {
5829 match closure_ty.store {
5830 RegionTraitStore(region, _) => accumulator.push(region),
5831 UniqTraitStore => {}
5834 ty_unboxed_closure(_, ref region, ref substs) => {
5835 accumulator.push(*region);
5836 accum_substs(accumulator, substs);
5857 fn accum_substs(accumulator: &mut Vec<Region>, substs: &Substs) {
5858 match substs.regions {
5859 subst::ErasedRegions => {}
5860 subst::NonerasedRegions(ref regions) => {
5861 for region in regions.iter() {
5862 accumulator.push(*region)
5869 /// A free variable referred to in a function.
5870 #[deriving(Encodable, Decodable)]
5871 pub struct Freevar {
5872 /// The variable being accessed free.
5875 // First span where it is accessed (there can be multiple).
5879 pub type FreevarMap = NodeMap<Vec<Freevar>>;
5881 pub type CaptureModeMap = NodeMap<ast::CaptureClause>;
5883 pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[Freevar]| -> T) -> T {
5884 match tcx.freevars.borrow().get(&fid) {
5886 Some(d) => f(d.as_slice())
5890 impl<'tcx> AutoAdjustment<'tcx> {
5891 pub fn is_identity(&self) -> bool {
5893 AdjustAddEnv(..) => false,
5894 AdjustDerefRef(ref r) => r.is_identity(),
5899 impl<'tcx> AutoDerefRef<'tcx> {
5900 pub fn is_identity(&self) -> bool {
5901 self.autoderefs == 0 && self.autoref.is_none()
5905 /// Replace any late-bound regions bound in `value` with free variants attached to scope-id
5907 pub fn liberate_late_bound_regions<'tcx, HR>(
5908 tcx: &ty::ctxt<'tcx>,
5909 scope: region::CodeExtent,
5912 where HR : HigherRankedFoldable<'tcx>
5914 replace_late_bound_regions(
5916 |br, _| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0
5919 /// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
5920 /// method lookup and a few other places where precise region relationships are not required.
5921 pub fn erase_late_bound_regions<'tcx, HR>(
5922 tcx: &ty::ctxt<'tcx>,
5925 where HR : HigherRankedFoldable<'tcx>
5927 replace_late_bound_regions(tcx, value, |_, _| ty::ReStatic).0
5930 /// Replaces the late-bound-regions in `value` that are bound by `value`.
5931 pub fn replace_late_bound_regions<'tcx, HR>(
5932 tcx: &ty::ctxt<'tcx>,
5934 mapf: |BoundRegion, DebruijnIndex| -> ty::Region)
5935 -> (HR, FnvHashMap<ty::BoundRegion,ty::Region>)
5936 where HR : HigherRankedFoldable<'tcx>
5938 debug!("replace_late_bound_regions({})", value.repr(tcx));
5940 let mut map = FnvHashMap::new();
5942 let mut f = ty_fold::RegionFolder::new(tcx, |region, current_depth| {
5943 debug!("region={}", region.repr(tcx));
5945 ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
5946 * match map.entry(br) {
5947 Vacant(entry) => entry.set(mapf(br, debruijn)),
5948 Occupied(entry) => entry.into_mut(),
5957 // Note: use `fold_contents` not `fold_with`. If we used
5958 // `fold_with`, it would consider the late-bound regions bound
5959 // by `value` to be bound, but we want to consider them as
5961 value.fold_contents(&mut f)
5963 debug!("resulting map: {} value: {}", map, value.repr(tcx));
5967 impl DebruijnIndex {
5968 pub fn new(depth: uint) -> DebruijnIndex {
5970 DebruijnIndex { depth: depth }
5973 pub fn shifted(&self, amount: uint) -> DebruijnIndex {
5974 DebruijnIndex { depth: self.depth + amount }
5978 impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
5979 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
5981 AdjustAddEnv(ref trait_store) => {
5982 format!("AdjustAddEnv({})", trait_store)
5984 AdjustDerefRef(ref data) => {
5991 impl<'tcx> Repr<'tcx> for UnsizeKind<'tcx> {
5992 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
5994 UnsizeLength(n) => format!("UnsizeLength({})", n),
5995 UnsizeStruct(ref k, n) => format!("UnsizeStruct({},{})", k.repr(tcx), n),
5996 UnsizeVtable(ref a, ref b) => format!("UnsizeVtable({},{})", a.repr(tcx), b.repr(tcx)),
6001 impl<'tcx> Repr<'tcx> for AutoDerefRef<'tcx> {
6002 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6003 format!("AutoDerefRef({}, {})", self.autoderefs, self.autoref.repr(tcx))
6007 impl<'tcx> Repr<'tcx> for AutoRef<'tcx> {
6008 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6010 AutoPtr(a, b, ref c) => {
6011 format!("AutoPtr({},{},{})", a.repr(tcx), b, c.repr(tcx))
6013 AutoUnsize(ref a) => {
6014 format!("AutoUnsize({})", a.repr(tcx))
6016 AutoUnsizeUniq(ref a) => {
6017 format!("AutoUnsizeUniq({})", a.repr(tcx))
6019 AutoUnsafe(ref a, ref b) => {
6020 format!("AutoUnsafe({},{})", a, b.repr(tcx))
6026 impl<'tcx> Repr<'tcx> for TyTrait<'tcx> {
6027 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6028 format!("TyTrait({},{})",
6029 self.principal.repr(tcx),
6030 self.bounds.repr(tcx))