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 pub fn type_has_escaping_regions(ty: Ty) -> bool {
676 * An "escaping region" is a bound region whose binder is not part of `t`.
678 * So, for example, consider a type like the following, which has two
681 * for<'a> fn(x: for<'b> fn(&'a int, &'b int))
682 * ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
683 * ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ inner scope
685 * This type has *bound regions* (`'a`, `'b`), but it does not
686 * have escaping regions, because the binders of both `'a` and
687 * `'b` are part of the type itself. However, if we consider the
688 * *inner fn type*, that type has an escaping region: `'a`.
690 * Note that what I'm calling an "escaping region" is often just
691 * called a "free region". However, we already use the term "free
692 * region". It refers to the regions that we use to represent
693 * bound regions on a fn definition while we are typechecking its
696 * To clarify, conceptually there is no particular difference
697 * between an "escaping" region and a "free" region. However,
698 * there is a big difference in practice. Basically, when
699 * "entering" a binding level, one is generally required to do
700 * some sort of processing to a bound region, such as replacing it
701 * with a fresh/skolemized region, or making an entry in the
702 * environment to represent the scope to which it is attached,
703 * etc. An escaping region represents a bound region for which
704 * this processing has not yet been done.
707 type_escapes_depth(ty, 0)
710 pub fn type_escapes_depth(ty: Ty, depth: uint) -> bool {
711 ty.region_depth > depth
714 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
715 pub struct BareFnTy<'tcx> {
716 pub fn_style: ast::FnStyle,
718 pub sig: FnSig<'tcx>,
721 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
722 pub struct ClosureTy<'tcx> {
723 pub fn_style: ast::FnStyle,
724 pub onceness: ast::Onceness,
725 pub store: TraitStore,
726 pub bounds: ExistentialBounds,
727 pub sig: FnSig<'tcx>,
731 #[deriving(Clone, PartialEq, Eq, Hash)]
732 pub enum FnOutput<'tcx> {
733 FnConverging(Ty<'tcx>),
737 impl<'tcx> FnOutput<'tcx> {
738 pub fn unwrap(self) -> Ty<'tcx> {
740 ty::FnConverging(t) => t,
741 ty::FnDiverging => unreachable!()
747 * Signature of a function type, which I have arbitrarily
748 * decided to use to refer to the input/output types.
750 * - `inputs` is the list of arguments and their modes.
751 * - `output` is the return type.
752 * - `variadic` indicates whether this is a varidic function. (only true for foreign fns)
754 * Note that a `FnSig` introduces a level of region binding, to
755 * account for late-bound parameters that appear in the types of the
756 * fn's arguments or the fn's return type.
758 #[deriving(Clone, PartialEq, Eq, Hash)]
759 pub struct FnSig<'tcx> {
760 pub inputs: Vec<Ty<'tcx>>,
761 pub output: FnOutput<'tcx>,
765 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
767 pub space: subst::ParamSpace,
773 * A [De Bruijn index][dbi] is a standard means of representing
774 * regions (and perhaps later types) in a higher-ranked setting. In
775 * particular, imagine a type like this:
777 * for<'a> fn(for<'b> fn(&'b int, &'a int), &'a char)
780 * | +------------+ 1 | |
782 * +--------------------------------+ 2 |
784 * +------------------------------------------+ 1
786 * In this type, there are two binders (the outer fn and the inner
787 * fn). We need to be able to determine, for any given region, which
788 * fn type it is bound by, the inner or the outer one. There are
789 * various ways you can do this, but a De Bruijn index is one of the
790 * more convenient and has some nice properties. The basic idea is to
791 * count the number of binders, inside out. Some examples should help
792 * clarify what I mean.
794 * Let's start with the reference type `&'b int` that is the first
795 * argument to the inner function. This region `'b` is assigned a De
796 * Bruijn index of 1, meaning "the innermost binder" (in this case, a
797 * fn). The region `'a` that appears in the second argument type (`&'a
798 * int`) would then be assigned a De Bruijn index of 2, meaning "the
799 * second-innermost binder". (These indices are written on the arrays
802 * What is interesting is that De Bruijn index attached to a particular
803 * variable will vary depending on where it appears. For example,
804 * the final type `&'a char` also refers to the region `'a` declared on
805 * the outermost fn. But this time, this reference is not nested within
806 * any other binders (i.e., it is not an argument to the inner fn, but
807 * rather the outer one). Therefore, in this case, it is assigned a
808 * De Bruijn index of 1, because the innermost binder in that location
811 * [dbi]: http://en.wikipedia.org/wiki/De_Bruijn_index
813 #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
814 pub struct DebruijnIndex {
815 // We maintain the invariant that this is never 0. So 1 indicates
816 // the innermost binder. To ensure this, create with `DebruijnIndex::new`.
820 /// Representation of regions:
821 #[deriving(Clone, PartialEq, Eq, Hash, Encodable, Decodable, Show)]
823 // Region bound in a type or fn declaration which will be
824 // substituted 'early' -- that is, at the same time when type
825 // parameters are substituted.
826 ReEarlyBound(/* param id */ ast::NodeId,
831 // Region bound in a function scope, which will be substituted when the
832 // function is called.
833 ReLateBound(DebruijnIndex, BoundRegion),
835 /// When checking a function body, the types of all arguments and so forth
836 /// that refer to bound region parameters are modified to refer to free
837 /// region parameters.
840 /// A concrete region naming some expression within the current function.
841 ReScope(region::CodeExtent),
843 /// Static data that has an "infinite" lifetime. Top in the region lattice.
846 /// A region variable. Should not exist after typeck.
847 ReInfer(InferRegion),
849 /// Empty lifetime is for data that is never accessed.
850 /// Bottom in the region lattice. We treat ReEmpty somewhat
851 /// specially; at least right now, we do not generate instances of
852 /// it during the GLB computations, but rather
853 /// generate an error instead. This is to improve error messages.
854 /// The only way to get an instance of ReEmpty is to have a region
855 /// variable with no constraints.
860 * Upvars do not get their own node-id. Instead, we use the pair of
861 * the original var id (that is, the root variable that is referenced
862 * by the upvar) and the id of the closure expression.
864 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
866 pub var_id: ast::NodeId,
867 pub closure_expr_id: ast::NodeId,
870 #[deriving(Clone, PartialEq, Eq, Hash, Show, Encodable, Decodable)]
871 pub enum BorrowKind {
872 /// Data must be immutable and is aliasable.
875 /// Data must be immutable but not aliasable. This kind of borrow
876 /// cannot currently be expressed by the user and is used only in
877 /// implicit closure bindings. It is needed when you the closure
878 /// is borrowing or mutating a mutable referent, e.g.:
880 /// let x: &mut int = ...;
881 /// let y = || *x += 5;
883 /// If we were to try to translate this closure into a more explicit
884 /// form, we'd encounter an error with the code as written:
886 /// struct Env { x: & &mut int }
887 /// let x: &mut int = ...;
888 /// let y = (&mut Env { &x }, fn_ptr); // Closure is pair of env and fn
889 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
891 /// This is then illegal because you cannot mutate a `&mut` found
892 /// in an aliasable location. To solve, you'd have to translate with
893 /// an `&mut` borrow:
895 /// struct Env { x: & &mut int }
896 /// let x: &mut int = ...;
897 /// let y = (&mut Env { &mut x }, fn_ptr); // changed from &x to &mut x
898 /// fn fn_ptr(env: &mut Env) { **env.x += 5; }
900 /// Now the assignment to `**env.x` is legal, but creating a
901 /// mutable pointer to `x` is not because `x` is not mutable. We
902 /// could fix this by declaring `x` as `let mut x`. This is ok in
903 /// user code, if awkward, but extra weird for closures, since the
904 /// borrow is hidden.
906 /// So we introduce a "unique imm" borrow -- the referent is
907 /// immutable, but not aliasable. This solves the problem. For
908 /// simplicity, we don't give users the way to express this
909 /// borrow, it's just used when translating closures.
912 /// Data is mutable and not aliasable.
917 * Information describing the borrowing of an upvar. This is computed
918 * during `typeck`, specifically by `regionck`. The general idea is
919 * that the compiler analyses treat closures like:
921 * let closure: &'e fn() = || {
922 * x = 1; // upvar x is assigned to
923 * use(y); // upvar y is read
924 * foo(&z); // upvar z is borrowed immutably
927 * as if they were "desugared" to something loosely like:
929 * struct Vars<'x,'y,'z> { x: &'x mut int,
932 * let closure: &'e fn() = {
938 * let env: &'e mut Vars<'x,'y,'z> = &mut Vars { x: &'x mut x,
944 * This is basically what happens at runtime. The closure is basically
945 * an existentially quantified version of the `(env, f)` pair.
947 * This data structure indicates the region and mutability of a single
948 * one of the `x...z` borrows.
950 * It may not be obvious why each borrowed variable gets its own
951 * lifetime (in the desugared version of the example, these are indicated
952 * by the lifetime parameters `'x`, `'y`, and `'z` in the `Vars` definition).
953 * Each such lifetime must encompass the lifetime `'e` of the closure itself,
954 * but need not be identical to it. The reason that this makes sense:
956 * - Callers are only permitted to invoke the closure, and hence to
957 * use the pointers, within the lifetime `'e`, so clearly `'e` must
958 * be a sublifetime of `'x...'z`.
959 * - The closure creator knows which upvars were borrowed by the closure
960 * and thus `x...z` will be reserved for `'x...'z` respectively.
961 * - Through mutation, the borrowed upvars can actually escape
962 * the closure, so sometimes it is necessary for them to be larger
963 * than the closure lifetime itself.
965 #[deriving(PartialEq, Clone, Encodable, Decodable, Show)]
966 pub struct UpvarBorrow {
967 pub kind: BorrowKind,
968 pub region: ty::Region,
971 pub type UpvarBorrowMap = FnvHashMap<UpvarId, UpvarBorrow>;
974 pub fn is_bound(&self) -> bool {
976 ty::ReEarlyBound(..) => true,
977 ty::ReLateBound(..) => true,
982 pub fn escapes_depth(&self, depth: uint) -> bool {
984 ty::ReLateBound(debruijn, _) => debruijn.depth > depth,
990 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
991 /// A "free" region `fr` can be interpreted as "some region
992 /// at least as big as the scope `fr.scope`".
993 pub struct FreeRegion {
994 pub scope: region::CodeExtent,
995 pub bound_region: BoundRegion
998 #[deriving(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Encodable, Decodable, Show)]
999 pub enum BoundRegion {
1000 /// An anonymous region parameter for a given fn (&T)
1003 /// Named region parameters for functions (a in &'a T)
1005 /// The def-id is needed to distinguish free regions in
1006 /// the event of shadowing.
1007 BrNamed(ast::DefId, ast::Name),
1009 /// Fresh bound identifiers created during GLB computations.
1012 // Anonymous region for the implicit env pointer parameter
1018 pub fn mk_prim_t<'tcx>(primitive: &'tcx TyS<'static>) -> Ty<'tcx> {
1019 // FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
1020 unsafe { &*(primitive as *const _ as *const TyS<'tcx>) }
1023 // Do not change these from static to const, interning types requires
1024 // the primitives to have a significant address.
1025 macro_rules! def_prim_tys(
1026 ($($name:ident -> $sty:expr;)*) => (
1027 $(#[inline] pub fn $name<'tcx>() -> Ty<'tcx> {
1028 static PRIM_TY: TyS<'static> = TyS {
1030 flags: NO_TYPE_FLAGS,
1041 mk_int -> ty_int(ast::TyI);
1042 mk_i8 -> ty_int(ast::TyI8);
1043 mk_i16 -> ty_int(ast::TyI16);
1044 mk_i32 -> ty_int(ast::TyI32);
1045 mk_i64 -> ty_int(ast::TyI64);
1046 mk_uint -> ty_uint(ast::TyU);
1047 mk_u8 -> ty_uint(ast::TyU8);
1048 mk_u16 -> ty_uint(ast::TyU16);
1049 mk_u32 -> ty_uint(ast::TyU32);
1050 mk_u64 -> ty_uint(ast::TyU64);
1051 mk_f32 -> ty_float(ast::TyF32);
1052 mk_f64 -> ty_float(ast::TyF64);
1056 pub fn mk_err<'tcx>() -> Ty<'tcx> {
1057 static TY_ERR: TyS<'static> = TyS {
1065 // NB: If you change this, you'll probably want to change the corresponding
1066 // AST structure in libsyntax/ast.rs as well.
1067 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
1068 pub enum sty<'tcx> {
1072 ty_uint(ast::UintTy),
1073 ty_float(ast::FloatTy),
1074 /// Substs here, possibly against intuition, *may* contain `ty_param`s.
1075 /// That is, even after substitution it is possible that there are type
1076 /// variables. This happens when the `ty_enum` corresponds to an enum
1077 /// definition and not a concrete use of it. To get the correct `ty_enum`
1078 /// from the tcx, use the `NodeId` from the `ast::Ty` and look it up in
1079 /// the `ast_ty_to_ty_cache`. This is probably true for `ty_struct` as
1081 ty_enum(DefId, Substs<'tcx>),
1084 ty_vec(Ty<'tcx>, Option<uint>), // Second field is length.
1086 ty_rptr(Region, mt<'tcx>),
1087 ty_bare_fn(BareFnTy<'tcx>),
1088 ty_closure(Box<ClosureTy<'tcx>>),
1089 ty_trait(Box<TyTrait<'tcx>>),
1090 ty_struct(DefId, Substs<'tcx>),
1091 ty_unboxed_closure(DefId, Region, Substs<'tcx>),
1092 ty_tup(Vec<Ty<'tcx>>),
1094 ty_param(ParamTy), // type parameter
1095 ty_open(Ty<'tcx>), // A deref'ed fat pointer, i.e., a dynamically sized value
1096 // and its size. Only ever used in trans. It is not necessary
1097 // earlier since we don't need to distinguish a DST with its
1098 // size (e.g., in a deref) vs a DST with the size elsewhere (
1099 // e.g., in a field).
1101 ty_infer(InferTy), // something used only during inference/typeck
1102 ty_err, // Also only used during inference/typeck, to represent
1103 // the type of an erroneous expression (helps cut down
1104 // on non-useful type error messages)
1107 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
1108 pub struct TyTrait<'tcx> {
1109 // Principal trait reference.
1110 pub principal: TraitRef<'tcx>, // would use Rc<TraitRef>, but it runs afoul of some static rules
1111 pub bounds: ExistentialBounds
1115 * A complete reference to a trait. These take numerous guises in syntax,
1116 * but perhaps the most recognizable form is in a where clause:
1120 * This would be represented by a trait-reference where the def-id is the
1121 * def-id for the trait `Foo` and the substs defines `T` as parameter 0 in the
1122 * `SelfSpace` and `U` as parameter 0 in the `TypeSpace`.
1124 * Trait references also appear in object types like `Foo<U>`, but in
1125 * that case the `Self` parameter is absent from the substitutions.
1127 * Note that a `TraitRef` introduces a level of region binding, to
1128 * account for higher-ranked trait bounds like `T : for<'a> Foo<&'a
1129 * U>` or higher-ranked object types.
1131 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
1132 pub struct TraitRef<'tcx> {
1134 pub substs: Substs<'tcx>,
1138 * Binder serves as a synthetic binder for lifetimes. It is used when
1139 * we wish to replace the escaping higher-ranked lifetimes in a type
1140 * or something else that is not itself a binder (this is because the
1141 * `replace_late_bound_regions` function replaces all lifetimes bound
1142 * by the binder supplied to it; but a type is not a binder, so you
1143 * must introduce an artificial one).
1145 #[deriving(Clone, PartialEq, Eq, Hash, Show)]
1146 pub struct Binder<T> {
1150 pub fn bind<T>(value: T) -> Binder<T> {
1151 Binder { value: value }
1154 #[deriving(Clone, PartialEq)]
1155 pub enum IntVarValue {
1156 IntType(ast::IntTy),
1157 UintType(ast::UintTy),
1160 #[deriving(Clone, Show)]
1161 pub enum terr_vstore_kind {
1168 #[deriving(Clone, Show)]
1169 pub struct expected_found<T> {
1174 // Data structures used in type unification
1175 #[deriving(Clone, Show)]
1176 pub enum type_err<'tcx> {
1178 terr_fn_style_mismatch(expected_found<FnStyle>),
1179 terr_onceness_mismatch(expected_found<Onceness>),
1180 terr_abi_mismatch(expected_found<abi::Abi>),
1182 terr_sigil_mismatch(expected_found<TraitStore>),
1183 terr_box_mutability,
1184 terr_ptr_mutability,
1185 terr_ref_mutability,
1186 terr_vec_mutability,
1187 terr_tuple_size(expected_found<uint>),
1188 terr_fixed_array_size(expected_found<uint>),
1189 terr_ty_param_size(expected_found<uint>),
1191 terr_regions_does_not_outlive(Region, Region),
1192 terr_regions_not_same(Region, Region),
1193 terr_regions_no_overlap(Region, Region),
1194 terr_regions_insufficiently_polymorphic(BoundRegion, Region),
1195 terr_regions_overly_polymorphic(BoundRegion, Region),
1196 terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
1197 terr_sorts(expected_found<Ty<'tcx>>),
1198 terr_integer_as_char,
1199 terr_int_mismatch(expected_found<IntVarValue>),
1200 terr_float_mismatch(expected_found<ast::FloatTy>),
1201 terr_traits(expected_found<ast::DefId>),
1202 terr_builtin_bounds(expected_found<BuiltinBounds>),
1203 terr_variadic_mismatch(expected_found<bool>),
1205 terr_convergence_mismatch(expected_found<bool>)
1208 /// Bounds suitable for a named type parameter like `A` in `fn foo<A>`
1209 /// as well as the existential type parameter in an object type.
1210 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
1211 pub struct ParamBounds<'tcx> {
1212 pub region_bounds: Vec<ty::Region>,
1213 pub builtin_bounds: BuiltinBounds,
1214 pub trait_bounds: Vec<Rc<TraitRef<'tcx>>>
1217 /// Bounds suitable for an existentially quantified type parameter
1218 /// such as those that appear in object types or closure types. The
1219 /// major difference between this case and `ParamBounds` is that
1220 /// general purpose trait bounds are omitted and there must be
1221 /// *exactly one* region.
1222 #[deriving(PartialEq, Eq, Hash, Clone, Show)]
1223 pub struct ExistentialBounds {
1224 pub region_bound: ty::Region,
1225 pub builtin_bounds: BuiltinBounds
1228 pub type BuiltinBounds = EnumSet<BuiltinBound>;
1230 #[deriving(Clone, Encodable, PartialEq, Eq, Decodable, Hash, Show)]
1232 pub enum BuiltinBound {
1239 pub fn empty_builtin_bounds() -> BuiltinBounds {
1243 pub fn all_builtin_bounds() -> BuiltinBounds {
1244 let mut set = EnumSet::new();
1245 set.insert(BoundSend);
1246 set.insert(BoundSized);
1247 set.insert(BoundSync);
1251 pub fn region_existential_bound(r: ty::Region) -> ExistentialBounds {
1253 * An existential bound that does not implement any traits.
1256 ty::ExistentialBounds { region_bound: r,
1257 builtin_bounds: empty_builtin_bounds() }
1260 impl CLike for BuiltinBound {
1261 fn to_uint(&self) -> uint {
1264 fn from_uint(v: uint) -> BuiltinBound {
1265 unsafe { mem::transmute(v) }
1269 #[deriving(Clone, PartialEq, Eq, Hash)]
1274 #[deriving(Clone, PartialEq, Eq, Hash)]
1279 #[deriving(Clone, PartialEq, Eq, Hash)]
1280 pub struct FloatVid {
1284 #[deriving(Clone, PartialEq, Eq, Encodable, Decodable, Hash)]
1285 pub struct RegionVid {
1289 #[deriving(Clone, PartialEq, Eq, Hash)]
1296 // FIXME -- once integral fallback is impl'd, we should remove
1297 // this type. It's only needed to prevent spurious errors for
1298 // integers whose type winds up never being constrained.
1299 SkolemizedIntTy(uint),
1302 #[deriving(Clone, Encodable, Decodable, Eq, Hash, Show)]
1303 pub enum InferRegion {
1305 ReSkolemized(uint, BoundRegion)
1308 impl cmp::PartialEq for InferRegion {
1309 fn eq(&self, other: &InferRegion) -> bool {
1310 match ((*self), *other) {
1311 (ReVar(rva), ReVar(rvb)) => {
1314 (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
1320 fn ne(&self, other: &InferRegion) -> bool {
1321 !((*self) == (*other))
1325 impl fmt::Show for TyVid {
1326 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result{
1327 write!(f, "_#{}t", self.index)
1331 impl fmt::Show for IntVid {
1332 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1333 write!(f, "_#{}i", self.index)
1337 impl fmt::Show for FloatVid {
1338 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1339 write!(f, "_#{}f", self.index)
1343 impl fmt::Show for RegionVid {
1344 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1345 write!(f, "'_#{}r", self.index)
1349 impl<'tcx> fmt::Show for FnSig<'tcx> {
1350 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1351 // grr, without tcx not much we can do.
1356 impl fmt::Show for InferTy {
1357 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1359 TyVar(ref v) => v.fmt(f),
1360 IntVar(ref v) => v.fmt(f),
1361 FloatVar(ref v) => v.fmt(f),
1362 SkolemizedTy(v) => write!(f, "SkolemizedTy({})", v),
1363 SkolemizedIntTy(v) => write!(f, "SkolemizedIntTy({})", v),
1368 impl fmt::Show for IntVarValue {
1369 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1371 IntType(ref v) => v.fmt(f),
1372 UintType(ref v) => v.fmt(f),
1377 #[deriving(Clone, Show)]
1378 pub struct TypeParameterDef<'tcx> {
1379 pub name: ast::Name,
1380 pub def_id: ast::DefId,
1381 pub space: subst::ParamSpace,
1383 pub associated_with: Option<ast::DefId>,
1384 pub bounds: ParamBounds<'tcx>,
1385 pub default: Option<Ty<'tcx>>,
1388 #[deriving(Encodable, Decodable, Clone, Show)]
1389 pub struct RegionParameterDef {
1390 pub name: ast::Name,
1391 pub def_id: ast::DefId,
1392 pub space: subst::ParamSpace,
1394 pub bounds: Vec<ty::Region>,
1397 /// Information about the type/lifetime parameters associated with an
1398 /// item or method. Analogous to ast::Generics.
1399 #[deriving(Clone, Show)]
1400 pub struct Generics<'tcx> {
1401 pub types: VecPerParamSpace<TypeParameterDef<'tcx>>,
1402 pub regions: VecPerParamSpace<RegionParameterDef>,
1405 impl<'tcx> Generics<'tcx> {
1406 pub fn empty() -> Generics<'tcx> {
1407 Generics { types: VecPerParamSpace::empty(),
1408 regions: VecPerParamSpace::empty() }
1411 pub fn has_type_params(&self, space: subst::ParamSpace) -> bool {
1412 !self.types.is_empty_in(space)
1415 pub fn has_region_params(&self, space: subst::ParamSpace) -> bool {
1416 !self.regions.is_empty_in(space)
1419 pub fn to_bounds(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>)
1420 -> GenericBounds<'tcx> {
1422 types: self.types.map(|d| d.bounds.subst(tcx, substs)),
1423 regions: self.regions.map(|d| d.bounds.subst(tcx, substs)),
1429 * Represents the bounds declared on a particular set of type
1430 * parameters. Should eventually be generalized into a flag list of
1431 * where clauses. You can obtain a `GenericBounds` list from a
1432 * `Generics` by using the `to_bounds` method. Note that this method
1433 * reflects an important semantic invariant of `GenericBounds`: while
1434 * the bounds in a `Generics` are expressed in terms of the bound type
1435 * parameters of the impl/trait/whatever, a `GenericBounds` instance
1436 * represented a set of bounds for some particular instantiation,
1437 * meaning that the generic parameters have been substituted with
1442 * struct Foo<T,U:Bar<T>> { ... }
1444 * Here, the `Generics` for `Foo` would contain a list of bounds like
1445 * `[[], [U:Bar<T>]]`. Now if there were some particular reference
1446 * like `Foo<int,uint>`, then the `GenericBounds` would be `[[],
1447 * [uint:Bar<int>]]`.
1449 #[deriving(Clone, Show)]
1450 pub struct GenericBounds<'tcx> {
1451 pub types: VecPerParamSpace<ParamBounds<'tcx>>,
1452 pub regions: VecPerParamSpace<Vec<Region>>,
1455 impl<'tcx> GenericBounds<'tcx> {
1456 pub fn empty() -> GenericBounds<'tcx> {
1457 GenericBounds { types: VecPerParamSpace::empty(),
1458 regions: VecPerParamSpace::empty() }
1461 pub fn has_escaping_regions(&self) -> bool {
1462 self.types.any(|pb| pb.trait_bounds.iter().any(|tr| tr.has_escaping_regions())) ||
1463 self.regions.any(|rs| rs.iter().any(|r| r.escapes_depth(0)))
1467 impl<'tcx> TraitRef<'tcx> {
1468 pub fn new(def_id: ast::DefId, substs: Substs<'tcx>) -> TraitRef<'tcx> {
1469 TraitRef { def_id: def_id, substs: substs }
1472 pub fn self_ty(&self) -> Ty<'tcx> {
1473 self.substs.self_ty().unwrap()
1476 pub fn input_types(&self) -> &[Ty<'tcx>] {
1477 // Select only the "input types" from a trait-reference. For
1478 // now this is all the types that appear in the
1479 // trait-reference, but it should eventually exclude
1480 // associated types.
1481 self.substs.types.as_slice()
1484 pub fn has_escaping_regions(&self) -> bool {
1485 self.substs.has_regions_escaping_depth(1)
1488 pub fn has_bound_regions(&self) -> bool {
1489 self.substs.has_regions_escaping_depth(0)
1493 /// When type checking, we use the `ParameterEnvironment` to track
1494 /// details about the type/lifetime parameters that are in scope.
1495 /// It primarily stores the bounds information.
1497 /// Note: This information might seem to be redundant with the data in
1498 /// `tcx.ty_param_defs`, but it is not. That table contains the
1499 /// parameter definitions from an "outside" perspective, but this
1500 /// struct will contain the bounds for a parameter as seen from inside
1501 /// the function body. Currently the only real distinction is that
1502 /// bound lifetime parameters are replaced with free ones, but in the
1503 /// future I hope to refine the representation of types so as to make
1504 /// more distinctions clearer.
1505 pub struct ParameterEnvironment<'tcx> {
1506 /// A substitution that can be applied to move from
1507 /// the "outer" view of a type or method to the "inner" view.
1508 /// In general, this means converting from bound parameters to
1509 /// free parameters. Since we currently represent bound/free type
1510 /// parameters in the same way, this only has an effect on regions.
1511 pub free_substs: Substs<'tcx>,
1513 /// Bounds on the various type parameters
1514 pub bounds: VecPerParamSpace<ParamBounds<'tcx>>,
1516 /// Each type parameter has an implicit region bound that
1517 /// indicates it must outlive at least the function body (the user
1518 /// may specify stronger requirements). This field indicates the
1519 /// region of the callee.
1520 pub implicit_region_bound: ty::Region,
1522 /// Obligations that the caller must satisfy. This is basically
1523 /// the set of bounds on the in-scope type parameters, translated
1524 /// into Obligations.
1526 /// Note: This effectively *duplicates* the `bounds` array for
1528 pub caller_obligations: VecPerParamSpace<traits::Obligation<'tcx>>,
1530 /// Caches the results of trait selection. This cache is used
1531 /// for things that have to do with the parameters in scope.
1532 pub selection_cache: traits::SelectionCache<'tcx>,
1535 impl<'tcx> ParameterEnvironment<'tcx> {
1536 pub fn for_item(cx: &ctxt<'tcx>, id: NodeId) -> ParameterEnvironment<'tcx> {
1537 match cx.map.find(id) {
1538 Some(ast_map::NodeImplItem(ref impl_item)) => {
1540 ast::MethodImplItem(ref method) => {
1541 let method_def_id = ast_util::local_def(id);
1542 match ty::impl_or_trait_item(cx, method_def_id) {
1543 MethodTraitItem(ref method_ty) => {
1544 let method_generics = &method_ty.generics;
1545 construct_parameter_environment(
1549 method.pe_body().id)
1551 TypeTraitItem(_) => {
1553 .bug("ParameterEnvironment::from_item(): \
1554 can't create a parameter environment \
1555 for type trait items")
1559 ast::TypeImplItem(_) => {
1560 cx.sess.bug("ParameterEnvironment::from_item(): \
1561 can't create a parameter environment \
1562 for type impl items")
1566 Some(ast_map::NodeTraitItem(trait_method)) => {
1567 match *trait_method {
1568 ast::RequiredMethod(ref required) => {
1569 cx.sess.span_bug(required.span,
1570 "ParameterEnvironment::from_item():
1571 can't create a parameter \
1572 environment for required trait \
1575 ast::ProvidedMethod(ref method) => {
1576 let method_def_id = ast_util::local_def(id);
1577 match ty::impl_or_trait_item(cx, method_def_id) {
1578 MethodTraitItem(ref method_ty) => {
1579 let method_generics = &method_ty.generics;
1580 construct_parameter_environment(
1584 method.pe_body().id)
1586 TypeTraitItem(_) => {
1588 .bug("ParameterEnvironment::from_item(): \
1589 can't create a parameter environment \
1590 for type trait items")
1594 ast::TypeTraitItem(_) => {
1595 cx.sess.bug("ParameterEnvironment::from_item(): \
1596 can't create a parameter environment \
1597 for type trait items")
1601 Some(ast_map::NodeItem(item)) => {
1603 ast::ItemFn(_, _, _, _, ref body) => {
1604 // We assume this is a function.
1605 let fn_def_id = ast_util::local_def(id);
1606 let fn_pty = ty::lookup_item_type(cx, fn_def_id);
1608 construct_parameter_environment(cx,
1614 ast::ItemStruct(..) |
1616 ast::ItemConst(..) |
1617 ast::ItemStatic(..) => {
1618 let def_id = ast_util::local_def(id);
1619 let pty = ty::lookup_item_type(cx, def_id);
1620 construct_parameter_environment(cx, item.span,
1624 cx.sess.span_bug(item.span,
1625 "ParameterEnvironment::from_item():
1626 can't create a parameter \
1627 environment for this kind of item")
1632 cx.sess.bug(format!("ParameterEnvironment::from_item(): \
1633 `{}` is not an item",
1634 cx.map.node_to_string(id)).as_slice())
1642 /// - `generics`: the set of type parameters and their bounds
1643 /// - `ty`: the base types, which may reference the parameters defined
1645 #[deriving(Clone, Show)]
1646 pub struct Polytype<'tcx> {
1647 pub generics: Generics<'tcx>,
1651 /// As `Polytype` but for a trait ref.
1652 pub struct TraitDef<'tcx> {
1653 /// Generic type definitions. Note that `Self` is listed in here
1654 /// as having a single bound, the trait itself (e.g., in the trait
1655 /// `Eq`, there is a single bound `Self : Eq`). This is so that
1656 /// default methods get to assume that the `Self` parameters
1657 /// implements the trait.
1658 pub generics: Generics<'tcx>,
1660 /// The "supertrait" bounds.
1661 pub bounds: ParamBounds<'tcx>,
1662 pub trait_ref: Rc<ty::TraitRef<'tcx>>,
1665 /// Records the substitutions used to translate the polytype for an
1666 /// item into the monotype of an item reference.
1668 pub struct ItemSubsts<'tcx> {
1669 pub substs: Substs<'tcx>,
1672 /// Records information about each unboxed closure.
1674 pub struct UnboxedClosure<'tcx> {
1675 /// The type of the unboxed closure.
1676 pub closure_type: ClosureTy<'tcx>,
1677 /// The kind of unboxed closure this is.
1678 pub kind: UnboxedClosureKind,
1681 #[deriving(Clone, PartialEq, Eq, Show)]
1682 pub enum UnboxedClosureKind {
1683 FnUnboxedClosureKind,
1684 FnMutUnboxedClosureKind,
1685 FnOnceUnboxedClosureKind,
1688 impl UnboxedClosureKind {
1689 pub fn trait_did(&self, cx: &ctxt) -> ast::DefId {
1690 let result = match *self {
1691 FnUnboxedClosureKind => cx.lang_items.require(FnTraitLangItem),
1692 FnMutUnboxedClosureKind => {
1693 cx.lang_items.require(FnMutTraitLangItem)
1695 FnOnceUnboxedClosureKind => {
1696 cx.lang_items.require(FnOnceTraitLangItem)
1700 Ok(trait_did) => trait_did,
1701 Err(err) => cx.sess.fatal(err.as_slice()),
1706 pub fn mk_ctxt<'tcx>(s: Session,
1707 type_arena: &'tcx TypedArena<TyS<'tcx>>,
1708 dm: resolve::DefMap,
1709 named_region_map: resolve_lifetime::NamedRegionMap,
1710 map: ast_map::Map<'tcx>,
1711 freevars: RefCell<FreevarMap>,
1712 capture_modes: RefCell<CaptureModeMap>,
1713 region_maps: middle::region::RegionMaps,
1714 lang_items: middle::lang_items::LanguageItems,
1715 stability: stability::Index) -> ctxt<'tcx> {
1717 type_arena: type_arena,
1718 interner: RefCell::new(FnvHashMap::new()),
1719 named_region_map: named_region_map,
1720 item_variance_map: RefCell::new(DefIdMap::new()),
1721 variance_computed: Cell::new(false),
1724 region_maps: region_maps,
1725 node_types: RefCell::new(FnvHashMap::new()),
1726 item_substs: RefCell::new(NodeMap::new()),
1727 trait_refs: RefCell::new(NodeMap::new()),
1728 trait_defs: RefCell::new(DefIdMap::new()),
1729 object_cast_map: RefCell::new(NodeMap::new()),
1731 intrinsic_defs: RefCell::new(DefIdMap::new()),
1733 tcache: RefCell::new(DefIdMap::new()),
1734 rcache: RefCell::new(FnvHashMap::new()),
1735 short_names_cache: RefCell::new(FnvHashMap::new()),
1736 needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()),
1737 tc_cache: RefCell::new(FnvHashMap::new()),
1738 ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
1739 enum_var_cache: RefCell::new(DefIdMap::new()),
1740 impl_or_trait_items: RefCell::new(DefIdMap::new()),
1741 trait_item_def_ids: RefCell::new(DefIdMap::new()),
1742 trait_items_cache: RefCell::new(DefIdMap::new()),
1743 impl_trait_cache: RefCell::new(DefIdMap::new()),
1744 ty_param_defs: RefCell::new(NodeMap::new()),
1745 adjustments: RefCell::new(NodeMap::new()),
1746 normalized_cache: RefCell::new(FnvHashMap::new()),
1747 lang_items: lang_items,
1748 provided_method_sources: RefCell::new(DefIdMap::new()),
1749 struct_fields: RefCell::new(DefIdMap::new()),
1750 destructor_for_type: RefCell::new(DefIdMap::new()),
1751 destructors: RefCell::new(DefIdSet::new()),
1752 trait_impls: RefCell::new(DefIdMap::new()),
1753 inherent_impls: RefCell::new(DefIdMap::new()),
1754 impl_items: RefCell::new(DefIdMap::new()),
1755 used_unsafe: RefCell::new(NodeSet::new()),
1756 used_mut_nodes: RefCell::new(NodeSet::new()),
1757 populated_external_types: RefCell::new(DefIdSet::new()),
1758 populated_external_traits: RefCell::new(DefIdSet::new()),
1759 upvar_borrow_map: RefCell::new(FnvHashMap::new()),
1760 extern_const_statics: RefCell::new(DefIdMap::new()),
1761 extern_const_variants: RefCell::new(DefIdMap::new()),
1762 method_map: RefCell::new(FnvHashMap::new()),
1763 dependency_formats: RefCell::new(FnvHashMap::new()),
1764 unboxed_closures: RefCell::new(DefIdMap::new()),
1765 node_lint_levels: RefCell::new(FnvHashMap::new()),
1766 transmute_restrictions: RefCell::new(Vec::new()),
1767 stability: RefCell::new(stability),
1768 capture_modes: capture_modes,
1769 associated_types: RefCell::new(DefIdMap::new()),
1770 selection_cache: traits::SelectionCache::new(),
1771 repr_hint_cache: RefCell::new(DefIdMap::new()),
1775 // Type constructors
1777 // Interns a type/name combination, stores the resulting box in cx.interner,
1778 // and returns the box as cast to an unsafe ptr (see comments for Ty above).
1779 pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: sty<'tcx>) -> Ty<'tcx> {
1780 // Check for primitive types.
1782 ty_err => return mk_err(),
1783 ty_bool => return mk_bool(),
1784 ty_int(i) => return mk_mach_int(i),
1785 ty_uint(u) => return mk_mach_uint(u),
1786 ty_float(f) => return mk_mach_float(f),
1787 ty_char => return mk_char(),
1791 match cx.interner.borrow().get(&st) {
1792 Some(ty) => return *ty,
1796 let flags = FlagComputation::for_sty(&st);
1798 let ty = cx.type_arena.alloc(TyS {
1801 region_depth: flags.depth,
1804 cx.interner.borrow_mut().insert(InternedTy { ty: ty }, ty);
1809 struct FlagComputation {
1812 // maximum depth of any bound region that we have seen thus far
1816 impl FlagComputation {
1817 fn new() -> FlagComputation {
1818 FlagComputation { flags: NO_TYPE_FLAGS, depth: 0 }
1821 fn for_sty(st: &sty) -> FlagComputation {
1822 let mut result = FlagComputation::new();
1827 fn add_flags(&mut self, flags: TypeFlags) {
1828 self.flags = self.flags | flags;
1831 fn add_depth(&mut self, depth: uint) {
1832 if depth > self.depth {
1837 fn add_bound_computation(&mut self, computation: &FlagComputation) {
1839 * Adds the flags/depth from a set of types that appear within
1840 * the current type, but within a region binder.
1843 self.add_flags(computation.flags);
1845 // The types that contributed to `computation` occured within
1846 // a region binder, so subtract one from the region depth
1847 // within when adding the depth to `self`.
1848 let depth = computation.depth;
1850 self.add_depth(depth - 1);
1854 fn add_sty(&mut self, st: &sty) {
1864 // You might think that we could just return ty_err for
1865 // any type containing ty_err as a component, and get
1866 // rid of the HAS_TY_ERR flag -- likewise for ty_bot (with
1867 // the exception of function types that return bot).
1868 // But doing so caused sporadic memory corruption, and
1869 // neither I (tjc) nor nmatsakis could figure out why,
1870 // so we're doing it this way.
1872 self.add_flags(HAS_TY_ERR)
1875 &ty_param(ref p) => {
1876 if p.space == subst::SelfSpace {
1877 self.add_flags(HAS_SELF);
1879 self.add_flags(HAS_PARAMS);
1883 &ty_unboxed_closure(_, ref region, ref substs) => {
1884 self.add_region(*region);
1885 self.add_substs(substs);
1889 self.add_flags(HAS_TY_INFER)
1892 &ty_enum(_, ref substs) | &ty_struct(_, ref substs) => {
1893 self.add_substs(substs);
1896 &ty_trait(box TyTrait { ref principal, ref bounds }) => {
1897 let mut computation = FlagComputation::new();
1898 computation.add_substs(&principal.substs);
1899 self.add_bound_computation(&computation);
1901 self.add_bounds(bounds);
1904 &ty_uniq(tt) | &ty_vec(tt, _) | &ty_open(tt) => {
1912 &ty_rptr(r, ref m) => {
1917 &ty_tup(ref ts) => {
1921 &ty_bare_fn(ref f) => {
1922 self.add_fn_sig(&f.sig);
1925 &ty_closure(ref f) => {
1927 RegionTraitStore(r, _) => {
1932 self.add_fn_sig(&f.sig);
1933 self.add_bounds(&f.bounds);
1938 fn add_ty(&mut self, ty: Ty) {
1939 self.add_flags(ty.flags);
1940 self.add_depth(ty.region_depth);
1943 fn add_tys(&mut self, tys: &[Ty]) {
1944 for &ty in tys.iter() {
1949 fn add_fn_sig(&mut self, fn_sig: &FnSig) {
1950 let mut computation = FlagComputation::new();
1952 computation.add_tys(fn_sig.inputs[]);
1954 if let ty::FnConverging(output) = fn_sig.output {
1955 computation.add_ty(output);
1958 self.add_bound_computation(&computation);
1961 fn add_region(&mut self, r: Region) {
1962 self.add_flags(HAS_REGIONS);
1964 ty::ReInfer(_) => { self.add_flags(HAS_RE_INFER); }
1965 ty::ReLateBound(debruijn, _) => {
1966 self.add_flags(HAS_RE_LATE_BOUND);
1967 self.add_depth(debruijn.depth);
1973 fn add_substs(&mut self, substs: &Substs) {
1974 self.add_tys(substs.types.as_slice());
1975 match substs.regions {
1976 subst::ErasedRegions => {}
1977 subst::NonerasedRegions(ref regions) => {
1978 for &r in regions.iter() {
1985 fn add_bounds(&mut self, bounds: &ExistentialBounds) {
1986 self.add_region(bounds.region_bound);
1990 pub fn mk_mach_int<'tcx>(tm: ast::IntTy) -> Ty<'tcx> {
1992 ast::TyI => mk_int(),
1993 ast::TyI8 => mk_i8(),
1994 ast::TyI16 => mk_i16(),
1995 ast::TyI32 => mk_i32(),
1996 ast::TyI64 => mk_i64(),
2000 pub fn mk_mach_uint<'tcx>(tm: ast::UintTy) -> Ty<'tcx> {
2002 ast::TyU => mk_uint(),
2003 ast::TyU8 => mk_u8(),
2004 ast::TyU16 => mk_u16(),
2005 ast::TyU32 => mk_u32(),
2006 ast::TyU64 => mk_u64(),
2010 pub fn mk_mach_float<'tcx>(tm: ast::FloatTy) -> Ty<'tcx> {
2012 ast::TyF32 => mk_f32(),
2013 ast::TyF64 => mk_f64(),
2017 pub fn mk_str<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
2021 pub fn mk_str_slice<'tcx>(cx: &ctxt<'tcx>, r: Region, m: ast::Mutability) -> Ty<'tcx> {
2024 ty: mk_t(cx, ty_str),
2029 pub fn mk_enum<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: Substs<'tcx>) -> Ty<'tcx> {
2030 // take a copy of substs so that we own the vectors inside
2031 mk_t(cx, ty_enum(did, substs))
2034 pub fn mk_uniq<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_uniq(ty)) }
2036 pub fn mk_ptr<'tcx>(cx: &ctxt<'tcx>, tm: mt<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_ptr(tm)) }
2038 pub fn mk_rptr<'tcx>(cx: &ctxt<'tcx>, r: Region, tm: mt<'tcx>) -> Ty<'tcx> {
2039 mk_t(cx, ty_rptr(r, tm))
2042 pub fn mk_mut_rptr<'tcx>(cx: &ctxt<'tcx>, r: Region, ty: Ty<'tcx>) -> Ty<'tcx> {
2043 mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutMutable})
2045 pub fn mk_imm_rptr<'tcx>(cx: &ctxt<'tcx>, r: Region, ty: Ty<'tcx>) -> Ty<'tcx> {
2046 mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutImmutable})
2049 pub fn mk_mut_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2050 mk_ptr(cx, mt {ty: ty, mutbl: ast::MutMutable})
2053 pub fn mk_imm_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2054 mk_ptr(cx, mt {ty: ty, mutbl: ast::MutImmutable})
2057 pub fn mk_nil_ptr<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
2058 mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::MutImmutable})
2061 pub fn mk_vec<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, sz: Option<uint>) -> Ty<'tcx> {
2062 mk_t(cx, ty_vec(ty, sz))
2065 pub fn mk_slice<'tcx>(cx: &ctxt<'tcx>, r: Region, tm: mt<'tcx>) -> Ty<'tcx> {
2068 ty: mk_vec(cx, tm.ty, None),
2073 pub fn mk_tup<'tcx>(cx: &ctxt<'tcx>, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
2074 mk_t(cx, ty_tup(ts))
2077 pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
2078 mk_tup(cx, Vec::new())
2081 pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, fty: ClosureTy<'tcx>) -> Ty<'tcx> {
2082 mk_t(cx, ty_closure(box fty))
2085 pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>, fty: BareFnTy<'tcx>) -> Ty<'tcx> {
2086 mk_t(cx, ty_bare_fn(fty))
2089 pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
2090 input_tys: &[Ty<'tcx>],
2091 output: Ty<'tcx>) -> Ty<'tcx> {
2092 let input_args = input_tys.iter().map(|ty| *ty).collect();
2095 fn_style: ast::NormalFn,
2099 output: ty::FnConverging(output),
2106 pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
2107 principal: ty::TraitRef<'tcx>,
2108 bounds: ExistentialBounds)
2110 // take a copy of substs so that we own the vectors inside
2111 let inner = box TyTrait {
2112 principal: principal,
2115 mk_t(cx, ty_trait(inner))
2118 pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId,
2119 substs: Substs<'tcx>) -> Ty<'tcx> {
2120 // take a copy of substs so that we own the vectors inside
2121 mk_t(cx, ty_struct(struct_id, substs))
2124 pub fn mk_unboxed_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId,
2125 region: Region, substs: Substs<'tcx>)
2127 mk_t(cx, ty_unboxed_closure(closure_id, region, substs))
2130 pub fn mk_var<'tcx>(cx: &ctxt<'tcx>, v: TyVid) -> Ty<'tcx> {
2131 mk_infer(cx, TyVar(v))
2134 pub fn mk_int_var<'tcx>(cx: &ctxt<'tcx>, v: IntVid) -> Ty<'tcx> {
2135 mk_infer(cx, IntVar(v))
2138 pub fn mk_float_var<'tcx>(cx: &ctxt<'tcx>, v: FloatVid) -> Ty<'tcx> {
2139 mk_infer(cx, FloatVar(v))
2142 pub fn mk_infer<'tcx>(cx: &ctxt<'tcx>, it: InferTy) -> Ty<'tcx> {
2143 mk_t(cx, ty_infer(it))
2146 pub fn mk_param<'tcx>(cx: &ctxt<'tcx>, space: subst::ParamSpace,
2147 n: uint, k: DefId) -> Ty<'tcx> {
2148 mk_t(cx, ty_param(ParamTy { space: space, idx: n, def_id: k }))
2151 pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId) -> Ty<'tcx> {
2152 mk_param(cx, subst::SelfSpace, 0, did)
2155 pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'tcx> {
2156 mk_param(cx, def.space, def.index, def.def_id)
2159 pub fn mk_open<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, ty_open(ty)) }
2161 pub fn walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>|) {
2162 maybe_walk_ty(ty, |ty| { f(ty); true });
2165 pub fn maybe_walk_ty<'tcx>(ty: Ty<'tcx>, f: |Ty<'tcx>| -> bool) {
2170 ty_bool | ty_char | ty_int(_) | ty_uint(_) | ty_float(_) |
2171 ty_str | ty_infer(_) | ty_param(_) | ty_err => {}
2172 ty_uniq(ty) | ty_vec(ty, _) | ty_open(ty) => maybe_walk_ty(ty, f),
2173 ty_ptr(ref tm) | ty_rptr(_, ref tm) => {
2174 maybe_walk_ty(tm.ty, f);
2176 ty_trait(box TyTrait { ref principal, .. }) => {
2177 for subty in principal.substs.types.iter() {
2178 maybe_walk_ty(*subty, |x| f(x));
2181 ty_enum(_, ref substs) |
2182 ty_struct(_, ref substs) |
2183 ty_unboxed_closure(_, _, ref substs) => {
2184 for subty in substs.types.iter() {
2185 maybe_walk_ty(*subty, |x| f(x));
2188 ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
2189 ty_bare_fn(ref ft) => {
2190 for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
2191 if let ty::FnConverging(output) = ft.sig.output {
2192 maybe_walk_ty(output, f);
2195 ty_closure(ref ft) => {
2196 for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
2197 if let ty::FnConverging(output) = ft.sig.output {
2198 maybe_walk_ty(output, f);
2204 // Folds types from the bottom up.
2205 pub fn fold_ty<'tcx>(cx: &ctxt<'tcx>, t0: Ty<'tcx>,
2206 fldop: |Ty<'tcx>| -> Ty<'tcx>)
2208 let mut f = ty_fold::BottomUpFolder {tcx: cx, fldop: fldop};
2213 pub fn new(space: subst::ParamSpace,
2217 ParamTy { space: space, idx: index, def_id: def_id }
2220 pub fn for_self(trait_def_id: ast::DefId) -> ParamTy {
2221 ParamTy::new(subst::SelfSpace, 0, trait_def_id)
2224 pub fn for_def(def: &TypeParameterDef) -> ParamTy {
2225 ParamTy::new(def.space, def.index, def.def_id)
2228 pub fn to_ty<'tcx>(self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
2229 ty::mk_param(tcx, self.space, self.idx, self.def_id)
2232 pub fn is_self(&self) -> bool {
2233 self.space == subst::SelfSpace && self.idx == 0
2237 impl<'tcx> ItemSubsts<'tcx> {
2238 pub fn empty() -> ItemSubsts<'tcx> {
2239 ItemSubsts { substs: Substs::empty() }
2242 pub fn is_noop(&self) -> bool {
2243 self.substs.is_noop()
2247 impl<'tcx> ParamBounds<'tcx> {
2248 pub fn empty() -> ParamBounds<'tcx> {
2250 builtin_bounds: empty_builtin_bounds(),
2251 trait_bounds: Vec::new(),
2252 region_bounds: Vec::new(),
2259 pub fn type_is_nil(ty: Ty) -> bool {
2261 ty_tup(ref tys) => tys.is_empty(),
2266 pub fn type_is_error(ty: Ty) -> bool {
2267 ty.flags.intersects(HAS_TY_ERR)
2270 pub fn type_needs_subst(ty: Ty) -> bool {
2271 ty.flags.intersects(NEEDS_SUBST)
2274 pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
2275 tref.substs.types.any(|&ty| type_is_error(ty))
2278 pub fn type_is_ty_var(ty: Ty) -> bool {
2280 ty_infer(TyVar(_)) => true,
2285 pub fn type_is_bool(ty: Ty) -> bool { ty.sty == ty_bool }
2287 pub fn type_is_self(ty: Ty) -> bool {
2289 ty_param(ref p) => p.space == subst::SelfSpace,
2294 fn type_is_slice(ty: Ty) -> bool {
2296 ty_ptr(mt) | ty_rptr(_, mt) => match mt.ty.sty {
2297 ty_vec(_, None) | ty_str => true,
2304 pub fn type_is_vec(ty: Ty) -> bool {
2307 ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..}) |
2308 ty_uniq(ty) => match ty.sty {
2309 ty_vec(_, None) => true,
2316 pub fn type_is_structural(ty: Ty) -> bool {
2318 ty_struct(..) | ty_tup(_) | ty_enum(..) | ty_closure(_) |
2319 ty_vec(_, Some(_)) | ty_unboxed_closure(..) => true,
2320 _ => type_is_slice(ty) | type_is_trait(ty)
2324 pub fn type_is_simd(cx: &ctxt, ty: Ty) -> bool {
2326 ty_struct(did, _) => lookup_simd(cx, did),
2331 pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2333 ty_vec(ty, _) => ty,
2334 ty_str => mk_mach_uint(ast::TyU8),
2335 ty_open(ty) => sequence_element_type(cx, ty),
2336 _ => cx.sess.bug(format!("sequence_element_type called on non-sequence value: {}",
2337 ty_to_string(cx, ty)).as_slice()),
2341 pub fn simd_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
2343 ty_struct(did, ref substs) => {
2344 let fields = lookup_struct_fields(cx, did);
2345 lookup_field_type(cx, did, fields[0].id, substs)
2347 _ => panic!("simd_type called on invalid type")
2351 pub fn simd_size(cx: &ctxt, ty: Ty) -> uint {
2353 ty_struct(did, _) => {
2354 let fields = lookup_struct_fields(cx, did);
2357 _ => panic!("simd_size called on invalid type")
2361 pub fn type_is_region_ptr(ty: Ty) -> bool {
2363 ty_rptr(..) => true,
2368 pub fn type_is_unsafe_ptr(ty: Ty) -> bool {
2370 ty_ptr(_) => return true,
2375 pub fn type_is_unique(ty: Ty) -> bool {
2377 ty_uniq(_) => match ty.sty {
2378 ty_trait(..) => false,
2385 pub fn type_is_fat_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2387 ty_ptr(mt{ty, ..}) | ty_rptr(_, mt{ty, ..})
2388 | ty_uniq(ty) if !type_is_sized(cx, ty) => true,
2394 A scalar type is one that denotes an atomic datum, with no sub-components.
2395 (A ty_ptr is scalar because it represents a non-managed pointer, so its
2396 contents are abstract to rustc.)
2398 pub fn type_is_scalar(ty: Ty) -> bool {
2400 ty_bool | ty_char | ty_int(_) | ty_float(_) | ty_uint(_) |
2401 ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) |
2402 ty_bare_fn(..) | ty_ptr(_) => true,
2403 ty_tup(ref tys) if tys.is_empty() => true,
2408 /// Returns true if this type is a floating point type and false otherwise.
2409 pub fn type_is_floating_point(ty: Ty) -> bool {
2411 ty_float(_) => true,
2416 pub fn type_needs_drop<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2417 type_contents(cx, ty).needs_drop(cx)
2420 // Some things don't need cleanups during unwinding because the
2421 // task can free them all at once later. Currently only things
2422 // that only contain scalars and shared boxes can avoid unwind
2424 pub fn type_needs_unwind_cleanup<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2425 return memoized(&cx.needs_unwind_cleanup_cache, ty, |ty| {
2426 type_needs_unwind_cleanup_(cx, ty, &mut FnvHashSet::new())
2429 fn type_needs_unwind_cleanup_<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>,
2430 tycache: &mut FnvHashSet<Ty<'tcx>>) -> bool {
2431 // Prevent infinite recursion
2432 if !tycache.insert(ty) {
2436 let mut needs_unwind_cleanup = false;
2437 maybe_walk_ty(ty, |ty| {
2438 needs_unwind_cleanup |= match ty.sty {
2439 ty_bool | ty_int(_) | ty_uint(_) |
2440 ty_float(_) | ty_tup(_) | ty_ptr(_) => false,
2442 ty_enum(did, ref substs) =>
2443 enum_variants(cx, did).iter().any(|v|
2444 v.args.iter().any(|aty| {
2445 let t = aty.subst(cx, substs);
2446 type_needs_unwind_cleanup_(cx, t, tycache)
2452 !needs_unwind_cleanup
2454 needs_unwind_cleanup
2459 * Type contents is how the type checker reasons about kinds.
2460 * They track what kinds of things are found within a type. You can
2461 * think of them as kind of an "anti-kind". They track the kinds of values
2462 * and thinks that are contained in types. Having a larger contents for
2463 * a type tends to rule that type *out* from various kinds. For example,
2464 * a type that contains a reference is not sendable.
2466 * The reason we compute type contents and not kinds is that it is
2467 * easier for me (nmatsakis) to think about what is contained within
2468 * a type than to think about what is *not* contained within a type.
2471 pub struct TypeContents {
2475 macro_rules! def_type_content_sets(
2476 (mod $mname:ident { $($name:ident = $bits:expr),+ }) => {
2477 #[allow(non_snake_case)]
2479 use middle::ty::TypeContents;
2481 #[allow(non_upper_case_globals)]
2482 pub const $name: TypeContents = TypeContents { bits: $bits };
2488 def_type_content_sets!(
2490 None = 0b0000_0000__0000_0000__0000,
2492 // Things that are interior to the value (first nibble):
2493 InteriorUnsized = 0b0000_0000__0000_0000__0001,
2494 InteriorUnsafe = 0b0000_0000__0000_0000__0010,
2495 // InteriorAll = 0b00000000__00000000__1111,
2497 // Things that are owned by the value (second and third nibbles):
2498 OwnsOwned = 0b0000_0000__0000_0001__0000,
2499 OwnsDtor = 0b0000_0000__0000_0010__0000,
2500 OwnsManaged /* see [1] below */ = 0b0000_0000__0000_0100__0000,
2501 OwnsAffine = 0b0000_0000__0000_1000__0000,
2502 OwnsAll = 0b0000_0000__1111_1111__0000,
2504 // Things that are reachable by the value in any way (fourth nibble):
2505 ReachesBorrowed = 0b0000_0010__0000_0000__0000,
2506 // ReachesManaged /* see [1] below */ = 0b0000_0100__0000_0000__0000,
2507 ReachesMutable = 0b0000_1000__0000_0000__0000,
2508 ReachesFfiUnsafe = 0b0010_0000__0000_0000__0000,
2509 ReachesAll = 0b0011_1111__0000_0000__0000,
2511 // Things that cause values to *move* rather than *copy*. This
2512 // is almost the same as the `Copy` trait, but for managed
2513 // data -- atm, we consider managed data to copy, not move,
2514 // but it does not impl Copy as a pure memcpy is not good
2516 Moves = 0b0000_0000__0000_1011__0000,
2518 // Things that mean drop glue is necessary
2519 NeedsDrop = 0b0000_0000__0000_0111__0000,
2521 // Things that prevent values from being considered sized
2522 Nonsized = 0b0000_0000__0000_0000__0001,
2524 // Things that make values considered not POD (would be same
2525 // as `Moves`, but for the fact that managed data `@` is
2526 // not considered POD)
2527 Noncopy = 0b0000_0000__0000_1111__0000,
2529 // Bits to set when a managed value is encountered
2531 // [1] Do not set the bits TC::OwnsManaged or
2532 // TC::ReachesManaged directly, instead reference
2533 // TC::Managed to set them both at once.
2534 Managed = 0b0000_0100__0000_0100__0000,
2537 All = 0b1111_1111__1111_1111__1111
2542 pub fn when(&self, cond: bool) -> TypeContents {
2543 if cond {*self} else {TC::None}
2546 pub fn intersects(&self, tc: TypeContents) -> bool {
2547 (self.bits & tc.bits) != 0
2550 pub fn owns_managed(&self) -> bool {
2551 self.intersects(TC::OwnsManaged)
2554 pub fn owns_owned(&self) -> bool {
2555 self.intersects(TC::OwnsOwned)
2558 pub fn is_sized(&self, _: &ctxt) -> bool {
2559 !self.intersects(TC::Nonsized)
2562 pub fn interior_unsafe(&self) -> bool {
2563 self.intersects(TC::InteriorUnsafe)
2566 pub fn interior_unsized(&self) -> bool {
2567 self.intersects(TC::InteriorUnsized)
2570 pub fn moves_by_default(&self, _: &ctxt) -> bool {
2571 self.intersects(TC::Moves)
2574 pub fn needs_drop(&self, _: &ctxt) -> bool {
2575 self.intersects(TC::NeedsDrop)
2578 pub fn owned_pointer(&self) -> TypeContents {
2580 * Includes only those bits that still apply
2581 * when indirected through a `Box` pointer
2584 *self & (TC::OwnsAll | TC::ReachesAll))
2587 pub fn reference(&self, bits: TypeContents) -> TypeContents {
2589 * Includes only those bits that still apply
2590 * when indirected through a reference (`&`)
2593 *self & TC::ReachesAll)
2596 pub fn managed_pointer(&self) -> TypeContents {
2598 * Includes only those bits that still apply
2599 * when indirected through a managed pointer (`@`)
2602 *self & TC::ReachesAll)
2605 pub fn unsafe_pointer(&self) -> TypeContents {
2607 * Includes only those bits that still apply
2608 * when indirected through an unsafe pointer (`*`)
2610 *self & TC::ReachesAll
2613 pub fn union<T>(v: &[T], f: |&T| -> TypeContents) -> TypeContents {
2614 v.iter().fold(TC::None, |tc, ty| tc | f(ty))
2617 pub fn has_dtor(&self) -> bool {
2618 self.intersects(TC::OwnsDtor)
2622 impl ops::BitOr<TypeContents,TypeContents> for TypeContents {
2623 fn bitor(&self, other: &TypeContents) -> TypeContents {
2624 TypeContents {bits: self.bits | other.bits}
2628 impl ops::BitAnd<TypeContents,TypeContents> for TypeContents {
2629 fn bitand(&self, other: &TypeContents) -> TypeContents {
2630 TypeContents {bits: self.bits & other.bits}
2634 impl ops::Sub<TypeContents,TypeContents> for TypeContents {
2635 fn sub(&self, other: &TypeContents) -> TypeContents {
2636 TypeContents {bits: self.bits & !other.bits}
2640 impl fmt::Show for TypeContents {
2641 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
2642 write!(f, "TypeContents({:b})", self.bits)
2646 pub fn type_interior_is_unsafe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2647 type_contents(cx, ty).interior_unsafe()
2650 pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
2651 return memoized(&cx.tc_cache, ty, |ty| {
2652 tc_ty(cx, ty, &mut FnvHashMap::new())
2655 fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
2657 cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
2659 // Subtle: Note that we are *not* using cx.tc_cache here but rather a
2660 // private cache for this walk. This is needed in the case of cyclic
2663 // struct List { next: Box<Option<List>>, ... }
2665 // When computing the type contents of such a type, we wind up deeply
2666 // recursing as we go. So when we encounter the recursive reference
2667 // to List, we temporarily use TC::None as its contents. Later we'll
2668 // patch up the cache with the correct value, once we've computed it
2669 // (this is basically a co-inductive process, if that helps). So in
2670 // the end we'll compute TC::OwnsOwned, in this case.
2672 // The problem is, as we are doing the computation, we will also
2673 // compute an *intermediate* contents for, e.g., Option<List> of
2674 // TC::None. This is ok during the computation of List itself, but if
2675 // we stored this intermediate value into cx.tc_cache, then later
2676 // requests for the contents of Option<List> would also yield TC::None
2677 // which is incorrect. This value was computed based on the crutch
2678 // value for the type contents of list. The correct value is
2679 // TC::OwnsOwned. This manifested as issue #4821.
2680 match cache.get(&ty) {
2681 Some(tc) => { return *tc; }
2684 match cx.tc_cache.borrow().get(&ty) { // Must check both caches!
2685 Some(tc) => { return *tc; }
2688 cache.insert(ty, TC::None);
2690 let result = match ty.sty {
2691 // uint and int are ffi-unsafe
2692 ty_uint(ast::TyU) | ty_int(ast::TyI) => {
2693 TC::ReachesFfiUnsafe
2696 // Scalar and unique types are sendable, and durable
2697 ty_infer(ty::SkolemizedIntTy(_)) |
2698 ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
2699 ty_bare_fn(_) | ty::ty_char => {
2703 ty_closure(ref c) => {
2704 closure_contents(cx, &**c) | TC::ReachesFfiUnsafe
2708 TC::ReachesFfiUnsafe | match typ.sty {
2709 ty_str => TC::OwnsOwned,
2710 _ => tc_ty(cx, typ, cache).owned_pointer(),
2714 ty_trait(box TyTrait { bounds, .. }) => {
2715 object_contents(cx, bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
2719 tc_ty(cx, mt.ty, cache).unsafe_pointer()
2722 ty_rptr(r, ref mt) => {
2723 TC::ReachesFfiUnsafe | match mt.ty.sty {
2724 ty_str => borrowed_contents(r, ast::MutImmutable),
2725 ty_vec(..) => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
2726 _ => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(r, mt.mutbl)),
2730 ty_vec(ty, Some(_)) => {
2731 tc_ty(cx, ty, cache)
2734 ty_vec(ty, None) => {
2735 tc_ty(cx, ty, cache) | TC::Nonsized
2737 ty_str => TC::Nonsized,
2739 ty_struct(did, ref substs) => {
2740 let flds = struct_fields(cx, did, substs);
2742 TypeContents::union(flds.as_slice(),
2743 |f| tc_mt(cx, f.mt, cache));
2745 if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) {
2746 res = res | TC::ReachesFfiUnsafe;
2749 if ty::has_dtor(cx, did) {
2750 res = res | TC::OwnsDtor;
2752 apply_lang_items(cx, did, res)
2755 ty_unboxed_closure(did, r, ref substs) => {
2756 // FIXME(#14449): `borrowed_contents` below assumes `&mut`
2758 let upvars = unboxed_closure_upvars(cx, did, substs);
2759 TypeContents::union(upvars.as_slice(),
2760 |f| tc_ty(cx, f.ty, cache)) |
2761 borrowed_contents(r, MutMutable)
2764 ty_tup(ref tys) => {
2765 TypeContents::union(tys.as_slice(),
2766 |ty| tc_ty(cx, *ty, cache))
2769 ty_enum(did, ref substs) => {
2770 let variants = substd_enum_variants(cx, did, substs);
2772 TypeContents::union(variants.as_slice(), |variant| {
2773 TypeContents::union(variant.args.as_slice(),
2775 tc_ty(cx, *arg_ty, cache)
2779 if ty::has_dtor(cx, did) {
2780 res = res | TC::OwnsDtor;
2783 if variants.len() != 0 {
2784 let repr_hints = lookup_repr_hints(cx, did);
2785 if repr_hints.len() > 1 {
2786 // this is an error later on, but this type isn't safe
2787 res = res | TC::ReachesFfiUnsafe;
2790 match repr_hints.as_slice().get(0) {
2791 Some(h) => if !h.is_ffi_safe() {
2792 res = res | TC::ReachesFfiUnsafe;
2796 res = res | TC::ReachesFfiUnsafe;
2798 // We allow ReprAny enums if they are eligible for
2799 // the nullable pointer optimization and the
2800 // contained type is an `extern fn`
2802 if variants.len() == 2 {
2803 let mut data_idx = 0;
2805 if variants[0].args.len() == 0 {
2809 if variants[data_idx].args.len() == 1 {
2810 match variants[data_idx].args[0].sty {
2811 ty_bare_fn(..) => { res = res - TC::ReachesFfiUnsafe; }
2821 apply_lang_items(cx, did, res)
2825 // We only ever ask for the kind of types that are defined in
2826 // the current crate; therefore, the only type parameters that
2827 // could be in scope are those defined in the current crate.
2828 // If this assertion fails, it is likely because of a
2829 // failure of the cross-crate inlining code to translate a
2831 assert_eq!(p.def_id.krate, ast::LOCAL_CRATE);
2833 let ty_param_defs = cx.ty_param_defs.borrow();
2834 let tp_def = &(*ty_param_defs)[p.def_id.node];
2835 kind_bounds_to_contents(
2837 tp_def.bounds.builtin_bounds,
2838 tp_def.bounds.trait_bounds.as_slice())
2842 // This occurs during coherence, but shouldn't occur at other
2848 let result = tc_ty(cx, ty, cache);
2849 assert!(!result.is_sized(cx))
2850 result.unsafe_pointer() | TC::Nonsized
2854 cx.sess.bug("asked to compute contents of error type");
2858 cache.insert(ty, result);
2862 fn tc_mt<'tcx>(cx: &ctxt<'tcx>,
2864 cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
2866 let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable);
2867 mc | tc_ty(cx, mt.ty, cache)
2870 fn apply_lang_items(cx: &ctxt,
2875 if Some(did) == cx.lang_items.managed_bound() {
2877 } else if Some(did) == cx.lang_items.no_copy_bound() {
2879 } else if Some(did) == cx.lang_items.unsafe_type() {
2880 tc | TC::InteriorUnsafe
2886 fn borrowed_contents(region: ty::Region,
2887 mutbl: ast::Mutability)
2890 * Type contents due to containing a reference
2891 * with the region `region` and borrow kind `bk`
2894 let b = match mutbl {
2895 ast::MutMutable => TC::ReachesMutable | TC::OwnsAffine,
2896 ast::MutImmutable => TC::None,
2898 b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
2901 fn closure_contents(cx: &ctxt, cty: &ClosureTy) -> TypeContents {
2902 // Closure contents are just like trait contents, but with potentially
2904 let st = object_contents(cx, cty.bounds);
2906 let st = match cty.store {
2910 RegionTraitStore(r, mutbl) => {
2911 st.reference(borrowed_contents(r, mutbl))
2915 // This also prohibits "@once fn" from being copied, which allows it to
2916 // be called. Neither way really makes much sense.
2917 let ot = match cty.onceness {
2918 ast::Once => TC::OwnsAffine,
2919 ast::Many => TC::None,
2925 fn object_contents(cx: &ctxt,
2926 bounds: ExistentialBounds)
2928 // These are the type contents of the (opaque) interior
2929 kind_bounds_to_contents(cx, bounds.builtin_bounds, &[])
2932 fn kind_bounds_to_contents<'tcx>(cx: &ctxt<'tcx>,
2933 bounds: BuiltinBounds,
2934 traits: &[Rc<TraitRef<'tcx>>])
2936 let _i = indenter();
2937 let mut tc = TC::All;
2938 each_inherited_builtin_bound(cx, bounds, traits, |bound| {
2939 tc = tc - match bound {
2940 BoundSync | BoundSend => TC::None,
2941 BoundSized => TC::Nonsized,
2942 BoundCopy => TC::Noncopy,
2947 // Iterates over all builtin bounds on the type parameter def, including
2948 // those inherited from traits with builtin-kind-supertraits.
2949 fn each_inherited_builtin_bound<'tcx>(cx: &ctxt<'tcx>,
2950 bounds: BuiltinBounds,
2951 traits: &[Rc<TraitRef<'tcx>>],
2952 f: |BuiltinBound|) {
2953 for bound in bounds.iter() {
2957 each_bound_trait_and_supertraits(cx, traits, |trait_ref| {
2958 let trait_def = lookup_trait_def(cx, trait_ref.def_id);
2959 for bound in trait_def.bounds.builtin_bounds.iter() {
2968 pub fn type_moves_by_default<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2969 type_contents(cx, ty).moves_by_default(cx)
2972 pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
2973 !type_contents(cx, ty).intersects(TC::ReachesFfiUnsafe)
2976 // True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2977 pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
2978 fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
2979 r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
2980 debug!("type_requires({}, {})?",
2981 ::util::ppaux::ty_to_string(cx, r_ty),
2982 ::util::ppaux::ty_to_string(cx, ty));
2984 let r = r_ty == ty || subtypes_require(cx, seen, r_ty, ty);
2986 debug!("type_requires({}, {})? {}",
2987 ::util::ppaux::ty_to_string(cx, r_ty),
2988 ::util::ppaux::ty_to_string(cx, ty),
2993 fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
2994 r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
2995 debug!("subtypes_require({}, {})?",
2996 ::util::ppaux::ty_to_string(cx, r_ty),
2997 ::util::ppaux::ty_to_string(cx, ty));
2999 let r = match ty.sty {
3000 // fixed length vectors need special treatment compared to
3001 // normal vectors, since they don't necessarily have the
3002 // possibility to have length zero.
3003 ty_vec(_, Some(0)) => false, // don't need no contents
3004 ty_vec(ty, Some(_)) => type_requires(cx, seen, r_ty, ty),
3017 ty_vec(_, None) => {
3020 ty_uniq(typ) | ty_open(typ) => {
3021 type_requires(cx, seen, r_ty, typ)
3023 ty_rptr(_, ref mt) => {
3024 type_requires(cx, seen, r_ty, mt.ty)
3028 false // unsafe ptrs can always be NULL
3035 ty_struct(ref did, _) if seen.contains(did) => {
3039 ty_struct(did, ref substs) => {
3041 let fields = struct_fields(cx, did, substs);
3042 let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
3043 seen.pop().unwrap();
3047 ty_unboxed_closure(did, _, ref substs) => {
3048 let upvars = unboxed_closure_upvars(cx, did, substs);
3049 upvars.iter().any(|f| type_requires(cx, seen, r_ty, f.ty))
3053 ts.iter().any(|ty| type_requires(cx, seen, r_ty, *ty))
3056 ty_enum(ref did, _) if seen.contains(did) => {
3060 ty_enum(did, ref substs) => {
3062 let vs = enum_variants(cx, did);
3063 let r = !vs.is_empty() && vs.iter().all(|variant| {
3064 variant.args.iter().any(|aty| {
3065 let sty = aty.subst(cx, substs);
3066 type_requires(cx, seen, r_ty, sty)
3069 seen.pop().unwrap();
3074 debug!("subtypes_require({}, {})? {}",
3075 ::util::ppaux::ty_to_string(cx, r_ty),
3076 ::util::ppaux::ty_to_string(cx, ty),
3082 let mut seen = Vec::new();
3083 !subtypes_require(cx, &mut seen, r_ty, r_ty)
3086 /// Describes whether a type is representable. For types that are not
3087 /// representable, 'SelfRecursive' and 'ContainsRecursive' are used to
3088 /// distinguish between types that are recursive with themselves and types that
3089 /// contain a different recursive type. These cases can therefore be treated
3090 /// differently when reporting errors.
3092 /// The ordering of the cases is significant. They are sorted so that cmp::max
3093 /// will keep the "more erroneous" of two values.
3094 #[deriving(PartialOrd, Ord, Eq, PartialEq, Show)]
3095 pub enum Representability {
3101 /// Check whether a type is representable. This means it cannot contain unboxed
3102 /// structural recursion. This check is needed for structs and enums.
3103 pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
3104 -> Representability {
3106 // Iterate until something non-representable is found
3107 fn find_nonrepresentable<'tcx, It: Iterator<Ty<'tcx>>>(cx: &ctxt<'tcx>, sp: Span,
3108 seen: &mut Vec<Ty<'tcx>>,
3110 -> Representability {
3111 iter.fold(Representable,
3112 |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty)))
3115 fn are_inner_types_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
3116 seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
3117 -> Representability {
3120 find_nonrepresentable(cx, sp, seen, ts.iter().map(|ty| *ty))
3122 // Fixed-length vectors.
3123 // FIXME(#11924) Behavior undecided for zero-length vectors.
3124 ty_vec(ty, Some(_)) => {
3125 is_type_structurally_recursive(cx, sp, seen, ty)
3127 ty_struct(did, ref substs) => {
3128 let fields = struct_fields(cx, did, substs);
3129 find_nonrepresentable(cx, sp, seen, fields.iter().map(|f| f.mt.ty))
3131 ty_enum(did, ref substs) => {
3132 let vs = enum_variants(cx, did);
3133 let iter = vs.iter()
3134 .flat_map(|variant| { variant.args.iter() })
3135 .map(|aty| { aty.subst_spanned(cx, substs, Some(sp)) });
3137 find_nonrepresentable(cx, sp, seen, iter)
3139 ty_unboxed_closure(did, _, ref substs) => {
3140 let upvars = unboxed_closure_upvars(cx, did, substs);
3141 find_nonrepresentable(cx, sp, seen, upvars.iter().map(|f| f.ty))
3147 fn same_struct_or_enum_def_id(ty: Ty, did: DefId) -> bool {
3149 ty_struct(ty_did, _) | ty_enum(ty_did, _) => {
3156 fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
3157 match (&a.sty, &b.sty) {
3158 (&ty_struct(did_a, ref substs_a), &ty_struct(did_b, ref substs_b)) |
3159 (&ty_enum(did_a, ref substs_a), &ty_enum(did_b, ref substs_b)) => {
3164 let types_a = substs_a.types.get_slice(subst::TypeSpace);
3165 let types_b = substs_b.types.get_slice(subst::TypeSpace);
3167 let pairs = types_a.iter().zip(types_b.iter());
3169 pairs.all(|(&a, &b)| same_type(a, b))
3177 // Does the type `ty` directly (without indirection through a pointer)
3178 // contain any types on stack `seen`?
3179 fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
3180 seen: &mut Vec<Ty<'tcx>>,
3181 ty: Ty<'tcx>) -> Representability {
3182 debug!("is_type_structurally_recursive: {}",
3183 ::util::ppaux::ty_to_string(cx, ty));
3186 ty_struct(did, _) | ty_enum(did, _) => {
3188 // Iterate through stack of previously seen types.
3189 let mut iter = seen.iter();
3191 // The first item in `seen` is the type we are actually curious about.
3192 // We want to return SelfRecursive if this type contains itself.
3193 // It is important that we DON'T take generic parameters into account
3194 // for this check, so that Bar<T> in this example counts as SelfRecursive:
3197 // struct Bar<T> { x: Bar<Foo> }
3200 Some(&seen_type) => {
3201 if same_struct_or_enum_def_id(seen_type, did) {
3202 debug!("SelfRecursive: {} contains {}",
3203 ::util::ppaux::ty_to_string(cx, seen_type),
3204 ::util::ppaux::ty_to_string(cx, ty));
3205 return SelfRecursive;
3211 // We also need to know whether the first item contains other types that
3212 // are structurally recursive. If we don't catch this case, we will recurse
3213 // infinitely for some inputs.
3215 // It is important that we DO take generic parameters into account here,
3216 // so that code like this is considered SelfRecursive, not ContainsRecursive:
3218 // struct Foo { Option<Option<Foo>> }
3220 for &seen_type in iter {
3221 if same_type(ty, seen_type) {
3222 debug!("ContainsRecursive: {} contains {}",
3223 ::util::ppaux::ty_to_string(cx, seen_type),
3224 ::util::ppaux::ty_to_string(cx, ty));
3225 return ContainsRecursive;
3230 // For structs and enums, track all previously seen types by pushing them
3231 // onto the 'seen' stack.
3233 let out = are_inner_types_recursive(cx, sp, seen, ty);
3238 // No need to push in other cases.
3239 are_inner_types_recursive(cx, sp, seen, ty)
3244 debug!("is_type_representable: {}",
3245 ::util::ppaux::ty_to_string(cx, ty));
3247 // To avoid a stack overflow when checking an enum variant or struct that
3248 // contains a different, structurally recursive type, maintain a stack
3249 // of seen types and check recursion for each of them (issues #3008, #3779).
3250 let mut seen: Vec<Ty> = Vec::new();
3251 let r = is_type_structurally_recursive(cx, sp, &mut seen, ty);
3252 debug!("is_type_representable: {} is {}",
3253 ::util::ppaux::ty_to_string(cx, ty), r);
3257 pub fn type_is_trait(ty: Ty) -> bool {
3258 type_trait_info(ty).is_some()
3261 pub fn type_trait_info<'tcx>(ty: Ty<'tcx>) -> Option<&'tcx TyTrait<'tcx>> {
3263 ty_uniq(ty) | ty_rptr(_, mt { ty, ..}) | ty_ptr(mt { ty, ..}) => match ty.sty {
3264 ty_trait(ref t) => Some(&**t),
3267 ty_trait(ref t) => Some(&**t),
3272 pub fn type_is_integral(ty: Ty) -> bool {
3274 ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
3279 pub fn type_is_skolemized(ty: Ty) -> bool {
3281 ty_infer(SkolemizedTy(_)) => true,
3282 ty_infer(SkolemizedIntTy(_)) => true,
3287 pub fn type_is_uint(ty: Ty) -> bool {
3289 ty_infer(IntVar(_)) | ty_uint(ast::TyU) => true,
3294 pub fn type_is_char(ty: Ty) -> bool {
3301 pub fn type_is_bare_fn(ty: Ty) -> bool {
3303 ty_bare_fn(..) => true,
3308 pub fn type_is_fp(ty: Ty) -> bool {
3310 ty_infer(FloatVar(_)) | ty_float(_) => true,
3315 pub fn type_is_numeric(ty: Ty) -> bool {
3316 return type_is_integral(ty) || type_is_fp(ty);
3319 pub fn type_is_signed(ty: Ty) -> bool {
3326 pub fn type_is_machine(ty: Ty) -> bool {
3328 ty_int(ast::TyI) | ty_uint(ast::TyU) => false,
3329 ty_int(..) | ty_uint(..) | ty_float(..) => true,
3334 // Is the type's representation size known at compile time?
3335 pub fn type_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
3336 type_contents(cx, ty).is_sized(cx)
3339 pub fn lltype_is_sized<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
3342 _ => type_contents(cx, ty).is_sized(cx)
3346 // Return the smallest part of `ty` which is unsized. Fails if `ty` is sized.
3347 // 'Smallest' here means component of the static representation of the type; not
3348 // the size of an object at runtime.
3349 pub fn unsized_part_of_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
3351 ty_str | ty_trait(..) | ty_vec(..) => ty,
3352 ty_struct(def_id, ref substs) => {
3353 let unsized_fields: Vec<_> = struct_fields(cx, def_id, substs).iter()
3354 .map(|f| f.mt.ty).filter(|ty| !type_is_sized(cx, *ty)).collect();
3355 // Exactly one of the fields must be unsized.
3356 assert!(unsized_fields.len() == 1)
3358 unsized_part_of_type(cx, unsized_fields[0])
3361 assert!(type_is_sized(cx, ty),
3362 "unsized_part_of_type failed even though ty is unsized");
3363 panic!("called unsized_part_of_type with sized ty");
3368 // Whether a type is enum like, that is an enum type with only nullary
3370 pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool {
3372 ty_enum(did, _) => {
3373 let variants = enum_variants(cx, did);
3374 if variants.len() == 0 {
3377 variants.iter().all(|v| v.args.len() == 0)
3384 // Returns the type and mutability of *ty.
3386 // The parameter `explicit` indicates if this is an *explicit* dereference.
3387 // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
3388 pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
3393 mutbl: ast::MutImmutable,
3396 ty_rptr(_, mt) => Some(mt),
3397 ty_ptr(mt) if explicit => Some(mt),
3402 pub fn close_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
3404 ty_open(ty) => mk_rptr(cx, ReStatic, mt {ty: ty, mutbl:ast::MutImmutable}),
3405 _ => cx.sess.bug(format!("Trying to close a non-open type {}",
3406 ty_to_string(cx, ty)).as_slice())
3410 pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
3413 ty_rptr(_, mt) |ty_ptr(mt) => mt.ty,
3418 // Extract the unsized type in an open type (or just return ty if it is not open).
3419 pub fn unopen_type<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
3426 // Returns the type of ty[i]
3427 pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
3429 ty_vec(ty, _) => Some(ty),
3434 // Returns the type of elements contained within an 'array-like' type.
3435 // This is exactly the same as the above, except it supports strings,
3436 // which can't actually be indexed.
3437 pub fn array_element_ty<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
3439 ty_vec(ty, _) => Some(ty),
3440 ty_str => Some(mk_u8()),
3445 /// Returns the type of element at index `i` in tuple or tuple-like type `t`.
3446 /// For an enum `t`, `variant` is None only if `t` is a univariant enum.
3447 pub fn positional_element_ty<'tcx>(cx: &ctxt<'tcx>,
3450 variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
3452 match (&ty.sty, variant) {
3453 (&ty_tup(ref v), None) => v.as_slice().get(i).map(|&t| t),
3456 (&ty_struct(def_id, ref substs), None) => lookup_struct_fields(cx, def_id)
3458 .map(|&t|lookup_item_type(cx, t.id).ty.subst(cx, substs)),
3460 (&ty_enum(def_id, ref substs), Some(variant_def_id)) => {
3461 let variant_info = enum_variant_with_id(cx, def_id, variant_def_id);
3462 variant_info.args.as_slice().get(i).map(|t|t.subst(cx, substs))
3465 (&ty_enum(def_id, ref substs), None) => {
3466 assert!(enum_is_univariant(cx, def_id));
3467 let enum_variants = enum_variants(cx, def_id);
3468 let variant_info = &(*enum_variants)[0];
3469 variant_info.args.as_slice().get(i).map(|t|t.subst(cx, substs))
3476 /// Returns the type of element at field `n` in struct or struct-like type `t`.
3477 /// For an enum `t`, `variant` must be some def id.
3478 pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
3481 variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
3483 match (&ty.sty, variant) {
3484 (&ty_struct(def_id, ref substs), None) => {
3485 let r = lookup_struct_fields(cx, def_id);
3486 r.iter().find(|f| f.name == n)
3487 .map(|&f| lookup_field_type(cx, def_id, f.id, substs))
3489 (&ty_enum(def_id, ref substs), Some(variant_def_id)) => {
3490 let variant_info = enum_variant_with_id(cx, def_id, variant_def_id);
3491 variant_info.arg_names.as_ref()
3492 .expect("must have struct enum variant if accessing a named fields")
3493 .iter().zip(variant_info.args.iter())
3494 .find(|&(ident, _)| ident.name == n)
3495 .map(|(_ident, arg_t)| arg_t.subst(cx, substs))
3501 pub fn node_id_to_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId)
3502 -> Rc<ty::TraitRef<'tcx>> {
3503 match cx.trait_refs.borrow().get(&id) {
3504 Some(ty) => ty.clone(),
3505 None => cx.sess.bug(
3506 format!("node_id_to_trait_ref: no trait ref for node `{}`",
3507 cx.map.node_to_string(id)).as_slice())
3511 pub fn try_node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Option<Ty<'tcx>> {
3512 cx.node_types.borrow().get(&id).cloned()
3515 pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> {
3516 match try_node_id_to_type(cx, id) {
3518 None => cx.sess.bug(
3519 format!("node_id_to_type: no type for node `{}`",
3520 cx.map.node_to_string(id)).as_slice())
3524 pub fn node_id_to_type_opt<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Option<Ty<'tcx>> {
3525 match cx.node_types.borrow().get(&id) {
3526 Some(&ty) => Some(ty),
3531 pub fn node_id_item_substs<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> ItemSubsts<'tcx> {
3532 match cx.item_substs.borrow().get(&id) {
3533 None => ItemSubsts::empty(),
3534 Some(ts) => ts.clone(),
3538 pub fn fn_is_variadic(fty: Ty) -> bool {
3540 ty_bare_fn(ref f) => f.sig.variadic,
3541 ty_closure(ref f) => f.sig.variadic,
3543 panic!("fn_is_variadic() called on non-fn type: {}", s)
3548 pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx FnSig<'tcx> {
3550 ty_bare_fn(ref f) => &f.sig,
3551 ty_closure(ref f) => &f.sig,
3553 panic!("ty_fn_sig() called on non-fn type: {}", s)
3558 /// Returns the ABI of the given function.
3559 pub fn ty_fn_abi(fty: Ty) -> abi::Abi {
3561 ty_bare_fn(ref f) => f.abi,
3562 ty_closure(ref f) => f.abi,
3563 _ => panic!("ty_fn_abi() called on non-fn type"),
3567 // Type accessors for substructures of types
3568 pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> &'tcx [Ty<'tcx>] {
3569 ty_fn_sig(fty).inputs.as_slice()
3572 pub fn ty_closure_store(fty: Ty) -> TraitStore {
3574 ty_closure(ref f) => f.store,
3575 ty_unboxed_closure(..) => {
3576 // Close enough for the purposes of all the callers of this
3577 // function (which is soon to be deprecated anyhow).
3581 panic!("ty_closure_store() called on non-closure type: {}", s)
3586 pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> FnOutput<'tcx> {
3588 ty_bare_fn(ref f) => f.sig.output,
3589 ty_closure(ref f) => f.sig.output,
3591 panic!("ty_fn_ret() called on non-fn type: {}", s)
3596 pub fn is_fn_ty(fty: Ty) -> bool {
3598 ty_bare_fn(_) => true,
3599 ty_closure(_) => true,
3604 pub fn ty_region(tcx: &ctxt,
3612 format!("ty_region() invoked on an inappropriate ty: {}",
3618 pub fn free_region_from_def(free_id: ast::NodeId, def: &RegionParameterDef)
3621 ty::ReFree(ty::FreeRegion { scope: region::CodeExtent::from_node_id(free_id),
3622 bound_region: ty::BrNamed(def.def_id,
3626 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
3627 // doesn't provide type parameter substitutions.
3628 pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> {
3629 return node_id_to_type(cx, pat.id);
3633 // Returns the type of an expression as a monotype.
3635 // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
3636 // some cases, we insert `AutoAdjustment` annotations such as auto-deref or
3637 // auto-ref. The type returned by this function does not consider such
3638 // adjustments. See `expr_ty_adjusted()` instead.
3640 // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
3641 // ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
3642 // instead of "fn(ty) -> T with T = int".
3643 pub fn expr_ty<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> {
3644 return node_id_to_type(cx, expr.id);
3647 pub fn expr_ty_opt<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Option<Ty<'tcx>> {
3648 return node_id_to_type_opt(cx, expr.id);
3651 pub fn expr_ty_adjusted<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> {
3654 * Returns the type of `expr`, considering any `AutoAdjustment`
3655 * entry recorded for that expression.
3657 * It would almost certainly be better to store the adjusted ty in with
3658 * the `AutoAdjustment`, but I opted not to do this because it would
3659 * require serializing and deserializing the type and, although that's not
3660 * hard to do, I just hate that code so much I didn't want to touch it
3661 * unless it was to fix it properly, which seemed a distraction from the
3662 * task at hand! -nmatsakis
3665 adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr),
3666 cx.adjustments.borrow().get(&expr.id),
3667 |method_call| cx.method_map.borrow().get(&method_call).map(|method| method.ty))
3670 pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
3671 match cx.map.find(id) {
3672 Some(ast_map::NodeExpr(e)) => {
3676 cx.sess.bug(format!("Node id {} is not an expr: {}",
3681 cx.sess.bug(format!("Node id {} is not present \
3682 in the node map", id).as_slice());
3687 pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
3688 match cx.map.find(id) {
3689 Some(ast_map::NodeLocal(pat)) => {
3691 ast::PatIdent(_, ref path1, _) => {
3692 token::get_ident(path1.node)
3696 format!("Variable id {} maps to {}, not local",
3703 cx.sess.bug(format!("Variable id {} maps to {}, not local",
3710 pub fn adjust_ty<'tcx>(cx: &ctxt<'tcx>,
3712 expr_id: ast::NodeId,
3713 unadjusted_ty: Ty<'tcx>,
3714 adjustment: Option<&AutoAdjustment<'tcx>>,
3715 method_type: |typeck::MethodCall| -> Option<Ty<'tcx>>)
3717 /*! See `expr_ty_adjusted` */
3719 match unadjusted_ty.sty {
3720 ty_err => return unadjusted_ty,
3724 return match adjustment {
3725 Some(adjustment) => {
3727 AdjustAddEnv(store) => {
3728 match unadjusted_ty.sty {
3729 ty::ty_bare_fn(ref b) => {
3730 let bounds = ty::ExistentialBounds {
3731 region_bound: ReStatic,
3732 builtin_bounds: all_builtin_bounds(),
3737 ty::ClosureTy {fn_style: b.fn_style,
3738 onceness: ast::Many,
3746 format!("add_env adjustment on non-bare-fn: \
3753 AdjustDerefRef(ref adj) => {
3754 let mut adjusted_ty = unadjusted_ty;
3756 if !ty::type_is_error(adjusted_ty) {
3757 for i in range(0, adj.autoderefs) {
3758 let method_call = typeck::MethodCall::autoderef(expr_id, i);
3759 match method_type(method_call) {
3760 Some(method_ty) => {
3761 if let ty::FnConverging(result_type) = ty_fn_ret(method_ty) {
3762 adjusted_ty = result_type;
3767 match deref(adjusted_ty, true) {
3768 Some(mt) => { adjusted_ty = mt.ty; }
3772 format!("the {}th autoderef failed: \
3775 ty_to_string(cx, adjusted_ty))
3782 adjust_ty_for_autoref(cx, span, adjusted_ty, adj.autoref.as_ref())
3786 None => unadjusted_ty
3790 pub fn adjust_ty_for_autoref<'tcx>(cx: &ctxt<'tcx>,
3793 autoref: Option<&AutoRef<'tcx>>)
3799 Some(&AutoPtr(r, m, ref a)) => {
3800 let adjusted_ty = match a {
3801 &Some(box ref a) => adjust_ty_for_autoref(cx, span, ty, Some(a)),
3810 Some(&AutoUnsafe(m, ref a)) => {
3811 let adjusted_ty = match a {
3812 &Some(box ref a) => adjust_ty_for_autoref(cx, span, ty, Some(a)),
3815 mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
3818 Some(&AutoUnsize(ref k)) => unsize_ty(cx, ty, k, span),
3820 Some(&AutoUnsizeUniq(ref k)) => ty::mk_uniq(cx, unsize_ty(cx, ty, k, span)),
3824 // Take a sized type and a sizing adjustment and produce an unsized version of
3826 pub fn unsize_ty<'tcx>(cx: &ctxt<'tcx>,
3828 kind: &UnsizeKind<'tcx>,
3832 &UnsizeLength(len) => match ty.sty {
3833 ty_vec(ty, Some(n)) => {
3835 mk_vec(cx, ty, None)
3837 _ => cx.sess.span_bug(span,
3838 format!("UnsizeLength with bad sty: {}",
3839 ty_to_string(cx, ty)).as_slice())
3841 &UnsizeStruct(box ref k, tp_index) => match ty.sty {
3842 ty_struct(did, ref substs) => {
3843 let ty_substs = substs.types.get_slice(subst::TypeSpace);
3844 let new_ty = unsize_ty(cx, ty_substs[tp_index], k, span);
3845 let mut unsized_substs = substs.clone();
3846 unsized_substs.types.get_mut_slice(subst::TypeSpace)[tp_index] = new_ty;
3847 mk_struct(cx, did, unsized_substs)
3849 _ => cx.sess.span_bug(span,
3850 format!("UnsizeStruct with bad sty: {}",
3851 ty_to_string(cx, ty)).as_slice())
3853 &UnsizeVtable(TyTrait { ref principal, bounds }, _) => {
3854 mk_trait(cx, (*principal).clone(), bounds)
3859 pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
3860 match tcx.def_map.borrow().get(&expr.id) {
3863 tcx.sess.span_bug(expr.span, format!(
3864 "no def-map entry for expr {}", expr.id).as_slice());
3869 pub fn expr_is_lval(tcx: &ctxt, e: &ast::Expr) -> bool {
3870 match expr_kind(tcx, e) {
3872 RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
3876 /// We categorize expressions into three kinds. The distinction between
3877 /// lvalue/rvalue is fundamental to the language. The distinction between the
3878 /// two kinds of rvalues is an artifact of trans which reflects how we will
3879 /// generate code for that kind of expression. See trans/expr.rs for more
3888 pub fn expr_kind(tcx: &ctxt, expr: &ast::Expr) -> ExprKind {
3889 if tcx.method_map.borrow().contains_key(&typeck::MethodCall::expr(expr.id)) {
3890 // Overloaded operations are generally calls, and hence they are
3891 // generated via DPS, but there are a few exceptions:
3892 return match expr.node {
3893 // `a += b` has a unit result.
3894 ast::ExprAssignOp(..) => RvalueStmtExpr,
3896 // the deref method invoked for `*a` always yields an `&T`
3897 ast::ExprUnary(ast::UnDeref, _) => LvalueExpr,
3899 // the index method invoked for `a[i]` always yields an `&T`
3900 ast::ExprIndex(..) => LvalueExpr,
3902 // the slice method invoked for `a[..]` always yields an `&T`
3903 ast::ExprSlice(..) => LvalueExpr,
3905 // `for` loops are statements
3906 ast::ExprForLoop(..) => RvalueStmtExpr,
3908 // in the general case, result could be any type, use DPS
3914 ast::ExprPath(..) => {
3915 match resolve_expr(tcx, expr) {
3916 def::DefVariant(tid, vid, _) => {
3917 let variant_info = enum_variant_with_id(tcx, tid, vid);
3918 if variant_info.args.len() > 0u {
3927 def::DefStruct(_) => {
3928 match expr_ty(tcx, expr).sty {
3929 ty_bare_fn(..) => RvalueDatumExpr,
3934 // Special case: A unit like struct's constructor must be called without () at the
3935 // end (like `UnitStruct`) which means this is an ExprPath to a DefFn. But in case
3936 // of unit structs this is should not be interpreted as function pointer but as
3937 // call to the constructor.
3938 def::DefFn(_, true) => RvalueDpsExpr,
3940 // Fn pointers are just scalar values.
3941 def::DefFn(..) | def::DefStaticMethod(..) | def::DefMethod(..) => RvalueDatumExpr,
3943 // Note: there is actually a good case to be made that
3944 // DefArg's, particularly those of immediate type, ought to
3945 // considered rvalues.
3946 def::DefStatic(..) |
3948 def::DefLocal(..) => LvalueExpr,
3950 def::DefConst(..) => RvalueDatumExpr,
3955 format!("uncategorized def for expr {}: {}",
3962 ast::ExprUnary(ast::UnDeref, _) |
3963 ast::ExprField(..) |
3964 ast::ExprTupField(..) |
3965 ast::ExprIndex(..) |
3966 ast::ExprSlice(..) => {
3971 ast::ExprMethodCall(..) |
3972 ast::ExprStruct(..) |
3975 ast::ExprMatch(..) |
3976 ast::ExprClosure(..) |
3978 ast::ExprBlock(..) |
3979 ast::ExprRepeat(..) |
3980 ast::ExprVec(..) => {
3984 ast::ExprIfLet(..) => {
3985 tcx.sess.span_bug(expr.span, "non-desugared ExprIfLet");
3987 ast::ExprWhileLet(..) => {
3988 tcx.sess.span_bug(expr.span, "non-desugared ExprWhileLet");
3991 ast::ExprLit(ref lit) if lit_is_str(&**lit) => {
3995 ast::ExprCast(..) => {
3996 match tcx.node_types.borrow().get(&expr.id) {
3998 if type_is_trait(ty) {
4005 // Technically, it should not happen that the expr is not
4006 // present within the table. However, it DOES happen
4007 // during type check, because the final types from the
4008 // expressions are not yet recorded in the tcx. At that
4009 // time, though, we are only interested in knowing lvalue
4010 // vs rvalue. It would be better to base this decision on
4011 // the AST type in cast node---but (at the time of this
4012 // writing) it's not easy to distinguish casts to traits
4013 // from other casts based on the AST. This should be
4014 // easier in the future, when casts to traits
4015 // would like @Foo, Box<Foo>, or &Foo.
4021 ast::ExprBreak(..) |
4022 ast::ExprAgain(..) |
4024 ast::ExprWhile(..) |
4026 ast::ExprAssign(..) |
4027 ast::ExprInlineAsm(..) |
4028 ast::ExprAssignOp(..) |
4029 ast::ExprForLoop(..) => {
4033 ast::ExprLit(_) | // Note: LitStr is carved out above
4034 ast::ExprUnary(..) |
4035 ast::ExprAddrOf(..) |
4036 ast::ExprBinary(..) => {
4040 ast::ExprBox(ref place, _) => {
4041 // Special case `Box<T>` for now:
4042 let definition = match tcx.def_map.borrow().get(&place.id) {
4044 None => panic!("no def for place"),
4046 let def_id = definition.def_id();
4047 if tcx.lang_items.exchange_heap() == Some(def_id) {
4054 ast::ExprParen(ref e) => expr_kind(tcx, &**e),
4056 ast::ExprMac(..) => {
4059 "macro expression remains after expansion");
4064 pub fn stmt_node_id(s: &ast::Stmt) -> ast::NodeId {
4066 ast::StmtDecl(_, id) | StmtExpr(_, id) | StmtSemi(_, id) => {
4069 ast::StmtMac(..) => panic!("unexpanded macro in trans")
4073 pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
4076 for f in fields.iter() { if f.name == name { return i; } i += 1u; }
4077 tcx.sess.bug(format!(
4078 "no field named `{}` found in the list of fields `{}`",
4079 token::get_name(name),
4081 .map(|f| token::get_name(f.name).get().to_string())
4082 .collect::<Vec<String>>()).as_slice());
4085 pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem])
4087 trait_items.iter().position(|m| m.name() == id)
4090 pub fn ty_sort_string<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> String {
4092 ty_bool | ty_char | ty_int(_) |
4093 ty_uint(_) | ty_float(_) | ty_str => {
4094 ::util::ppaux::ty_to_string(cx, ty)
4096 ty_tup(ref tys) if tys.is_empty() => ::util::ppaux::ty_to_string(cx, ty),
4098 ty_enum(id, _) => format!("enum {}", item_path_str(cx, id)),
4099 ty_uniq(_) => "box".to_string(),
4100 ty_vec(_, Some(n)) => format!("array of {} elements", n),
4101 ty_vec(_, None) => "slice".to_string(),
4102 ty_ptr(_) => "*-ptr".to_string(),
4103 ty_rptr(_, _) => "&-ptr".to_string(),
4104 ty_bare_fn(_) => "extern fn".to_string(),
4105 ty_closure(_) => "fn".to_string(),
4106 ty_trait(ref inner) => {
4107 format!("trait {}", item_path_str(cx, inner.principal.def_id))
4109 ty_struct(id, _) => {
4110 format!("struct {}", item_path_str(cx, id))
4112 ty_unboxed_closure(..) => "closure".to_string(),
4113 ty_tup(_) => "tuple".to_string(),
4114 ty_infer(TyVar(_)) => "inferred type".to_string(),
4115 ty_infer(IntVar(_)) => "integral variable".to_string(),
4116 ty_infer(FloatVar(_)) => "floating-point variable".to_string(),
4117 ty_infer(SkolemizedTy(_)) => "skolemized type".to_string(),
4118 ty_infer(SkolemizedIntTy(_)) => "skolemized integral type".to_string(),
4119 ty_param(ref p) => {
4120 if p.space == subst::SelfSpace {
4123 "type parameter".to_string()
4126 ty_err => "type error".to_string(),
4127 ty_open(_) => "opened DST".to_string(),
4131 pub fn type_err_to_str<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>) -> String {
4134 * Explains the source of a type err in a short,
4135 * human readable way. This is meant to be placed in
4136 * parentheses after some larger message. You should
4137 * also invoke `note_and_explain_type_err()` afterwards
4138 * to present additional details, particularly when
4139 * it comes to lifetime-related errors. */
4141 fn tstore_to_closure(s: &TraitStore) -> String {
4143 &UniqTraitStore => "proc".to_string(),
4144 &RegionTraitStore(..) => "closure".to_string()
4149 terr_cyclic_ty => "cyclic type of infinite size".to_string(),
4150 terr_mismatch => "types differ".to_string(),
4151 terr_fn_style_mismatch(values) => {
4152 format!("expected {} fn, found {} fn",
4153 values.expected.to_string(),
4154 values.found.to_string())
4156 terr_abi_mismatch(values) => {
4157 format!("expected {} fn, found {} fn",
4158 values.expected.to_string(),
4159 values.found.to_string())
4161 terr_onceness_mismatch(values) => {
4162 format!("expected {} fn, found {} fn",
4163 values.expected.to_string(),
4164 values.found.to_string())
4166 terr_sigil_mismatch(values) => {
4167 format!("expected {}, found {}",
4168 tstore_to_closure(&values.expected),
4169 tstore_to_closure(&values.found))
4171 terr_mutability => "values differ in mutability".to_string(),
4172 terr_box_mutability => {
4173 "boxed values differ in mutability".to_string()
4175 terr_vec_mutability => "vectors differ in mutability".to_string(),
4176 terr_ptr_mutability => "pointers differ in mutability".to_string(),
4177 terr_ref_mutability => "references differ in mutability".to_string(),
4178 terr_ty_param_size(values) => {
4179 format!("expected a type with {} type params, \
4180 found one with {} type params",
4184 terr_fixed_array_size(values) => {
4185 format!("expected an array with a fixed size of {} elements, \
4186 found one with {} elements",
4190 terr_tuple_size(values) => {
4191 format!("expected a tuple with {} elements, \
4192 found one with {} elements",
4197 "incorrect number of function parameters".to_string()
4199 terr_regions_does_not_outlive(..) => {
4200 "lifetime mismatch".to_string()
4202 terr_regions_not_same(..) => {
4203 "lifetimes are not the same".to_string()
4205 terr_regions_no_overlap(..) => {
4206 "lifetimes do not intersect".to_string()
4208 terr_regions_insufficiently_polymorphic(br, _) => {
4209 format!("expected bound lifetime parameter {}, \
4210 found concrete lifetime",
4211 bound_region_ptr_to_string(cx, br))
4213 terr_regions_overly_polymorphic(br, _) => {
4214 format!("expected concrete lifetime, \
4215 found bound lifetime parameter {}",
4216 bound_region_ptr_to_string(cx, br))
4218 terr_trait_stores_differ(_, ref values) => {
4219 format!("trait storage differs: expected `{}`, found `{}`",
4220 trait_store_to_string(cx, (*values).expected),
4221 trait_store_to_string(cx, (*values).found))
4223 terr_sorts(values) => {
4224 // A naive approach to making sure that we're not reporting silly errors such as:
4225 // (expected closure, found closure).
4226 let expected_str = ty_sort_string(cx, values.expected);
4227 let found_str = ty_sort_string(cx, values.found);
4228 if expected_str == found_str {
4229 format!("expected {}, found a different {}", expected_str, found_str)
4231 format!("expected {}, found {}", expected_str, found_str)
4234 terr_traits(values) => {
4235 format!("expected trait `{}`, found trait `{}`",
4236 item_path_str(cx, values.expected),
4237 item_path_str(cx, values.found))
4239 terr_builtin_bounds(values) => {
4240 if values.expected.is_empty() {
4241 format!("expected no bounds, found `{}`",
4242 values.found.user_string(cx))
4243 } else if values.found.is_empty() {
4244 format!("expected bounds `{}`, found no bounds",
4245 values.expected.user_string(cx))
4247 format!("expected bounds `{}`, found bounds `{}`",
4248 values.expected.user_string(cx),
4249 values.found.user_string(cx))
4252 terr_integer_as_char => {
4253 "expected an integral type, found `char`".to_string()
4255 terr_int_mismatch(ref values) => {
4256 format!("expected `{}`, found `{}`",
4257 values.expected.to_string(),
4258 values.found.to_string())
4260 terr_float_mismatch(ref values) => {
4261 format!("expected `{}`, found `{}`",
4262 values.expected.to_string(),
4263 values.found.to_string())
4265 terr_variadic_mismatch(ref values) => {
4266 format!("expected {} fn, found {} function",
4267 if values.expected { "variadic" } else { "non-variadic" },
4268 if values.found { "variadic" } else { "non-variadic" })
4270 terr_convergence_mismatch(ref values) => {
4271 format!("expected {} fn, found {} function",
4272 if values.expected { "converging" } else { "diverging" },
4273 if values.found { "converging" } else { "diverging" })
4278 pub fn note_and_explain_type_err(cx: &ctxt, err: &type_err) {
4280 terr_regions_does_not_outlive(subregion, superregion) => {
4281 note_and_explain_region(cx, "", subregion, "...");
4282 note_and_explain_region(cx, "...does not necessarily outlive ",
4285 terr_regions_not_same(region1, region2) => {
4286 note_and_explain_region(cx, "", region1, "...");
4287 note_and_explain_region(cx, "...is not the same lifetime as ",
4290 terr_regions_no_overlap(region1, region2) => {
4291 note_and_explain_region(cx, "", region1, "...");
4292 note_and_explain_region(cx, "...does not overlap ",
4295 terr_regions_insufficiently_polymorphic(_, conc_region) => {
4296 note_and_explain_region(cx,
4297 "concrete lifetime that was found is ",
4300 terr_regions_overly_polymorphic(_, conc_region) => {
4301 note_and_explain_region(cx,
4302 "expected concrete lifetime is ",
4309 pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
4310 cx.provided_method_sources.borrow().get(&id).map(|x| *x)
4313 pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
4314 -> Vec<Rc<Method<'tcx>>> {
4316 match cx.map.find(id.node) {
4317 Some(ast_map::NodeItem(item)) => {
4319 ItemTrait(_, _, _, ref ms) => {
4321 ast_util::split_trait_methods(ms.as_slice());
4324 match impl_or_trait_item(
4326 ast_util::local_def(m.id)) {
4327 MethodTraitItem(m) => m,
4328 TypeTraitItem(_) => {
4329 cx.sess.bug("provided_trait_methods(): \
4330 split_trait_methods() put \
4331 associated types in the \
4332 provided method bucket?!")
4338 cx.sess.bug(format!("provided_trait_methods: `{}` is \
4345 cx.sess.bug(format!("provided_trait_methods: `{}` is not a \
4351 csearch::get_provided_trait_methods(cx, id)
4355 fn lookup_locally_or_in_crate_store<V:Clone>(
4358 map: &mut DefIdMap<V>,
4359 load_external: || -> V) -> V {
4361 * Helper for looking things up in the various maps
4362 * that are populated during typeck::collect (e.g.,
4363 * `cx.impl_or_trait_items`, `cx.tcache`, etc). All of these share
4364 * the pattern that if the id is local, it should have
4365 * been loaded into the map by the `typeck::collect` phase.
4366 * If the def-id is external, then we have to go consult
4367 * the crate loading code (and cache the result for the future).
4370 match map.get(&def_id).cloned() {
4371 Some(v) => { return v; }
4375 if def_id.krate == ast::LOCAL_CRATE {
4376 panic!("No def'n found for {} in tcx.{}", def_id, descr);
4378 let v = load_external();
4379 map.insert(def_id, v.clone());
4383 pub fn trait_item<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId, idx: uint)
4384 -> ImplOrTraitItem<'tcx> {
4385 let method_def_id = (*ty::trait_item_def_ids(cx, trait_did))[idx].def_id();
4386 impl_or_trait_item(cx, method_def_id)
4389 pub fn trait_items<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId)
4390 -> Rc<Vec<ImplOrTraitItem<'tcx>>> {
4391 let mut trait_items = cx.trait_items_cache.borrow_mut();
4392 match trait_items.get(&trait_did).cloned() {
4393 Some(trait_items) => trait_items,
4395 let def_ids = ty::trait_item_def_ids(cx, trait_did);
4396 let items: Rc<Vec<ImplOrTraitItem>> =
4397 Rc::new(def_ids.iter()
4398 .map(|d| impl_or_trait_item(cx, d.def_id()))
4400 trait_items.insert(trait_did, items.clone());
4406 pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
4407 -> ImplOrTraitItem<'tcx> {
4408 lookup_locally_or_in_crate_store("impl_or_trait_items",
4410 &mut *cx.impl_or_trait_items
4413 csearch::get_impl_or_trait_item(cx, id)
4417 /// Returns true if the given ID refers to an associated type and false if it
4418 /// refers to anything else.
4419 pub fn is_associated_type(cx: &ctxt, id: ast::DefId) -> bool {
4420 memoized(&cx.associated_types, id, |id: ast::DefId| {
4421 if id.krate == ast::LOCAL_CRATE {
4422 match cx.impl_or_trait_items.borrow().get(&id) {
4425 TypeTraitItem(_) => true,
4426 MethodTraitItem(_) => false,
4432 csearch::is_associated_type(&cx.sess.cstore, id)
4437 /// Returns the parameter index that the given associated type corresponds to.
4438 pub fn associated_type_parameter_index(cx: &ctxt,
4439 trait_def: &TraitDef,
4440 associated_type_id: ast::DefId)
4442 for type_parameter_def in trait_def.generics.types.iter() {
4443 if type_parameter_def.def_id == associated_type_id {
4444 return type_parameter_def.index
4447 cx.sess.bug("couldn't find associated type parameter index")
4450 #[deriving(PartialEq, Eq)]
4451 pub struct AssociatedTypeInfo {
4452 pub def_id: ast::DefId,
4454 pub name: ast::Name,
4457 impl PartialOrd for AssociatedTypeInfo {
4458 fn partial_cmp(&self, other: &AssociatedTypeInfo) -> Option<Ordering> {
4459 Some(self.index.cmp(&other.index))
4463 impl Ord for AssociatedTypeInfo {
4464 fn cmp(&self, other: &AssociatedTypeInfo) -> Ordering {
4465 self.index.cmp(&other.index)
4469 pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
4470 -> Rc<Vec<ImplOrTraitItemId>> {
4471 lookup_locally_or_in_crate_store("trait_item_def_ids",
4473 &mut *cx.trait_item_def_ids.borrow_mut(),
4475 Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id))
4479 pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
4480 -> Option<Rc<TraitRef<'tcx>>> {
4481 memoized(&cx.impl_trait_cache, id, |id: ast::DefId| {
4482 if id.krate == ast::LOCAL_CRATE {
4483 debug!("(impl_trait_ref) searching for trait impl {}", id);
4484 match cx.map.find(id.node) {
4485 Some(ast_map::NodeItem(item)) => {
4487 ast::ItemImpl(_, ref opt_trait, _, _) => {
4490 Some(ty::node_id_to_trait_ref(cx, t.ref_id))
4501 csearch::get_impl_trait(cx, id)
4506 pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
4507 let def = *tcx.def_map.borrow()
4509 .expect("no def-map entry for trait");
4513 pub fn try_add_builtin_trait(
4515 trait_def_id: ast::DefId,
4516 builtin_bounds: &mut EnumSet<BuiltinBound>)
4519 //! Checks whether `trait_ref` refers to one of the builtin
4520 //! traits, like `Send`, and adds the corresponding
4521 //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
4522 //! is a builtin trait.
4524 match tcx.lang_items.to_builtin_kind(trait_def_id) {
4525 Some(bound) => { builtin_bounds.insert(bound); true }
4530 pub fn ty_to_def_id(ty: Ty) -> Option<ast::DefId> {
4533 Some(tt.principal.def_id),
4536 ty_unboxed_closure(id, _, _) =>
4545 pub struct VariantInfo<'tcx> {
4546 pub args: Vec<Ty<'tcx>>,
4547 pub arg_names: Option<Vec<ast::Ident>>,
4548 pub ctor_ty: Option<Ty<'tcx>>,
4549 pub name: ast::Name,
4555 impl<'tcx> VariantInfo<'tcx> {
4557 /// Creates a new VariantInfo from the corresponding ast representation.
4559 /// Does not do any caching of the value in the type context.
4560 pub fn from_ast_variant(cx: &ctxt<'tcx>,
4561 ast_variant: &ast::Variant,
4562 discriminant: Disr) -> VariantInfo<'tcx> {
4563 let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
4565 match ast_variant.node.kind {
4566 ast::TupleVariantKind(ref args) => {
4567 let arg_tys = if args.len() > 0 {
4568 ty_fn_args(ctor_ty).iter().map(|a| *a).collect()
4573 return VariantInfo {
4576 ctor_ty: Some(ctor_ty),
4577 name: ast_variant.node.name.name,
4578 id: ast_util::local_def(ast_variant.node.id),
4579 disr_val: discriminant,
4580 vis: ast_variant.node.vis
4583 ast::StructVariantKind(ref struct_def) => {
4585 let fields: &[StructField] = struct_def.fields.as_slice();
4587 assert!(fields.len() > 0);
4589 let arg_tys = struct_def.fields.iter()
4590 .map(|field| node_id_to_type(cx, field.node.id)).collect();
4591 let arg_names = fields.iter().map(|field| {
4592 match field.node.kind {
4593 NamedField(ident, _) => ident,
4594 UnnamedField(..) => cx.sess.bug(
4595 "enum_variants: all fields in struct must have a name")
4599 return VariantInfo {
4601 arg_names: Some(arg_names),
4603 name: ast_variant.node.name.name,
4604 id: ast_util::local_def(ast_variant.node.id),
4605 disr_val: discriminant,
4606 vis: ast_variant.node.vis
4613 pub fn substd_enum_variants<'tcx>(cx: &ctxt<'tcx>,
4615 substs: &Substs<'tcx>)
4616 -> Vec<Rc<VariantInfo<'tcx>>> {
4617 enum_variants(cx, id).iter().map(|variant_info| {
4618 let substd_args = variant_info.args.iter()
4619 .map(|aty| aty.subst(cx, substs)).collect::<Vec<_>>();
4621 let substd_ctor_ty = variant_info.ctor_ty.subst(cx, substs);
4623 Rc::new(VariantInfo {
4625 ctor_ty: substd_ctor_ty,
4626 ..(**variant_info).clone()
4631 pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String {
4632 with_path(cx, id, |path| ast_map::path_to_string(path)).to_string()
4637 TraitDtor(DefId, bool)
4641 pub fn is_present(&self) -> bool {
4643 TraitDtor(..) => true,
4648 pub fn has_drop_flag(&self) -> bool {
4651 &TraitDtor(_, flag) => flag
4656 /* If struct_id names a struct with a dtor, return Some(the dtor's id).
4657 Otherwise return none. */
4658 pub fn ty_dtor(cx: &ctxt, struct_id: DefId) -> DtorKind {
4659 match cx.destructor_for_type.borrow().get(&struct_id) {
4660 Some(&method_def_id) => {
4661 let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag");
4663 TraitDtor(method_def_id, flag)
4669 pub fn has_dtor(cx: &ctxt, struct_id: DefId) -> bool {
4670 cx.destructor_for_type.borrow().contains_key(&struct_id)
4673 pub fn with_path<T>(cx: &ctxt, id: ast::DefId, f: |ast_map::PathElems| -> T) -> T {
4674 if id.krate == ast::LOCAL_CRATE {
4675 cx.map.with_path(id.node, f)
4677 f(ast_map::Values(csearch::get_item_path(cx, id).iter()).chain(None))
4681 pub fn enum_is_univariant(cx: &ctxt, id: ast::DefId) -> bool {
4682 enum_variants(cx, id).len() == 1
4685 pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool {
4687 ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
4692 pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
4693 -> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
4694 memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
4695 if ast::LOCAL_CRATE != id.krate {
4696 Rc::new(csearch::get_enum_variants(cx, id))
4699 Although both this code and check_enum_variants in typeck/check
4700 call eval_const_expr, it should never get called twice for the same
4701 expr, since check_enum_variants also updates the enum_var_cache
4703 match cx.map.get(id.node) {
4704 ast_map::NodeItem(ref item) => {
4706 ast::ItemEnum(ref enum_definition, _) => {
4707 let mut last_discriminant: Option<Disr> = None;
4708 Rc::new(enum_definition.variants.iter().map(|variant| {
4710 let mut discriminant = match last_discriminant {
4711 Some(val) => val + 1,
4712 None => INITIAL_DISCRIMINANT_VALUE
4715 match variant.node.disr_expr {
4717 match const_eval::eval_const_expr_partial(cx, &**e) {
4718 Ok(const_eval::const_int(val)) => {
4719 discriminant = val as Disr
4721 Ok(const_eval::const_uint(val)) => {
4722 discriminant = val as Disr
4727 "expected signed integer constant");
4732 format!("expected constant: {}",
4739 last_discriminant = Some(discriminant);
4740 Rc::new(VariantInfo::from_ast_variant(cx, &**variant,
4745 cx.sess.bug("enum_variants: id not bound to an enum")
4749 _ => cx.sess.bug("enum_variants: id not bound to an enum")
4755 // Returns information about the enum variant with the given ID:
4756 pub fn enum_variant_with_id<'tcx>(cx: &ctxt<'tcx>,
4757 enum_id: ast::DefId,
4758 variant_id: ast::DefId)
4759 -> Rc<VariantInfo<'tcx>> {
4760 enum_variants(cx, enum_id).iter()
4761 .find(|variant| variant.id == variant_id)
4762 .expect("enum_variant_with_id(): no variant exists with that ID")
4767 // If the given item is in an external crate, looks up its type and adds it to
4768 // the type cache. Returns the type parameters and type.
4769 pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>,
4772 lookup_locally_or_in_crate_store(
4773 "tcache", did, &mut *cx.tcache.borrow_mut(),
4774 || csearch::get_type(cx, did))
4777 /// Given the did of a trait, returns its canonical trait ref.
4778 pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
4779 -> Rc<ty::TraitDef<'tcx>> {
4780 memoized(&cx.trait_defs, did, |did: DefId| {
4781 assert!(did.krate != ast::LOCAL_CRATE);
4782 Rc::new(csearch::get_trait_def(cx, did))
4786 /// Given a reference to a trait, returns the bounds declared on the
4787 /// trait, with appropriate substitutions applied.
4788 pub fn bounds_for_trait_ref<'tcx>(tcx: &ctxt<'tcx>,
4789 trait_ref: &TraitRef<'tcx>)
4790 -> ty::ParamBounds<'tcx>
4792 let trait_def = lookup_trait_def(tcx, trait_ref.def_id);
4794 debug!("bounds_for_trait_ref(trait_def={}, trait_ref={})",
4795 trait_def.repr(tcx), trait_ref.repr(tcx));
4797 // The interaction between HRTB and supertraits is not entirely
4798 // obvious. Let me walk you (and myself) through an example.
4800 // Let's start with an easy case. Consider two traits:
4802 // trait Foo<'a> : Bar<'a,'a> { }
4803 // trait Bar<'b,'c> { }
4805 // Now, if we have a trait reference `for<'x> T : Foo<'x>`, then
4806 // we can deduce that `for<'x> T : Bar<'x,'x>`. Basically, if we
4807 // knew that `Foo<'x>` (for any 'x) then we also know that
4808 // `Bar<'x,'x>` (for any 'x). This more-or-less falls out from
4809 // normal substitution.
4811 // In terms of why this is sound, the idea is that whenever there
4812 // is an impl of `T:Foo<'a>`, it must show that `T:Bar<'a,'a>`
4813 // holds. So if there is an impl of `T:Foo<'a>` that applies to
4814 // all `'a`, then we must know that `T:Bar<'a,'a>` holds for all
4817 // Another example to be careful of is this:
4819 // trait Foo1<'a> : for<'b> Bar1<'a,'b> { }
4820 // trait Bar1<'b,'c> { }
4822 // Here, if we have `for<'x> T : Foo1<'x>`, then what do we know?
4823 // The answer is that we know `for<'x,'b> T : Bar1<'x,'b>`. The
4824 // reason is similar to the previous example: any impl of
4825 // `T:Foo1<'x>` must show that `for<'b> T : Bar1<'x, 'b>`. So
4826 // basically we would want to collapse the bound lifetimes from
4827 // the input (`trait_ref`) and the supertraits.
4829 // To achieve this in practice is fairly straightforward. Let's
4830 // consider the more complicated scenario:
4832 // - We start out with `for<'x> T : Foo1<'x>`. In this case, `'x`
4833 // has a De Bruijn index of 1. We want to produce `for<'x,'b> T : Bar1<'x,'b>`,
4834 // where both `'x` and `'b` would have a DB index of 1.
4835 // The substitution from the input trait-ref is therefore going to be
4836 // `'a => 'x` (where `'x` has a DB index of 1).
4837 // - The super-trait-ref is `for<'b> Bar1<'a,'b>`, where `'a` is an
4838 // early-bound parameter and `'b' is a late-bound parameter with a
4840 // - If we replace `'a` with `'x` from the input, it too will have
4841 // a DB index of 1, and thus we'll have `for<'x,'b> Bar1<'x,'b>`
4842 // just as we wanted.
4844 // There is only one catch. If we just apply the substitution `'a
4845 // => 'x` to `for<'b> Bar1<'a,'b>`, the substitution code will
4846 // adjust the DB index because we substituting into a binder (it
4847 // tries to be so smart...) resulting in `for<'x> for<'b>
4848 // Bar1<'x,'b>` (we have no syntax for this, so use your
4849 // imagination). Basically the 'x will have DB index of 2 and 'b
4850 // will have DB index of 1. Not quite what we want. So we apply
4851 // the substitution to the *contents* of the trait reference,
4852 // rather than the trait reference itself (put another way, the
4853 // substitution code expects equal binding levels in the values
4854 // from the substitution and the value being substituted into, and
4855 // this trick achieves that).
4857 // Carefully avoid the binder introduced by each trait-ref by
4858 // substituting over the substs, not the trait-refs themselves,
4859 // thus achieving the "collapse" described in the big comment
4861 let trait_bounds: Vec<_> =
4862 trait_def.bounds.trait_bounds
4864 .map(|bound_trait_ref| {
4865 ty::TraitRef::new(bound_trait_ref.def_id,
4866 bound_trait_ref.substs.subst(tcx, &trait_ref.substs))
4868 .map(|bound_trait_ref| Rc::new(bound_trait_ref))
4871 debug!("bounds_for_trait_ref: trait_bounds={}",
4872 trait_bounds.repr(tcx));
4874 // The region bounds and builtin bounds do not currently introduce
4875 // binders so we can just substitute in a straightforward way here.
4877 trait_def.bounds.region_bounds.subst(tcx, &trait_ref.substs);
4878 let builtin_bounds =
4879 trait_def.bounds.builtin_bounds.subst(tcx, &trait_ref.substs);
4882 trait_bounds: trait_bounds,
4883 region_bounds: region_bounds,
4884 builtin_bounds: builtin_bounds,
4888 /// Iterate over attributes of a definition.
4889 // (This should really be an iterator, but that would require csearch and
4890 // decoder to use iterators instead of higher-order functions.)
4891 pub fn each_attr(tcx: &ctxt, did: DefId, f: |&ast::Attribute| -> bool) -> bool {
4893 let item = tcx.map.expect_item(did.node);
4894 item.attrs.iter().all(|attr| f(attr))
4896 info!("getting foreign attrs");
4897 let mut cont = true;
4898 csearch::get_item_attrs(&tcx.sess.cstore, did, |attrs| {
4900 cont = attrs.iter().all(|attr| f(attr));
4908 /// Determine whether an item is annotated with an attribute
4909 pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
4910 let mut found = false;
4911 each_attr(tcx, did, |item| {
4912 if item.check_name(attr) {
4922 /// Determine whether an item is annotated with `#[repr(packed)]`
4923 pub fn lookup_packed(tcx: &ctxt, did: DefId) -> bool {
4924 lookup_repr_hints(tcx, did).contains(&attr::ReprPacked)
4927 /// Determine whether an item is annotated with `#[simd]`
4928 pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
4929 has_attr(tcx, did, "simd")
4932 /// Obtain the representation annotation for a struct definition.
4933 pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
4934 memoized(&tcx.repr_hint_cache, did, |did: DefId| {
4935 Rc::new(if did.krate == LOCAL_CRATE {
4936 let mut acc = Vec::new();
4937 ty::each_attr(tcx, did, |meta| {
4938 acc.extend(attr::find_repr_attrs(tcx.sess.diagnostic(),
4944 csearch::get_repr_attrs(&tcx.sess.cstore, did)
4949 // Look up a field ID, whether or not it's local
4950 // Takes a list of type substs in case the struct is generic
4951 pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>,
4954 substs: &Substs<'tcx>)
4956 let ty = if id.krate == ast::LOCAL_CRATE {
4957 node_id_to_type(tcx, id.node)
4959 let mut tcache = tcx.tcache.borrow_mut();
4960 let pty = match tcache.entry(id) {
4961 Occupied(entry) => entry.into_mut(),
4962 Vacant(entry) => entry.set(csearch::get_field_type(tcx, struct_id, id)),
4966 ty.subst(tcx, substs)
4969 // Look up the list of field names and IDs for a given struct.
4970 // Panics if the id is not bound to a struct.
4971 pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
4972 if did.krate == ast::LOCAL_CRATE {
4973 let struct_fields = cx.struct_fields.borrow();
4974 match struct_fields.get(&did) {
4975 Some(fields) => (**fields).clone(),
4978 format!("ID not mapped to struct fields: {}",
4979 cx.map.node_to_string(did.node)).as_slice());
4983 csearch::get_struct_fields(&cx.sess.cstore, did)
4987 pub fn is_tuple_struct(cx: &ctxt, did: ast::DefId) -> bool {
4988 let fields = lookup_struct_fields(cx, did);
4989 !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field)
4992 // Returns a list of fields corresponding to the struct's items. trans uses
4993 // this. Takes a list of substs with which to instantiate field types.
4994 pub fn struct_fields<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &Substs<'tcx>)
4995 -> Vec<field<'tcx>> {
4996 lookup_struct_fields(cx, did).iter().map(|f| {
5000 ty: lookup_field_type(cx, did, f.id, substs),
5007 // Returns a list of fields corresponding to the tuple's items. trans uses
5009 pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
5010 v.iter().enumerate().map(|(i, &f)| {
5012 name: token::intern(i.to_string().as_slice()),
5021 pub struct UnboxedClosureUpvar<'tcx> {
5027 // Returns a list of `UnboxedClosureUpvar`s for each upvar.
5028 pub fn unboxed_closure_upvars<'tcx>(tcx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &Substs<'tcx>)
5029 -> Vec<UnboxedClosureUpvar<'tcx>> {
5030 // Presently an unboxed closure type cannot "escape" out of a
5031 // function, so we will only encounter ones that originated in the
5032 // local crate or were inlined into it along with some function.
5033 // This may change if abstract return types of some sort are
5035 assert!(closure_id.krate == ast::LOCAL_CRATE);
5036 let capture_mode = tcx.capture_modes.borrow()[closure_id.node].clone();
5037 match tcx.freevars.borrow().get(&closure_id.node) {
5039 Some(ref freevars) => {
5040 freevars.iter().map(|freevar| {
5041 let freevar_def_id = freevar.def.def_id();
5042 let freevar_ty = node_id_to_type(tcx, freevar_def_id.node);
5043 let mut freevar_ty = freevar_ty.subst(tcx, substs);
5044 if capture_mode == ast::CaptureByRef {
5045 let borrow = tcx.upvar_borrow_map.borrow()[ty::UpvarId {
5046 var_id: freevar_def_id.node,
5047 closure_expr_id: closure_id.node
5049 freevar_ty = mk_rptr(tcx, borrow.region, ty::mt {
5051 mutbl: borrow.kind.to_mutbl_lossy()
5054 UnboxedClosureUpvar {
5064 pub fn is_binopable<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, op: ast::BinOp) -> bool {
5065 #![allow(non_upper_case_globals)]
5066 static tycat_other: int = 0;
5067 static tycat_bool: int = 1;
5068 static tycat_char: int = 2;
5069 static tycat_int: int = 3;
5070 static tycat_float: int = 4;
5071 static tycat_raw_ptr: int = 6;
5073 static opcat_add: int = 0;
5074 static opcat_sub: int = 1;
5075 static opcat_mult: int = 2;
5076 static opcat_shift: int = 3;
5077 static opcat_rel: int = 4;
5078 static opcat_eq: int = 5;
5079 static opcat_bit: int = 6;
5080 static opcat_logic: int = 7;
5081 static opcat_mod: int = 8;
5083 fn opcat(op: ast::BinOp) -> int {
5085 ast::BiAdd => opcat_add,
5086 ast::BiSub => opcat_sub,
5087 ast::BiMul => opcat_mult,
5088 ast::BiDiv => opcat_mult,
5089 ast::BiRem => opcat_mod,
5090 ast::BiAnd => opcat_logic,
5091 ast::BiOr => opcat_logic,
5092 ast::BiBitXor => opcat_bit,
5093 ast::BiBitAnd => opcat_bit,
5094 ast::BiBitOr => opcat_bit,
5095 ast::BiShl => opcat_shift,
5096 ast::BiShr => opcat_shift,
5097 ast::BiEq => opcat_eq,
5098 ast::BiNe => opcat_eq,
5099 ast::BiLt => opcat_rel,
5100 ast::BiLe => opcat_rel,
5101 ast::BiGe => opcat_rel,
5102 ast::BiGt => opcat_rel
5106 fn tycat<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> int {
5107 if type_is_simd(cx, ty) {
5108 return tycat(cx, simd_type(cx, ty))
5111 ty_char => tycat_char,
5112 ty_bool => tycat_bool,
5113 ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
5114 ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
5115 ty_ptr(_) => tycat_raw_ptr,
5120 static t: bool = true;
5121 static f: bool = false;
5124 // +, -, *, shift, rel, ==, bit, logic, mod
5125 /*other*/ [f, f, f, f, f, f, f, f, f],
5126 /*bool*/ [f, f, f, f, t, t, t, t, f],
5127 /*char*/ [f, f, f, f, t, t, f, f, f],
5128 /*int*/ [t, t, t, t, t, t, t, f, t],
5129 /*float*/ [t, t, t, f, t, t, f, f, f],
5130 /*bot*/ [t, t, t, t, t, t, t, t, t],
5131 /*raw ptr*/ [f, f, f, f, t, t, f, f, f]];
5133 return tbl[tycat(cx, ty) as uint ][opcat(op) as uint];
5136 /// Returns an equivalent type with all the typedefs and self regions removed.
5137 pub fn normalize_ty<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
5138 let u = TypeNormalizer(cx).fold_ty(ty);
5141 struct TypeNormalizer<'a, 'tcx: 'a>(&'a ctxt<'tcx>);
5143 impl<'a, 'tcx> TypeFolder<'tcx> for TypeNormalizer<'a, 'tcx> {
5144 fn tcx(&self) -> &ctxt<'tcx> { let TypeNormalizer(c) = *self; c }
5146 fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
5147 match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
5152 let t_norm = ty_fold::super_fold_ty(self, ty);
5153 self.tcx().normalized_cache.borrow_mut().insert(ty, t_norm);
5157 fn fold_region(&mut self, _: ty::Region) -> ty::Region {
5161 fn fold_substs(&mut self,
5162 substs: &subst::Substs<'tcx>)
5163 -> subst::Substs<'tcx> {
5164 subst::Substs { regions: subst::ErasedRegions,
5165 types: substs.types.fold_with(self) }
5168 fn fold_fn_sig(&mut self,
5169 sig: &ty::FnSig<'tcx>)
5170 -> ty::FnSig<'tcx> {
5171 // The binder-id is only relevant to bound regions, which
5172 // are erased at trans time.
5174 inputs: sig.inputs.fold_with(self),
5175 output: sig.output.fold_with(self),
5176 variadic: sig.variadic,
5182 // Returns the repeat count for a repeating vector expression.
5183 pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> uint {
5184 match const_eval::eval_const_expr_partial(tcx, count_expr) {
5186 let found = match val {
5187 const_eval::const_uint(count) => return count as uint,
5188 const_eval::const_int(count) if count >= 0 => return count as uint,
5189 const_eval::const_int(_) =>
5191 const_eval::const_float(_) =>
5193 const_eval::const_str(_) =>
5195 const_eval::const_bool(_) =>
5197 const_eval::const_binary(_) =>
5200 tcx.sess.span_err(count_expr.span, format!(
5201 "expected positive integer for repeat count, found {}",
5205 let found = match count_expr.node {
5206 ast::ExprPath(ast::Path {
5210 }) if segments.len() == 1 =>
5213 "non-constant expression"
5215 tcx.sess.span_err(count_expr.span, format!(
5216 "expected constant integer for repeat count, found {}",
5223 // Iterate over a type parameter's bounded traits and any supertraits
5224 // of those traits, ignoring kinds.
5225 // Here, the supertraits are the transitive closure of the supertrait
5226 // relation on the supertraits from each bounded trait's constraint
5228 pub fn each_bound_trait_and_supertraits<'tcx>(tcx: &ctxt<'tcx>,
5229 bounds: &[Rc<TraitRef<'tcx>>],
5230 f: |Rc<TraitRef<'tcx>>| -> bool)
5233 for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
5234 if !f(bound_trait_ref) {
5241 pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
5242 region_bounds: &[ty::Region],
5243 builtin_bounds: BuiltinBounds,
5244 trait_bounds: &[Rc<TraitRef<'tcx>>])
5248 * Given a type which must meet the builtin bounds and trait
5249 * bounds, returns a set of lifetimes which the type must outlive.
5251 * Requires that trait definitions have been processed.
5254 let mut all_bounds = Vec::new();
5256 debug!("required_region_bounds(builtin_bounds={}, trait_bounds={})",
5257 builtin_bounds.repr(tcx),
5258 trait_bounds.repr(tcx));
5260 all_bounds.push_all(region_bounds);
5262 push_region_bounds(&[],
5266 debug!("from builtin bounds: all_bounds={}", all_bounds.repr(tcx));
5268 each_bound_trait_and_supertraits(
5272 let bounds = ty::bounds_for_trait_ref(tcx, &*trait_ref);
5273 push_region_bounds(bounds.region_bounds.as_slice(),
5274 bounds.builtin_bounds,
5276 debug!("from {}: bounds={} all_bounds={}",
5277 trait_ref.repr(tcx),
5279 all_bounds.repr(tcx));
5285 fn push_region_bounds(region_bounds: &[ty::Region],
5286 builtin_bounds: ty::BuiltinBounds,
5287 all_bounds: &mut Vec<ty::Region>) {
5288 all_bounds.push_all(region_bounds.as_slice());
5290 if builtin_bounds.contains(&ty::BoundSend) {
5291 all_bounds.push(ty::ReStatic);
5296 pub fn get_tydesc_ty<'tcx>(tcx: &ctxt<'tcx>) -> Result<Ty<'tcx>, String> {
5297 tcx.lang_items.require(TyDescStructLangItem).map(|tydesc_lang_item| {
5298 tcx.intrinsic_defs.borrow().get(&tydesc_lang_item).cloned()
5299 .expect("Failed to resolve TyDesc")
5303 pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
5304 lookup_locally_or_in_crate_store(
5305 "item_variance_map", item_id, &mut *tcx.item_variance_map.borrow_mut(),
5306 || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
5309 /// Records a trait-to-implementation mapping.
5310 pub fn record_trait_implementation(tcx: &ctxt,
5311 trait_def_id: DefId,
5312 impl_def_id: DefId) {
5313 match tcx.trait_impls.borrow().get(&trait_def_id) {
5314 Some(impls_for_trait) => {
5315 impls_for_trait.borrow_mut().push(impl_def_id);
5320 tcx.trait_impls.borrow_mut().insert(trait_def_id, Rc::new(RefCell::new(vec!(impl_def_id))));
5323 /// Populates the type context with all the implementations for the given type
5325 pub fn populate_implementations_for_type_if_necessary(tcx: &ctxt,
5326 type_id: ast::DefId) {
5327 if type_id.krate == LOCAL_CRATE {
5330 if tcx.populated_external_types.borrow().contains(&type_id) {
5334 let mut inherent_impls = Vec::new();
5335 csearch::each_implementation_for_type(&tcx.sess.cstore, type_id,
5337 let impl_items = csearch::get_impl_items(&tcx.sess.cstore,
5340 // Record the trait->implementation mappings, if applicable.
5341 let associated_traits = csearch::get_impl_trait(tcx, impl_def_id);
5342 for trait_ref in associated_traits.iter() {
5343 record_trait_implementation(tcx, trait_ref.def_id, impl_def_id);
5346 // For any methods that use a default implementation, add them to
5347 // the map. This is a bit unfortunate.
5348 for impl_item_def_id in impl_items.iter() {
5349 let method_def_id = impl_item_def_id.def_id();
5350 match impl_or_trait_item(tcx, method_def_id) {
5351 MethodTraitItem(method) => {
5352 for &source in method.provided_source.iter() {
5353 tcx.provided_method_sources
5355 .insert(method_def_id, source);
5358 TypeTraitItem(_) => {}
5362 // Store the implementation info.
5363 tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
5365 // If this is an inherent implementation, record it.
5366 if associated_traits.is_none() {
5367 inherent_impls.push(impl_def_id);
5371 tcx.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
5372 tcx.populated_external_types.borrow_mut().insert(type_id);
5375 /// Populates the type context with all the implementations for the given
5376 /// trait if necessary.
5377 pub fn populate_implementations_for_trait_if_necessary(
5379 trait_id: ast::DefId) {
5380 if trait_id.krate == LOCAL_CRATE {
5383 if tcx.populated_external_traits.borrow().contains(&trait_id) {
5387 csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id,
5388 |implementation_def_id| {
5389 let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
5391 // Record the trait->implementation mapping.
5392 record_trait_implementation(tcx, trait_id, implementation_def_id);
5394 // For any methods that use a default implementation, add them to
5395 // the map. This is a bit unfortunate.
5396 for impl_item_def_id in impl_items.iter() {
5397 let method_def_id = impl_item_def_id.def_id();
5398 match impl_or_trait_item(tcx, method_def_id) {
5399 MethodTraitItem(method) => {
5400 for &source in method.provided_source.iter() {
5401 tcx.provided_method_sources
5403 .insert(method_def_id, source);
5406 TypeTraitItem(_) => {}
5410 // Store the implementation info.
5411 tcx.impl_items.borrow_mut().insert(implementation_def_id, impl_items);
5414 tcx.populated_external_traits.borrow_mut().insert(trait_id);
5417 /// Given the def_id of an impl, return the def_id of the trait it implements.
5418 /// If it implements no trait, return `None`.
5419 pub fn trait_id_of_impl(tcx: &ctxt,
5420 def_id: ast::DefId) -> Option<ast::DefId> {
5421 let node = match tcx.map.find(def_id.node) {
5426 ast_map::NodeItem(item) => {
5428 ast::ItemImpl(_, Some(ref trait_ref), _, _) => {
5429 Some(node_id_to_trait_ref(tcx, trait_ref.ref_id).def_id)
5438 /// If the given def ID describes a method belonging to an impl, return the
5439 /// ID of the impl that the method belongs to. Otherwise, return `None`.
5440 pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
5441 -> Option<ast::DefId> {
5442 if def_id.krate != LOCAL_CRATE {
5443 return match csearch::get_impl_or_trait_item(tcx,
5444 def_id).container() {
5445 TraitContainer(_) => None,
5446 ImplContainer(def_id) => Some(def_id),
5449 match tcx.impl_or_trait_items.borrow().get(&def_id).cloned() {
5450 Some(trait_item) => {
5451 match trait_item.container() {
5452 TraitContainer(_) => None,
5453 ImplContainer(def_id) => Some(def_id),
5460 /// If the given def ID describes an item belonging to a trait (either a
5461 /// default method or an implementation of a trait method), return the ID of
5462 /// the trait that the method belongs to. Otherwise, return `None`.
5463 pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option<ast::DefId> {
5464 if def_id.krate != LOCAL_CRATE {
5465 return csearch::get_trait_of_item(&tcx.sess.cstore, def_id, tcx);
5467 match tcx.impl_or_trait_items.borrow().get(&def_id).cloned() {
5468 Some(impl_or_trait_item) => {
5469 match impl_or_trait_item.container() {
5470 TraitContainer(def_id) => Some(def_id),
5471 ImplContainer(def_id) => trait_id_of_impl(tcx, def_id),
5478 /// If the given def ID describes an item belonging to a trait, (either a
5479 /// default method or an implementation of a trait method), return the ID of
5480 /// the method inside trait definition (this means that if the given def ID
5481 /// is already that of the original trait method, then the return value is
5483 /// Otherwise, return `None`.
5484 pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
5485 -> Option<ImplOrTraitItemId> {
5486 let impl_item = match tcx.impl_or_trait_items.borrow().get(&def_id) {
5487 Some(m) => m.clone(),
5488 None => return None,
5490 let name = impl_item.name();
5491 match trait_of_item(tcx, def_id) {
5492 Some(trait_did) => {
5493 let trait_items = ty::trait_items(tcx, trait_did);
5495 .position(|m| m.name() == name)
5496 .map(|idx| ty::trait_item(tcx, trait_did, idx).id())
5502 /// Creates a hash of the type `Ty` which will be the same no matter what crate
5503 /// context it's calculated within. This is used by the `type_id` intrinsic.
5504 pub fn hash_crate_independent(tcx: &ctxt, ty: Ty, svh: &Svh) -> u64 {
5505 let mut state = sip::SipState::new();
5506 macro_rules! byte( ($b:expr) => { ($b as u8).hash(&mut state) } );
5507 macro_rules! hash( ($e:expr) => { $e.hash(&mut state) } );
5509 let region = |_state: &mut sip::SipState, r: Region| {
5519 tcx.sess.bug("non-static region found when hashing a type")
5523 let did = |state: &mut sip::SipState, did: DefId| {
5524 let h = if ast_util::is_local(did) {
5527 tcx.sess.cstore.get_crate_hash(did.krate)
5529 h.as_str().hash(state);
5530 did.node.hash(state);
5532 let mt = |state: &mut sip::SipState, mt: mt| {
5533 mt.mutbl.hash(state);
5535 ty::walk_ty(ty, |ty| {
5537 ty_bool => byte!(2),
5538 ty_char => byte!(3),
5561 ty_vec(_, Some(n)) => {
5565 ty_vec(_, None) => {
5574 region(&mut state, r);
5577 ty_bare_fn(ref b) => {
5582 ty_closure(ref c) => {
5588 UniqTraitStore => byte!(0),
5589 RegionTraitStore(r, m) => {
5591 region(&mut state, r);
5592 assert_eq!(m, ast::MutMutable);
5596 ty_trait(box TyTrait { ref principal, bounds }) => {
5598 did(&mut state, principal.def_id);
5601 ty_struct(d, _) => {
5605 ty_tup(ref inner) => {
5612 did(&mut state, p.def_id);
5614 ty_open(_) => byte!(22),
5615 ty_infer(_) => unreachable!(),
5616 ty_err => byte!(23),
5617 ty_unboxed_closure(d, r, _) => {
5620 region(&mut state, r);
5629 pub fn to_string(self) -> &'static str {
5632 Contravariant => "-",
5639 pub fn empty_parameter_environment<'tcx>() -> ParameterEnvironment<'tcx> {
5641 * Construct a parameter environment suitable for static contexts
5642 * or other contexts where there are no free type/lifetime
5643 * parameters in scope.
5646 ty::ParameterEnvironment { free_substs: Substs::empty(),
5647 bounds: VecPerParamSpace::empty(),
5648 caller_obligations: VecPerParamSpace::empty(),
5649 implicit_region_bound: ty::ReEmpty,
5650 selection_cache: traits::SelectionCache::new(), }
5653 pub fn construct_parameter_environment<'tcx>(
5656 generics: &ty::Generics<'tcx>,
5657 free_id: ast::NodeId)
5658 -> ParameterEnvironment<'tcx>
5660 /*! See `ParameterEnvironment` struct def'n for details */
5663 // Construct the free substs.
5667 let mut types = VecPerParamSpace::empty();
5668 for &space in subst::ParamSpace::all().iter() {
5669 push_types_from_defs(tcx, &mut types, space,
5670 generics.types.get_slice(space));
5673 // map bound 'a => free 'a
5674 let mut regions = VecPerParamSpace::empty();
5675 for &space in subst::ParamSpace::all().iter() {
5676 push_region_params(&mut regions, space, free_id,
5677 generics.regions.get_slice(space));
5680 let free_substs = Substs {
5682 regions: subst::NonerasedRegions(regions)
5685 let free_id_scope = region::CodeExtent::from_node_id(free_id);
5688 // Compute the bounds on Self and the type parameters.
5691 let bounds = generics.to_bounds(tcx, &free_substs);
5692 let bounds = liberate_late_bound_regions(tcx, free_id_scope, &bind(bounds)).value;
5693 let obligations = traits::obligations_for_generics(tcx,
5694 traits::ObligationCause::misc(span),
5696 &free_substs.types);
5697 let type_bounds = bounds.types.subst(tcx, &free_substs);
5700 // Compute region bounds. For now, these relations are stored in a
5701 // global table on the tcx, so just enter them there. I'm not
5702 // crazy about this scheme, but it's convenient, at least.
5705 for &space in subst::ParamSpace::all().iter() {
5706 record_region_bounds(tcx, space, &free_substs, bounds.regions.get_slice(space));
5710 debug!("construct_parameter_environment: free_id={} free_subst={} \
5711 obligations={} type_bounds={}",
5713 free_substs.repr(tcx),
5714 obligations.repr(tcx),
5715 type_bounds.repr(tcx));
5717 return ty::ParameterEnvironment {
5718 free_substs: free_substs,
5719 bounds: bounds.types,
5720 implicit_region_bound: ty::ReScope(free_id_scope),
5721 caller_obligations: obligations,
5722 selection_cache: traits::SelectionCache::new(),
5725 fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
5726 space: subst::ParamSpace,
5727 free_id: ast::NodeId,
5728 region_params: &[RegionParameterDef])
5730 for r in region_params.iter() {
5731 regions.push(space, ty::free_region_from_def(free_id, r));
5735 fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
5736 types: &mut subst::VecPerParamSpace<Ty<'tcx>>,
5737 space: subst::ParamSpace,
5738 defs: &[TypeParameterDef<'tcx>]) {
5739 for (i, def) in defs.iter().enumerate() {
5740 debug!("construct_parameter_environment(): push_types_from_defs: \
5741 space={} def={} index={}",
5745 let ty = ty::mk_param(tcx, space, i, def.def_id);
5746 types.push(space, ty);
5750 fn record_region_bounds<'tcx>(tcx: &ty::ctxt<'tcx>,
5751 space: subst::ParamSpace,
5752 free_substs: &Substs<'tcx>,
5753 bound_sets: &[Vec<ty::Region>]) {
5754 for (subst_region, bound_set) in
5755 free_substs.regions().get_slice(space).iter().zip(
5758 // For each region parameter 'subst...
5759 for bound_region in bound_set.iter() {
5760 // Which is declared with a bound like 'subst:'bound...
5761 match (subst_region, bound_region) {
5762 (&ty::ReFree(subst_fr), &ty::ReFree(bound_fr)) => {
5763 // Record that 'subst outlives 'bound. Or, put
5764 // another way, 'bound <= 'subst.
5765 tcx.region_maps.relate_free_regions(bound_fr, subst_fr);
5768 // All named regions are instantiated with free regions.
5770 format!("record_region_bounds: \
5771 non free region: {} / {}",
5772 subst_region.repr(tcx),
5773 bound_region.repr(tcx)).as_slice());
5782 pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
5784 ast::MutMutable => MutBorrow,
5785 ast::MutImmutable => ImmBorrow,
5789 pub fn to_mutbl_lossy(self) -> ast::Mutability {
5791 * Returns a mutability `m` such that an `&m T` pointer could
5792 * be used to obtain this borrow kind. Because borrow kinds
5793 * are richer than mutabilities, we sometimes have to pick a
5794 * mutability that is stronger than necessary so that it at
5795 * least *would permit* the borrow in question.
5799 MutBorrow => ast::MutMutable,
5800 ImmBorrow => ast::MutImmutable,
5802 // We have no type corresponding to a unique imm borrow, so
5803 // use `&mut`. It gives all the capabilities of an `&uniq`
5804 // and hence is a safe "over approximation".
5805 UniqueImmBorrow => ast::MutMutable,
5809 pub fn to_user_str(&self) -> &'static str {
5811 MutBorrow => "mutable",
5812 ImmBorrow => "immutable",
5813 UniqueImmBorrow => "uniquely immutable",
5818 impl<'tcx> mc::Typer<'tcx> for ty::ctxt<'tcx> {
5819 fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
5823 fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
5824 Ok(ty::node_id_to_type(self, id))
5827 fn node_method_ty(&self, method_call: typeck::MethodCall) -> Option<Ty<'tcx>> {
5828 self.method_map.borrow().get(&method_call).map(|method| method.ty)
5831 fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
5835 fn is_method_call(&self, id: ast::NodeId) -> bool {
5836 self.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
5839 fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<region::CodeExtent> {
5840 self.region_maps.temporary_scope(rvalue_id)
5843 fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
5844 self.upvar_borrow_map.borrow()[upvar_id].clone()
5847 fn capture_mode(&self, closure_expr_id: ast::NodeId)
5848 -> ast::CaptureClause {
5849 self.capture_modes.borrow()[closure_expr_id].clone()
5852 fn unboxed_closures<'a>(&'a self)
5853 -> &'a RefCell<DefIdMap<UnboxedClosure<'tcx>>> {
5854 &self.unboxed_closures
5858 /// The category of explicit self.
5859 #[deriving(Clone, Eq, PartialEq, Show)]
5860 pub enum ExplicitSelfCategory {
5861 StaticExplicitSelfCategory,
5862 ByValueExplicitSelfCategory,
5863 ByReferenceExplicitSelfCategory(Region, ast::Mutability),
5864 ByBoxExplicitSelfCategory,
5867 /// Pushes all the lifetimes in the given type onto the given list. A
5868 /// "lifetime in a type" is a lifetime specified by a reference or a lifetime
5869 /// in a list of type substitutions. This does *not* traverse into nominal
5870 /// types, nor does it resolve fictitious types.
5871 pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
5875 ty_rptr(region, _) => {
5876 accumulator.push(region)
5878 ty_trait(ref t) => {
5879 accumulator.push_all(t.principal.substs.regions().as_slice());
5881 ty_enum(_, ref substs) |
5882 ty_struct(_, ref substs) => {
5883 accum_substs(accumulator, substs);
5885 ty_closure(ref closure_ty) => {
5886 match closure_ty.store {
5887 RegionTraitStore(region, _) => accumulator.push(region),
5888 UniqTraitStore => {}
5891 ty_unboxed_closure(_, ref region, ref substs) => {
5892 accumulator.push(*region);
5893 accum_substs(accumulator, substs);
5914 fn accum_substs(accumulator: &mut Vec<Region>, substs: &Substs) {
5915 match substs.regions {
5916 subst::ErasedRegions => {}
5917 subst::NonerasedRegions(ref regions) => {
5918 for region in regions.iter() {
5919 accumulator.push(*region)
5926 /// A free variable referred to in a function.
5927 #[deriving(Encodable, Decodable)]
5928 pub struct Freevar {
5929 /// The variable being accessed free.
5932 // First span where it is accessed (there can be multiple).
5936 pub type FreevarMap = NodeMap<Vec<Freevar>>;
5938 pub type CaptureModeMap = NodeMap<ast::CaptureClause>;
5940 pub fn with_freevars<T>(tcx: &ty::ctxt, fid: ast::NodeId, f: |&[Freevar]| -> T) -> T {
5941 match tcx.freevars.borrow().get(&fid) {
5943 Some(d) => f(d.as_slice())
5947 impl<'tcx> AutoAdjustment<'tcx> {
5948 pub fn is_identity(&self) -> bool {
5950 AdjustAddEnv(..) => false,
5951 AdjustDerefRef(ref r) => r.is_identity(),
5956 impl<'tcx> AutoDerefRef<'tcx> {
5957 pub fn is_identity(&self) -> bool {
5958 self.autoderefs == 0 && self.autoref.is_none()
5962 pub fn liberate_late_bound_regions<'tcx, HR>(
5963 tcx: &ty::ctxt<'tcx>,
5964 scope: region::CodeExtent,
5967 where HR : HigherRankedFoldable<'tcx>
5970 * Replace any late-bound regions bound in `value` with free variants
5971 * attached to scope-id `scope_id`.
5974 replace_late_bound_regions(
5976 |br, _| ty::ReFree(ty::FreeRegion{scope: scope, bound_region: br})).0
5979 pub fn erase_late_bound_regions<'tcx, HR>(
5980 tcx: &ty::ctxt<'tcx>,
5983 where HR : HigherRankedFoldable<'tcx>
5986 * Replace any late-bound regions bound in `value` with `'static`.
5987 * Useful in trans but also method lookup and a few other places
5988 * where precise region relationships are not required.
5991 replace_late_bound_regions(tcx, value, |_, _| ty::ReStatic).0
5994 pub fn replace_late_bound_regions<'tcx, HR>(
5995 tcx: &ty::ctxt<'tcx>,
5997 mapf: |BoundRegion, DebruijnIndex| -> ty::Region)
5998 -> (HR, FnvHashMap<ty::BoundRegion,ty::Region>)
5999 where HR : HigherRankedFoldable<'tcx>
6002 * Replaces the late-bound-regions in `value` that are bound by `value`.
6005 debug!("replace_late_bound_regions({})", value.repr(tcx));
6007 let mut map = FnvHashMap::new();
6009 let mut f = ty_fold::RegionFolder::new(tcx, |region, current_depth| {
6010 debug!("region={}", region.repr(tcx));
6012 ty::ReLateBound(debruijn, br) if debruijn.depth == current_depth => {
6013 * match map.entry(br) {
6014 Vacant(entry) => entry.set(mapf(br, debruijn)),
6015 Occupied(entry) => entry.into_mut(),
6024 // Note: use `fold_contents` not `fold_with`. If we used
6025 // `fold_with`, it would consider the late-bound regions bound
6026 // by `value` to be bound, but we want to consider them as
6028 value.fold_contents(&mut f)
6030 debug!("resulting map: {} value: {}", map, value.repr(tcx));
6034 impl DebruijnIndex {
6035 pub fn new(depth: uint) -> DebruijnIndex {
6037 DebruijnIndex { depth: depth }
6040 pub fn shifted(&self, amount: uint) -> DebruijnIndex {
6041 DebruijnIndex { depth: self.depth + amount }
6045 impl<'tcx> Repr<'tcx> for AutoAdjustment<'tcx> {
6046 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6048 AdjustAddEnv(ref trait_store) => {
6049 format!("AdjustAddEnv({})", trait_store)
6051 AdjustDerefRef(ref data) => {
6058 impl<'tcx> Repr<'tcx> for UnsizeKind<'tcx> {
6059 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6061 UnsizeLength(n) => format!("UnsizeLength({})", n),
6062 UnsizeStruct(ref k, n) => format!("UnsizeStruct({},{})", k.repr(tcx), n),
6063 UnsizeVtable(ref a, ref b) => format!("UnsizeVtable({},{})", a.repr(tcx), b.repr(tcx)),
6068 impl<'tcx> Repr<'tcx> for AutoDerefRef<'tcx> {
6069 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6070 format!("AutoDerefRef({}, {})", self.autoderefs, self.autoref.repr(tcx))
6074 impl<'tcx> Repr<'tcx> for AutoRef<'tcx> {
6075 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6077 AutoPtr(a, b, ref c) => {
6078 format!("AutoPtr({},{},{})", a.repr(tcx), b, c.repr(tcx))
6080 AutoUnsize(ref a) => {
6081 format!("AutoUnsize({})", a.repr(tcx))
6083 AutoUnsizeUniq(ref a) => {
6084 format!("AutoUnsizeUniq({})", a.repr(tcx))
6086 AutoUnsafe(ref a, ref b) => {
6087 format!("AutoUnsafe({},{})", a, b.repr(tcx))
6093 impl<'tcx> Repr<'tcx> for TyTrait<'tcx> {
6094 fn repr(&self, tcx: &ctxt<'tcx>) -> String {
6095 format!("TyTrait({},{})",
6096 self.principal.repr(tcx),
6097 self.bounds.repr(tcx))