1 // Copyright 2012-2013 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.
13 use metadata::csearch;
15 use middle::const_eval;
17 use middle::lint::{get_lint_level, allow};
19 use middle::resolve::{Impl, MethodInfo};
22 use middle::subst::Subst;
25 use util::ppaux::{note_and_explain_region, bound_region_to_str};
26 use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
27 use util::ppaux::Repr;
28 use util::common::{indenter};
31 use core::ptr::to_unsafe_ptr;
33 use core::hashmap::{HashMap, HashSet};
34 use std::smallintmap::SmallIntMap;
36 use syntax::ast_util::{is_local, local_def};
39 use syntax::codemap::span;
41 use syntax::parse::token::special_idents;
42 use syntax::{ast, ast_map};
43 use syntax::opt_vec::OptVec;
45 use syntax::abi::AbiSet;
50 #[deriving(Eq, IterBytes)]
61 pub type param_bounds = @~[param_bound];
65 generics: ty::Generics,
66 transformed_self_ty: Option<ty::t>,
68 self_ty: ast::self_ty_,
76 mutbl: ast::mutability,
91 #[deriving(Eq, IterBytes)]
93 BoxTraitStore, // @Trait
94 UniqTraitStore, // ~Trait
95 RegionTraitStore(Region), // &Trait
98 // XXX: This should probably go away at some point. Maybe after destructors
108 pub struct field_ty {
111 vis: ast::visibility,
112 mutability: ast::struct_mutability,
115 // Contains information needed to resolve types and (in the future) look up
116 // the types of AST nodes.
118 pub struct creader_cache_key {
124 type creader_cache = @mut HashMap<creader_cache_key, t>;
126 impl to_bytes::IterBytes for creader_cache_key {
127 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
128 to_bytes::iter_bytes_3(&self.cnum, &self.pos, &self.len, lsb0, f);
136 // NB: Do not replace this with #[deriving(Eq)]. The automatically-derived
137 // implementation will not recurse through sty and you will get stack
139 impl cmp::Eq for intern_key {
140 fn eq(&self, other: &intern_key) -> bool {
142 *self.sty == *other.sty
145 fn ne(&self, other: &intern_key) -> bool {
150 impl to_bytes::IterBytes for intern_key {
151 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
153 (*self.sty).iter_bytes(lsb0, f);
158 pub enum ast_ty_to_ty_cache_entry {
159 atttce_unresolved, /* not resolved yet */
160 atttce_resolved(t) /* resolved to a type, irrespective of region */
163 pub type opt_region_variance = Option<region_variance>;
168 pub enum region_variance { rv_covariant, rv_invariant, rv_contravariant }
172 pub enum AutoAdjustment {
173 AutoAddEnv(ty::Region, ast::Sigil),
174 AutoDerefRef(AutoDerefRef)
179 pub struct AutoDerefRef {
181 autoref: Option<AutoRef>
189 mutbl: ast::mutability
194 pub enum AutoRefKind {
195 /// Convert from T to &T
198 /// Convert from @[]/~[]/&[] to &[] (or str)
201 /// Convert from @[]/~[]/&[] to &&[] (or str)
204 /// Convert from @fn()/~fn()/&fn() to &fn()
208 // Stores information about provided methods (a.k.a. default methods) in
211 // This is a map from ID of each implementation to the method info and trait
212 // method ID of each of the default methods belonging to the trait that that
213 // implementation implements.
214 pub type ProvidedMethodsMap = @mut HashMap<def_id,@mut ~[@ProvidedMethodInfo]>;
216 // Stores the method info and definition ID of the associated trait method for
217 // each instantiation of each provided method.
218 pub struct ProvidedMethodInfo {
219 method_info: @MethodInfo,
220 trait_method_def_id: def_id
223 pub struct ProvidedMethodSource {
224 method_id: ast::def_id,
228 pub type ctxt = @ctxt_;
231 diag: @syntax::diagnostic::span_handler,
232 interner: @mut HashMap<intern_key, ~t_box_>,
234 vecs_implicitly_copyable: bool,
236 cstore: @mut metadata::cstore::CStore,
237 sess: session::Session,
238 def_map: resolve::DefMap,
240 region_maps: @mut middle::region::RegionMaps,
241 region_paramd_items: middle::region::region_paramd_items,
243 // Stores the types for various nodes in the AST. Note that this table
244 // is not guaranteed to be populated until after typeck. See
245 // typeck::check::fn_ctxt for details.
246 node_types: node_type_table,
248 // Stores the type parameters which were substituted to obtain the type
249 // of this node. This only applies to nodes that refer to entities
250 // parameterized by type parameters, such as generic fns, types, or
252 node_type_substs: @mut HashMap<node_id, ~[t]>,
254 // Maps from a method to the method "descriptor"
255 methods: @mut HashMap<def_id, @method>,
257 // Maps from a trait def-id to a list of the def-ids of its methods
258 trait_method_def_ids: @mut HashMap<def_id, @~[def_id]>,
260 // A cache for the trait_methods() routine
261 trait_methods_cache: @mut HashMap<def_id, @~[@method]>,
263 trait_refs: @mut HashMap<node_id, @TraitRef>,
264 trait_defs: @mut HashMap<def_id, @TraitDef>,
267 intrinsic_defs: @mut HashMap<ast::ident, (ast::def_id, t)>,
268 intrinsic_traits: @mut HashMap<ast::ident, @TraitRef>,
269 freevars: freevars::freevar_map,
271 rcache: creader_cache,
272 ccache: constness_cache,
273 short_names_cache: @mut HashMap<t, @~str>,
274 needs_unwind_cleanup_cache: @mut HashMap<t, bool>,
275 tc_cache: @mut HashMap<uint, TypeContents>,
276 ast_ty_to_ty_cache: @mut HashMap<node_id, ast_ty_to_ty_cache_entry>,
277 enum_var_cache: @mut HashMap<def_id, @~[VariantInfo]>,
278 ty_param_defs: @mut HashMap<ast::node_id, TypeParameterDef>,
279 adjustments: @mut HashMap<ast::node_id, @AutoAdjustment>,
280 normalized_cache: @mut HashMap<t, t>,
281 lang_items: middle::lang_items::LanguageItems,
282 // A mapping from an implementation ID to the method info and trait
283 // method ID of the provided (a.k.a. default) methods in the traits that
284 // that implementation implements.
285 provided_methods: ProvidedMethodsMap,
286 provided_method_sources: @mut HashMap<ast::def_id, ProvidedMethodSource>,
287 supertraits: @mut HashMap<ast::def_id, @~[@TraitRef]>,
289 // A mapping from the def ID of an enum or struct type to the def ID
290 // of the method that implements its destructor. If the type is not
291 // present in this map, it does not have a destructor. This map is
292 // populated during the coherence phase of typechecking.
293 destructor_for_type: @mut HashMap<ast::def_id, ast::def_id>,
295 // A method will be in this list if and only if it is a destructor.
296 destructors: @mut HashSet<ast::def_id>,
298 // Maps a trait onto a mapping from self-ty to impl
299 trait_impls: @mut HashMap<ast::def_id, @mut HashMap<t, @Impl>>,
301 // Set of used unsafe nodes (functions or blocks). Unsafe nodes not
302 // present in this set can be warned about.
303 used_unsafe: @mut HashSet<ast::node_id>,
305 // Set of nodes which mark locals as mutable which end up getting used at
306 // some point. Local variable definitions not in this set can be warned
308 used_mut_nodes: @mut HashSet<ast::node_id>,
319 // a meta-flag: subst may be required if the type has parameters, a self
320 // type, or references bound regions
321 needs_subst = 1 | 2 | 8
324 pub type t_box = &'static t_box_;
332 // To reduce refcounting cost, we're representing types as unsafe pointers
333 // throughout the compiler. These are simply casted t_box values. Use ty::get
334 // to cast them back to a box. (Without the cast, compiler performance suffers
335 // ~15%.) This does mean that a t value relies on the ctxt to keep its box
336 // alive, and using ty::get is unsafe when the ctxt is no longer alive.
338 pub type t = *t_opaque;
340 pub fn get(t: t) -> t_box {
342 let t2: t_box = cast::transmute(t);
347 pub fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
348 (tb.flags & (flag as uint)) != 0u
350 pub fn type_has_params(t: t) -> bool {
351 tbox_has_flag(get(t), has_params)
353 pub fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
354 pub fn type_needs_infer(t: t) -> bool {
355 tbox_has_flag(get(t), needs_infer)
357 pub fn type_has_regions(t: t) -> bool {
358 tbox_has_flag(get(t), has_regions)
360 pub fn type_id(t: t) -> uint { get(t).id }
363 pub struct BareFnTy {
370 pub struct ClosureTy {
373 onceness: ast::Onceness,
379 * Signature of a function type, which I have arbitrarily
380 * decided to use to refer to the input/output types.
382 * - `lifetimes` is the list of region names bound in this fn.
383 * - `inputs` is the list of arguments and their modes.
384 * - `output` is the return type. */
387 bound_lifetime_names: OptVec<ast::ident>,
392 impl to_bytes::IterBytes for BareFnTy {
393 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
394 to_bytes::iter_bytes_3(&self.purity, &self.abis, &self.sig, lsb0, f)
398 impl to_bytes::IterBytes for ClosureTy {
399 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
400 to_bytes::iter_bytes_5(&self.purity, &self.sigil, &self.onceness,
401 &self.region, &self.sig, lsb0, f)
405 #[deriving(Eq, IterBytes)]
406 pub struct param_ty {
411 /// Representation of regions:
414 #[deriving(Eq, IterBytes)]
416 /// Bound regions are found (primarily) in function types. They indicate
417 /// region parameters that have yet to be replaced with actual regions
418 /// (analogous to type parameters, except that due to the monomorphic
419 /// nature of our type system, bound type parameters are always replaced
420 /// with fresh type variables whenever an item is referenced, so type
421 /// parameters only appear "free" in types. Regions in contrast can
422 /// appear free or bound.). When a function is called, all bound regions
423 /// tied to that function's node-id are replaced with fresh region
424 /// variables whose value is then inferred.
425 re_bound(bound_region),
427 /// When checking a function body, the types of all arguments and so forth
428 /// that refer to bound region parameters are modified to refer to free
429 /// region parameters.
432 /// A concrete region naming some expression within the current function.
435 /// Static data that has an "infinite" lifetime.
438 /// A region variable. Should not exist after typeck.
439 re_infer(InferRegion)
443 fn is_bound(&self) -> bool {
445 &re_bound(*) => true,
453 #[deriving(Eq, IterBytes)]
454 pub struct FreeRegion {
456 bound_region: bound_region
461 #[deriving(Eq, IterBytes)]
462 pub enum bound_region {
463 /// The self region for structs, impls (&T in a type defn or &'self T)
466 /// An anonymous region parameter for a given fn (&T)
469 /// Named region parameters for functions (a in &'a T)
470 br_named(ast::ident),
472 /// Fresh bound identifiers created during GLB computations.
476 * Handles capture-avoiding substitution in a rather subtle case. If you
477 * have a closure whose argument types are being inferred based on the
478 * expected type, and the expected type includes bound regions, then we
479 * will wrap those bound regions in a br_cap_avoid() with the id of the
480 * fn expression. This ensures that the names are not "captured" by the
481 * enclosing scope, which may define the same names. For an example of
482 * where this comes up, see src/test/compile-fail/regions-ret-borrowed.rs
483 * and regions-ret-borrowed-1.rs. */
484 br_cap_avoid(ast::node_id, @bound_region),
487 type opt_region = Option<Region>;
490 * The type substs represents the kinds of things that can be substituted to
491 * convert a polytype into a monotype. Note however that substituting bound
492 * regions other than `self` is done through a different mechanism:
494 * - `tps` represents the type parameters in scope. They are indexed
495 * according to the order in which they were declared.
497 * - `self_r` indicates the region parameter `self` that is present on nominal
498 * types (enums, structs) declared as having a region parameter. `self_r`
499 * should always be none for types that are not region-parameterized and
500 * Some(_) for types that are. The only bound region parameter that should
501 * appear within a region-parameterized type is `self`.
503 * - `self_ty` is the type to which `self` should be remapped, if any. The
504 * `self` type is rather funny in that it can only appear on traits and is
505 * always substituted away to the implementing type for a trait. */
509 self_ty: Option<ty::t>,
518 macro_rules! def_prim_ty(
519 ($name:ident, $sty:expr, $id:expr) => (
520 pub static $name: t_box_ = t_box_ {
528 def_prim_ty!(TY_NIL, super::ty_nil, 0)
529 def_prim_ty!(TY_BOOL, super::ty_bool, 1)
530 def_prim_ty!(TY_INT, super::ty_int(ast::ty_i), 2)
531 def_prim_ty!(TY_CHAR, super::ty_int(ast::ty_char), 3)
532 def_prim_ty!(TY_I8, super::ty_int(ast::ty_i8), 4)
533 def_prim_ty!(TY_I16, super::ty_int(ast::ty_i16), 5)
534 def_prim_ty!(TY_I32, super::ty_int(ast::ty_i32), 6)
535 def_prim_ty!(TY_I64, super::ty_int(ast::ty_i64), 7)
536 def_prim_ty!(TY_UINT, super::ty_uint(ast::ty_u), 8)
537 def_prim_ty!(TY_U8, super::ty_uint(ast::ty_u8), 9)
538 def_prim_ty!(TY_U16, super::ty_uint(ast::ty_u16), 10)
539 def_prim_ty!(TY_U32, super::ty_uint(ast::ty_u32), 11)
540 def_prim_ty!(TY_U64, super::ty_uint(ast::ty_u64), 12)
541 def_prim_ty!(TY_FLOAT, super::ty_float(ast::ty_f), 13)
542 def_prim_ty!(TY_F32, super::ty_float(ast::ty_f32), 14)
543 def_prim_ty!(TY_F64, super::ty_float(ast::ty_f64), 15)
545 pub static TY_BOT: t_box_ = t_box_ {
548 flags: super::has_ty_bot as uint,
551 pub static TY_ERR: t_box_ = t_box_ {
554 flags: super::has_ty_err as uint,
557 pub static LAST_PRIMITIVE_ID: uint = 18;
560 // NB: If you change this, you'll probably want to change the corresponding
561 // AST structure in libsyntax/ast.rs as well.
568 ty_uint(ast::uint_ty),
569 ty_float(ast::float_ty),
571 ty_enum(def_id, substs),
577 ty_bare_fn(BareFnTy),
578 ty_closure(ClosureTy),
579 ty_trait(def_id, substs, TraitStore, ast::mutability),
580 ty_struct(def_id, substs),
583 ty_param(param_ty), // type parameter
584 ty_self(def_id), /* special, implicit `self` type parameter;
585 * def_id is the id of the trait */
587 ty_infer(InferTy), // something used only during inference/typeck
588 ty_err, // Also only used during inference/typeck, to represent
589 // the type of an erroneous expression (helps cut down
590 // on non-useful type error messages)
592 // "Fake" types, used for trans purposes
593 ty_type, // type_desc*
594 ty_opaque_box, // used by monomorphizer to represent any @ box
595 ty_opaque_closure_ptr(Sigil), // ptr to env for &fn, @fn, ~fn
599 #[deriving(Eq, IterBytes)]
600 pub struct TraitRef {
606 pub enum IntVarValue {
607 IntType(ast::int_ty),
608 UintType(ast::uint_ty),
611 pub enum terr_vstore_kind {
612 terr_vec, terr_str, terr_fn, terr_trait
615 pub struct expected_found<T> {
620 // Data structures used in type unification
623 terr_purity_mismatch(expected_found<purity>),
624 terr_onceness_mismatch(expected_found<Onceness>),
625 terr_abi_mismatch(expected_found<AbiSet>),
627 terr_sigil_mismatch(expected_found<ast::Sigil>),
632 terr_tuple_size(expected_found<uint>),
633 terr_ty_param_size(expected_found<uint>),
634 terr_record_size(expected_found<uint>),
635 terr_record_mutability,
636 terr_record_fields(expected_found<ident>),
638 terr_regions_does_not_outlive(Region, Region),
639 terr_regions_not_same(Region, Region),
640 terr_regions_no_overlap(Region, Region),
641 terr_regions_insufficiently_polymorphic(bound_region, Region),
642 terr_regions_overly_polymorphic(bound_region, Region),
643 terr_vstores_differ(terr_vstore_kind, expected_found<vstore>),
644 terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
645 terr_in_field(@type_err, ast::ident),
646 terr_sorts(expected_found<t>),
648 terr_integer_as_char,
649 terr_int_mismatch(expected_found<IntVarValue>),
650 terr_float_mismatch(expected_found<ast::float_ty>),
651 terr_traits(expected_found<ast::def_id>),
654 #[deriving(Eq, IterBytes)]
655 pub enum param_bound {
660 bound_trait(@TraitRef),
664 pub struct TyVid(uint);
667 pub struct IntVid(uint);
670 pub struct FloatVid(uint);
675 pub struct RegionVid {
686 impl to_bytes::IterBytes for InferTy {
687 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
689 TyVar(ref tv) => to_bytes::iter_bytes_2(&0u8, tv, lsb0, f),
690 IntVar(ref iv) => to_bytes::iter_bytes_2(&1u8, iv, lsb0, f),
691 FloatVar(ref fv) => to_bytes::iter_bytes_2(&2u8, fv, lsb0, f),
698 pub enum InferRegion {
700 ReSkolemized(uint, bound_region)
703 impl to_bytes::IterBytes for InferRegion {
704 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
706 ReVar(ref rv) => to_bytes::iter_bytes_2(&0u8, rv, lsb0, f),
707 ReSkolemized(ref v, _) => to_bytes::iter_bytes_2(&1u8, v, lsb0, f)
712 impl cmp::Eq for InferRegion {
713 fn eq(&self, other: &InferRegion) -> bool {
714 match ((*self), *other) {
715 (ReVar(rva), ReVar(rvb)) => {
718 (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
724 fn ne(&self, other: &InferRegion) -> bool {
725 !((*self) == (*other))
730 fn to_uint(&self) -> uint;
734 fn to_uint(&self) -> uint { **self }
737 impl ToStr for TyVid {
738 fn to_str(&self) -> ~str { fmt!("<V%u>", self.to_uint()) }
741 impl Vid for IntVid {
742 fn to_uint(&self) -> uint { **self }
745 impl ToStr for IntVid {
746 fn to_str(&self) -> ~str { fmt!("<VI%u>", self.to_uint()) }
749 impl Vid for FloatVid {
750 fn to_uint(&self) -> uint { **self }
753 impl ToStr for FloatVid {
754 fn to_str(&self) -> ~str { fmt!("<VF%u>", self.to_uint()) }
757 impl Vid for RegionVid {
758 fn to_uint(&self) -> uint { self.id }
761 impl ToStr for RegionVid {
762 fn to_str(&self) -> ~str { fmt!("%?", self.id) }
765 impl ToStr for FnSig {
766 fn to_str(&self) -> ~str {
767 // grr, without tcx not much we can do.
772 impl ToStr for InferTy {
773 fn to_str(&self) -> ~str {
775 TyVar(ref v) => v.to_str(),
776 IntVar(ref v) => v.to_str(),
777 FloatVar(ref v) => v.to_str()
782 impl ToStr for IntVarValue {
783 fn to_str(&self) -> ~str {
785 IntType(ref v) => v.to_str(),
786 UintType(ref v) => v.to_str(),
791 impl to_bytes::IterBytes for TyVid {
792 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
793 self.to_uint().iter_bytes(lsb0, f)
797 impl to_bytes::IterBytes for IntVid {
798 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
799 self.to_uint().iter_bytes(lsb0, f)
803 impl to_bytes::IterBytes for FloatVid {
804 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
805 self.to_uint().iter_bytes(lsb0, f)
809 impl to_bytes::IterBytes for RegionVid {
810 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
811 self.to_uint().iter_bytes(lsb0, f)
815 pub struct TypeParameterDef {
820 /// Information about the type/lifetime parametesr associated with an item.
821 /// Analogous to ast::Generics.
822 pub struct Generics {
823 type_param_defs: @~[TypeParameterDef],
824 region_param: Option<region_variance>,
828 fn has_type_params(&self) -> bool {
829 !self.type_param_defs.is_empty()
835 /// - `bounds`: The list of bounds for each type parameter. The length of the
836 /// list also tells you how many type parameters there are.
838 /// - `rp`: true if the type is region-parameterized. Types can have at
839 /// most one region parameter, always called `&self`.
841 /// - `ty`: the base type. May have reference to the (unsubstituted) bound
842 /// region `&self` or to (unsubstituted) ty_param types
843 pub struct ty_param_bounds_and_ty {
848 /// As `ty_param_bounds_and_ty` but for a trait ref.
849 pub struct TraitDef {
851 trait_ref: @ty::TraitRef,
854 pub struct ty_param_substs_and_ty {
859 type type_cache = @mut HashMap<ast::def_id, ty_param_bounds_and_ty>;
861 type constness_cache = @mut HashMap<ast::def_id, const_eval::constness>;
863 pub type node_type_table = @mut SmallIntMap<t>;
865 fn mk_rcache() -> creader_cache {
866 return @mut HashMap::new();
869 pub fn new_ty_hash<V:Copy>() -> @mut HashMap<t, V> {
873 pub fn mk_ctxt(s: session::Session,
876 freevars: freevars::freevar_map,
877 region_maps: @mut middle::region::RegionMaps,
878 region_paramd_items: middle::region::region_paramd_items,
879 lang_items: middle::lang_items::LanguageItems,
882 let mut legacy_modes = false;
883 for crate.node.attrs.each |attribute| {
884 match attribute.node.value.node {
885 ast::meta_word(w) if *w == ~"legacy_modes" => {
892 let vecs_implicitly_copyable =
893 get_lint_level(s.lint_settings.default_settings,
894 lint::vecs_implicitly_copyable) == allow;
896 diag: s.diagnostic(),
897 interner: @mut HashMap::new(),
898 next_id: @mut primitives::LAST_PRIMITIVE_ID,
899 vecs_implicitly_copyable: vecs_implicitly_copyable,
900 legacy_modes: legacy_modes,
904 region_maps: region_maps,
905 region_paramd_items: region_paramd_items,
906 node_types: @mut SmallIntMap::new(),
907 node_type_substs: @mut HashMap::new(),
908 trait_refs: @mut HashMap::new(),
909 trait_defs: @mut HashMap::new(),
910 intrinsic_traits: @mut HashMap::new(),
912 intrinsic_defs: @mut HashMap::new(),
914 tcache: @mut HashMap::new(),
916 ccache: @mut HashMap::new(),
917 short_names_cache: new_ty_hash(),
918 needs_unwind_cleanup_cache: new_ty_hash(),
919 tc_cache: @mut HashMap::new(),
920 ast_ty_to_ty_cache: @mut HashMap::new(),
921 enum_var_cache: @mut HashMap::new(),
922 methods: @mut HashMap::new(),
923 trait_method_def_ids: @mut HashMap::new(),
924 trait_methods_cache: @mut HashMap::new(),
925 ty_param_defs: @mut HashMap::new(),
926 adjustments: @mut HashMap::new(),
927 normalized_cache: new_ty_hash(),
928 lang_items: lang_items,
929 provided_methods: @mut HashMap::new(),
930 provided_method_sources: @mut HashMap::new(),
931 supertraits: @mut HashMap::new(),
932 destructor_for_type: @mut HashMap::new(),
933 destructors: @mut HashSet::new(),
934 trait_impls: @mut HashMap::new(),
935 used_unsafe: @mut HashSet::new(),
936 used_mut_nodes: @mut HashSet::new(),
942 // Interns a type/name combination, stores the resulting box in cx.interner,
943 // and returns the box as cast to an unsafe ptr (see comments for t above).
944 fn mk_t(cx: ctxt, st: sty) -> t {
945 // Check for primitive types.
947 ty_nil => return mk_nil(),
948 ty_err => return mk_err(),
949 ty_bool => return mk_bool(),
950 ty_int(i) => return mk_mach_int(i),
951 ty_uint(u) => return mk_mach_uint(u),
952 ty_float(f) => return mk_mach_float(f),
956 let key = intern_key { sty: to_unsafe_ptr(&st) };
957 match cx.interner.find(&key) {
958 Some(t) => unsafe { return cast::transmute(&t.sty); },
963 fn rflags(r: Region) -> uint {
964 (has_regions as uint) | {
966 ty::re_infer(_) => needs_infer as uint,
971 fn sflags(substs: &substs) -> uint {
973 for substs.tps.each |tt| { f |= get(*tt).flags; }
974 for substs.self_r.each |r| { f |= rflags(*r) }
978 &ty_estr(vstore_slice(r)) => {
981 &ty_evec(ref mt, vstore_slice(r)) => {
983 flags |= get(mt.ty).flags;
985 &ty_nil | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
986 &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
987 &ty_opaque_box => (),
988 // You might think that we could just return ty_err for
989 // any type containing ty_err as a component, and get
990 // rid of the has_ty_err flag -- likewise for ty_bot (with
991 // the exception of function types that return bot).
992 // But doing so caused sporadic memory corruption, and
993 // neither I (tjc) nor nmatsakis could figure out why,
994 // so we're doing it this way.
995 &ty_bot => flags |= has_ty_bot as uint,
996 &ty_err => flags |= has_ty_err as uint,
997 &ty_param(_) => flags |= has_params as uint,
998 &ty_infer(_) => flags |= needs_infer as uint,
999 &ty_self(_) => flags |= has_self as uint,
1000 &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
1001 &ty_trait(_, ref substs, _, _) => {
1002 flags |= sflags(substs);
1004 &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
1005 &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
1006 flags |= get(m.ty).flags;
1008 &ty_rptr(r, ref m) => {
1010 flags |= get(m.ty).flags;
1012 &ty_tup(ref ts) => for ts.each |tt| { flags |= get(*tt).flags; },
1013 &ty_bare_fn(ref f) => {
1014 for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
1015 flags |= get(f.sig.output).flags;
1016 // T -> _|_ is *not* _|_ !
1017 flags &= !(has_ty_bot as uint);
1019 &ty_closure(ref f) => {
1020 flags |= rflags(f.region);
1021 for f.sig.inputs.each |a| { flags |= get(a.ty).flags; }
1022 flags |= get(f.sig.output).flags;
1023 // T -> _|_ is *not* _|_ !
1024 flags &= !(has_ty_bot as uint);
1034 let sty_ptr = to_unsafe_ptr(&t.sty);
1036 let key = intern_key {
1040 cx.interner.insert(key, t);
1045 cast::transmute::<*sty, t>(sty_ptr)
1050 pub fn mk_prim_t(primitive: &'static t_box_) -> t {
1052 cast::transmute::<&'static t_box_, t>(primitive)
1057 pub fn mk_nil() -> t { mk_prim_t(&primitives::TY_NIL) }
1060 pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) }
1063 pub fn mk_bot() -> t { mk_prim_t(&primitives::TY_BOT) }
1066 pub fn mk_bool() -> t { mk_prim_t(&primitives::TY_BOOL) }
1069 pub fn mk_int() -> t { mk_prim_t(&primitives::TY_INT) }
1072 pub fn mk_i8() -> t { mk_prim_t(&primitives::TY_I8) }
1075 pub fn mk_i16() -> t { mk_prim_t(&primitives::TY_I16) }
1078 pub fn mk_i32() -> t { mk_prim_t(&primitives::TY_I32) }
1081 pub fn mk_i64() -> t { mk_prim_t(&primitives::TY_I64) }
1084 pub fn mk_float() -> t { mk_prim_t(&primitives::TY_FLOAT) }
1087 pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) }
1090 pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) }
1093 pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) }
1096 pub fn mk_u8() -> t { mk_prim_t(&primitives::TY_U8) }
1099 pub fn mk_u16() -> t { mk_prim_t(&primitives::TY_U16) }
1102 pub fn mk_u32() -> t { mk_prim_t(&primitives::TY_U32) }
1105 pub fn mk_u64() -> t { mk_prim_t(&primitives::TY_U64) }
1107 pub fn mk_mach_int(tm: ast::int_ty) -> t {
1109 ast::ty_i => mk_int(),
1110 ast::ty_char => mk_char(),
1111 ast::ty_i8 => mk_i8(),
1112 ast::ty_i16 => mk_i16(),
1113 ast::ty_i32 => mk_i32(),
1114 ast::ty_i64 => mk_i64(),
1118 pub fn mk_mach_uint(tm: ast::uint_ty) -> t {
1120 ast::ty_u => mk_uint(),
1121 ast::ty_u8 => mk_u8(),
1122 ast::ty_u16 => mk_u16(),
1123 ast::ty_u32 => mk_u32(),
1124 ast::ty_u64 => mk_u64(),
1128 pub fn mk_mach_float(tm: ast::float_ty) -> t {
1130 ast::ty_f => mk_float(),
1131 ast::ty_f32 => mk_f32(),
1132 ast::ty_f64 => mk_f64(),
1137 pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) }
1139 pub fn mk_estr(cx: ctxt, t: vstore) -> t {
1140 mk_t(cx, ty_estr(t))
1143 pub fn mk_enum(cx: ctxt, did: ast::def_id, substs: substs) -> t {
1144 // take a copy of substs so that we own the vectors inside
1145 mk_t(cx, ty_enum(did, substs))
1148 pub fn mk_box(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_box(tm)) }
1150 pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
1151 mk_box(cx, mt {ty: ty, mutbl: ast::m_imm})
1154 pub fn mk_uniq(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_uniq(tm)) }
1156 pub fn mk_imm_uniq(cx: ctxt, ty: t) -> t {
1157 mk_uniq(cx, mt {ty: ty, mutbl: ast::m_imm})
1160 pub fn mk_ptr(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
1162 pub fn mk_rptr(cx: ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
1164 pub fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
1165 mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_mutbl})
1167 pub fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
1168 mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_imm})
1171 pub fn mk_mut_ptr(cx: ctxt, ty: t) -> t {
1172 mk_ptr(cx, mt {ty: ty, mutbl: ast::m_mutbl})
1175 pub fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
1176 mk_ptr(cx, mt {ty: ty, mutbl: ast::m_imm})
1179 pub fn mk_nil_ptr(cx: ctxt) -> t {
1180 mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::m_imm})
1183 pub fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
1184 mk_t(cx, ty_evec(tm, t))
1187 pub fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
1188 mk_t(cx, ty_unboxed_vec(tm))
1190 pub fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
1191 mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::m_imm}))
1194 pub fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
1196 pub fn mk_closure(cx: ctxt, fty: ClosureTy) -> t {
1197 mk_t(cx, ty_closure(fty))
1200 pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
1201 mk_t(cx, ty_bare_fn(fty))
1204 pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
1205 let input_args = input_tys.map(|t| arg { ty: *t });
1208 purity: ast::pure_fn,
1209 abis: AbiSet::Rust(),
1211 bound_lifetime_names: opt_vec::Empty,
1219 pub fn mk_trait(cx: ctxt,
1223 mutability: ast::mutability)
1225 // take a copy of substs so that we own the vectors inside
1226 mk_t(cx, ty_trait(did, substs, store, mutability))
1229 pub fn mk_struct(cx: ctxt, struct_id: ast::def_id, substs: substs) -> t {
1230 // take a copy of substs so that we own the vectors inside
1231 mk_t(cx, ty_struct(struct_id, substs))
1234 pub fn mk_var(cx: ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
1236 pub fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }
1238 pub fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
1240 pub fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
1242 pub fn mk_self(cx: ctxt, did: ast::def_id) -> t { mk_t(cx, ty_self(did)) }
1244 pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
1245 mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
1248 pub fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
1250 pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
1251 mk_t(cx, ty_opaque_closure_ptr(sigil))
1254 pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
1256 pub fn walk_ty(ty: t, f: &fn(t)) {
1257 maybe_walk_ty(ty, |t| { f(t); true });
1260 pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
1265 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1266 ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
1267 ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
1269 ty_box(ref tm) | ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) |
1270 ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
1271 maybe_walk_ty(tm.ty, f);
1273 ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1274 ty_trait(_, ref substs, _, _) => {
1275 for (*substs).tps.each |subty| { maybe_walk_ty(*subty, f); }
1277 ty_tup(ref ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
1278 ty_bare_fn(ref ft) => {
1279 for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
1280 maybe_walk_ty(ft.sig.output, f);
1282 ty_closure(ref ft) => {
1283 for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
1284 maybe_walk_ty(ft.sig.output, f);
1289 pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: &fn(t) -> t) -> t {
1290 mk_t(tcx, fold_sty(sty, foldop))
1293 pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
1294 let args = do sig.inputs.map |arg| {
1301 bound_lifetime_names: copy sig.bound_lifetime_names,
1303 output: fldop(sig.output)
1307 pub fn fold_bare_fn_ty(fty: &BareFnTy, fldop: &fn(t) -> t) -> BareFnTy {
1308 BareFnTy {sig: fold_sig(&fty.sig, fldop),
1313 fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
1314 fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs {
1315 substs {self_r: substs.self_r,
1316 self_ty: substs.self_ty.map(|t| fldop(*t)),
1317 tps: substs.tps.map(|t| fldop(*t))}
1322 ty_box(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1324 ty_uniq(ref tm) => {
1325 ty_uniq(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1328 ty_ptr(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1330 ty_unboxed_vec(ref tm) => {
1331 ty_unboxed_vec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1333 ty_evec(ref tm, vst) => {
1334 ty_evec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
1336 ty_enum(tid, ref substs) => {
1337 ty_enum(tid, fold_substs(substs, fldop))
1339 ty_trait(did, ref substs, st, mutbl) => {
1340 ty_trait(did, fold_substs(substs, fldop), st, mutbl)
1343 let new_ts = ts.map(|tt| fldop(*tt));
1346 ty_bare_fn(ref f) => {
1347 ty_bare_fn(fold_bare_fn_ty(f, fldop))
1349 ty_closure(ref f) => {
1350 let sig = fold_sig(&f.sig, fldop);
1351 ty_closure(ClosureTy {sig: sig, ..copy *f})
1353 ty_rptr(r, ref tm) => {
1354 ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1356 ty_struct(did, ref substs) => {
1357 ty_struct(did, fold_substs(substs, fldop))
1359 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1360 ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
1361 ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self(_) => {
1367 // Folds types from the bottom up.
1368 pub fn fold_ty(cx: ctxt, t0: t, fldop: &fn(t) -> t) -> t {
1369 let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
1370 fldop(mk_t(cx, sty))
1373 pub fn walk_regions_and_ty(
1376 walkr: &fn(r: Region),
1377 walkt: &fn(t: t) -> bool) {
1380 fold_regions_and_ty(
1382 |r| { walkr(r); r },
1383 |t| { walk_regions_and_ty(cx, t, walkr, walkt); t },
1384 |t| { walk_regions_and_ty(cx, t, walkr, walkt); t });
1388 pub fn fold_regions_and_ty(
1391 fldr: &fn(r: Region) -> Region,
1392 fldfnt: &fn(t: t) -> t,
1393 fldt: &fn(t: t) -> t) -> t {
1397 fldr: &fn(r: Region) -> Region,
1398 fldt: &fn(t: t) -> t)
1401 self_r: substs.self_r.map(|r| fldr(*r)),
1402 self_ty: substs.self_ty.map(|t| fldt(*t)),
1403 tps: substs.tps.map(|t| fldt(*t))
1407 let tb = ty::get(ty);
1409 ty::ty_rptr(r, mt) => {
1411 let m_t = fldt(mt.ty);
1412 ty::mk_rptr(cx, m_r, mt {ty: m_t, mutbl: mt.mutbl})
1414 ty_estr(vstore_slice(r)) => {
1416 ty::mk_estr(cx, vstore_slice(m_r))
1418 ty_evec(mt, vstore_slice(r)) => {
1420 let m_t = fldt(mt.ty);
1421 ty::mk_evec(cx, mt {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
1423 ty_enum(def_id, ref substs) => {
1424 ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
1426 ty_struct(def_id, ref substs) => {
1427 ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
1429 ty_trait(def_id, ref substs, st, mutbl) => {
1430 ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl)
1432 ty_bare_fn(ref f) => {
1433 ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt),
1436 ty_closure(ref f) => {
1437 ty::mk_closure(cx, ClosureTy {region: fldr(f.region),
1438 sig: fold_sig(&f.sig, fldfnt),
1442 fold_sty_to_ty(cx, sty, |t| fldt(t))
1447 // n.b. this function is intended to eventually replace fold_region() below,
1448 // that is why its name is so similar.
1449 pub fn fold_regions(
1452 fldr: &fn(r: Region, in_fn: bool) -> Region) -> t {
1453 fn do_fold(cx: ctxt, ty: t, in_fn: bool,
1454 fldr: &fn(Region, bool) -> Region) -> t {
1455 debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn);
1456 if !type_has_regions(ty) { return ty; }
1457 fold_regions_and_ty(
1460 |t| do_fold(cx, t, true, fldr),
1461 |t| do_fold(cx, t, in_fn, fldr))
1463 do_fold(cx, ty, false, fldr)
1466 // Substitute *only* type parameters. Used in trans where regions are erased.
1467 pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
1468 if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
1469 let tb = ty::get(typ);
1470 if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1472 ty_param(p) => tps[p.idx],
1475 None => cx.sess.bug(~"ty_self unexpected here"),
1477 subst_tps(cx, tps, self_ty_opt, self_ty)
1482 fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, self_ty_opt, t))
1487 pub fn substs_is_noop(substs: &substs) -> bool {
1488 substs.tps.len() == 0u &&
1489 substs.self_r.is_none() &&
1490 substs.self_ty.is_none()
1493 pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
1497 pub fn param_bound_to_str(cx: ctxt, pb: ¶m_bound) -> ~str {
1501 pub fn param_bounds_to_str(cx: ctxt, pbs: param_bounds) -> ~str {
1505 pub fn subst(cx: ctxt,
1509 typ.subst(cx, substs)
1514 pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
1516 pub fn type_is_bot(ty: t) -> bool {
1517 (get(ty).flags & (has_ty_bot as uint)) != 0
1520 pub fn type_is_error(ty: t) -> bool {
1521 (get(ty).flags & (has_ty_err as uint)) != 0
1524 pub fn type_needs_subst(ty: t) -> bool {
1525 tbox_has_flag(get(ty), needs_subst)
1528 pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
1529 tref.substs.self_ty.any(|&t| type_is_error(t)) ||
1530 tref.substs.tps.any(|&t| type_is_error(t))
1533 pub fn type_is_ty_var(ty: t) -> bool {
1535 ty_infer(TyVar(_)) => true,
1540 pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
1542 pub fn type_is_structural(ty: t) -> bool {
1544 ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_closure(_) | ty_trait(*) |
1545 ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
1546 ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
1552 pub fn type_is_sequence(ty: t) -> bool {
1554 ty_estr(_) | ty_evec(_, _) => true,
1559 pub fn type_is_str(ty: t) -> bool {
1566 pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
1568 ty_estr(_) => return mk_mach_uint(ast::ty_u8),
1569 ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
1571 ~"sequence_element_type called on non-sequence value"),
1575 pub fn get_element_type(ty: t, i: uint) -> t {
1577 ty_tup(ref ts) => return ts[i],
1578 _ => fail!(~"get_element_type called on invalid type")
1582 pub fn type_is_box(ty: t) -> bool {
1584 ty_box(_) => return true,
1589 pub fn type_is_boxed(ty: t) -> bool {
1591 ty_box(_) | ty_opaque_box |
1592 ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
1597 pub fn type_is_region_ptr(ty: t) -> bool {
1599 ty_rptr(_, _) => true,
1604 pub fn type_is_slice(ty: t) -> bool {
1606 ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true,
1611 pub fn type_is_unique_box(ty: t) -> bool {
1613 ty_uniq(_) => return true,
1618 pub fn type_is_unsafe_ptr(ty: t) -> bool {
1620 ty_ptr(_) => return true,
1625 pub fn type_is_vec(ty: t) -> bool {
1626 return match get(ty).sty {
1627 ty_evec(_, _) | ty_unboxed_vec(_) => true,
1633 pub fn type_is_unique(ty: t) -> bool {
1636 ty_evec(_, vstore_uniq) |
1637 ty_estr(vstore_uniq) |
1638 ty_opaque_closure_ptr(ast::OwnedSigil) => true,
1644 A scalar type is one that denotes an atomic datum, with no sub-components.
1645 (A ty_ptr is scalar because it represents a non-managed pointer, so its
1646 contents are abstract to rustc.)
1648 pub fn type_is_scalar(ty: t) -> bool {
1650 ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1651 ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
1652 ty_bare_fn(*) | ty_ptr(_) => true,
1657 pub fn type_is_immediate(ty: t) -> bool {
1658 return type_is_scalar(ty) || type_is_boxed(ty) ||
1659 type_is_unique(ty) || type_is_region_ptr(ty);
1662 pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1663 type_contents(cx, ty).needs_drop(cx)
1666 // Some things don't need cleanups during unwinding because the
1667 // task can free them all at once later. Currently only things
1668 // that only contain scalars and shared boxes can avoid unwind
1670 pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
1671 match cx.needs_unwind_cleanup_cache.find(&ty) {
1672 Some(&result) => return result,
1676 let mut tycache = HashSet::new();
1677 let needs_unwind_cleanup =
1678 type_needs_unwind_cleanup_(cx, ty, &mut tycache, false);
1679 cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup);
1680 return needs_unwind_cleanup;
1683 fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
1684 tycache: &mut HashSet<t>,
1685 encountered_box: bool) -> bool {
1687 // Prevent infinite recursion
1688 if !tycache.insert(ty) {
1692 let mut encountered_box = encountered_box;
1693 let mut needs_unwind_cleanup = false;
1694 do maybe_walk_ty(ty) |ty| {
1695 let old_encountered_box = encountered_box;
1696 let result = match get(ty).sty {
1697 ty_box(_) | ty_opaque_box => {
1698 encountered_box = true;
1701 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1702 ty_tup(_) | ty_ptr(_) => {
1705 ty_enum(did, ref substs) => {
1706 for vec::each(*enum_variants(cx, did)) |v| {
1707 for v.args.each |aty| {
1708 let t = subst(cx, substs, *aty);
1709 needs_unwind_cleanup |=
1710 type_needs_unwind_cleanup_(cx, t, tycache,
1714 !needs_unwind_cleanup
1717 ty_estr(vstore_uniq) |
1718 ty_estr(vstore_box) |
1719 ty_evec(_, vstore_uniq) |
1720 ty_evec(_, vstore_box)
1722 // Once we're inside a box, the annihilator will find
1723 // it and destroy it.
1724 if !encountered_box {
1725 needs_unwind_cleanup = true;
1732 needs_unwind_cleanup = true;
1737 encountered_box = old_encountered_box;
1741 return needs_unwind_cleanup;
1745 * Type contents is how the type checker reasons about kinds.
1746 * They track what kinds of things are found within a type. You can
1747 * think of them as kind of an "anti-kind". They track the kinds of values
1748 * and thinks that are contained in types. Having a larger contents for
1749 * a type tends to rule that type *out* from various kinds. For example,
1750 * a type that contains a borrowed pointer is not sendable.
1752 * The reason we compute type contents and not kinds is that it is
1753 * easier for me (nmatsakis) to think about what is contained within
1754 * a type than to think about what is *not* contained within a type.
1756 pub struct TypeContents {
1760 pub impl TypeContents {
1761 fn intersects(&self, tc: TypeContents) -> bool {
1762 (self.bits & tc.bits) != 0
1765 fn is_copy(&self, cx: ctxt) -> bool {
1766 !self.intersects(TypeContents::noncopyable(cx))
1769 fn noncopyable(_cx: ctxt) -> TypeContents {
1770 TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_OWNED_CLOSURE +
1774 fn is_durable(&self, cx: ctxt) -> bool {
1775 !self.intersects(TypeContents::nondurable(cx))
1778 fn nondurable(_cx: ctxt) -> TypeContents {
1782 fn is_owned(&self, cx: ctxt) -> bool {
1783 !self.intersects(TypeContents::nonowned(cx))
1786 fn nonowned(_cx: ctxt) -> TypeContents {
1787 TC_MANAGED + TC_BORROWED_POINTER
1790 fn contains_managed(&self) -> bool {
1791 self.intersects(TC_MANAGED)
1794 fn is_const(&self, cx: ctxt) -> bool {
1795 !self.intersects(TypeContents::nonconst(cx))
1798 fn nonconst(_cx: ctxt) -> TypeContents {
1802 fn moves_by_default(&self, cx: ctxt) -> bool {
1803 self.intersects(TypeContents::nonimplicitly_copyable(cx))
1806 fn nonimplicitly_copyable(cx: ctxt) -> TypeContents {
1807 let base = TypeContents::noncopyable(cx) + TC_OWNED_POINTER;
1808 if cx.vecs_implicitly_copyable {base} else {base + TC_OWNED_VEC}
1811 fn is_safe_for_default_mode(&self, cx: ctxt) -> bool {
1812 !self.intersects(TypeContents::nondefault_mode(cx))
1815 fn nondefault_mode(cx: ctxt) -> TypeContents {
1816 let tc = TypeContents::nonimplicitly_copyable(cx);
1817 tc + TC_BIG + TC_OWNED_VEC // disregard cx.vecs_implicitly_copyable
1820 fn needs_drop(&self, cx: ctxt) -> bool {
1821 let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx);
1825 fn owned(_cx: ctxt) -> TypeContents {
1826 //! Any kind of owned contents.
1827 TC_OWNED_CLOSURE + TC_OWNED_POINTER + TC_OWNED_VEC
1831 impl ops::Add<TypeContents,TypeContents> for TypeContents {
1832 fn add(&self, other: &TypeContents) -> TypeContents {
1833 TypeContents {bits: self.bits | other.bits}
1837 impl ops::Sub<TypeContents,TypeContents> for TypeContents {
1838 fn sub(&self, other: &TypeContents) -> TypeContents {
1839 TypeContents {bits: self.bits & !other.bits}
1843 impl ToStr for TypeContents {
1844 fn to_str(&self) -> ~str {
1845 fmt!("TypeContents(%s)", u32::to_str_radix(self.bits, 2))
1849 /// Constant for a type containing nothing of interest.
1850 static TC_NONE: TypeContents = TypeContents{bits:0b0000_00000000};
1852 /// Contains a borrowed value with a lifetime other than static
1853 static TC_BORROWED_POINTER: TypeContents = TypeContents{bits:0b0000_00000001};
1855 /// Contains an owned pointer (~T) but not slice of some kind
1856 static TC_OWNED_POINTER: TypeContents = TypeContents{bits:0b000000000010};
1858 /// Contains an owned vector ~[] or owned string ~str
1859 static TC_OWNED_VEC: TypeContents = TypeContents{bits:0b000000000100};
1861 /// Contains a ~fn() or a ~Trait, which is non-copyable.
1862 static TC_OWNED_CLOSURE: TypeContents = TypeContents{bits:0b000000001000};
1864 /// Type with a destructor
1865 static TC_DTOR: TypeContents = TypeContents{bits:0b000000010000};
1867 /// Contains a managed value
1868 static TC_MANAGED: TypeContents = TypeContents{bits:0b000000100000};
1870 /// &mut with any region
1871 static TC_BORROWED_MUT: TypeContents = TypeContents{bits:0b000001000000};
1873 /// Mutable content, whether owned or by ref
1874 static TC_MUTABLE: TypeContents = TypeContents{bits:0b000010000000};
1876 /// Mutable content, whether owned or by ref
1877 static TC_ONCE_CLOSURE: TypeContents = TypeContents{bits:0b000100000000};
1879 /// Something we estimate to be "big"
1880 static TC_BIG: TypeContents = TypeContents{bits:0b001000000000};
1882 /// An enum with no variants.
1883 static TC_EMPTY_ENUM: TypeContents = TypeContents{bits:0b010000000000};
1885 /// All possible contents.
1886 static TC_ALL: TypeContents = TypeContents{bits:0b011111111111};
1888 pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
1889 type_contents(cx, t).is_copy(cx)
1892 pub fn type_is_durable(cx: ctxt, t: ty::t) -> bool {
1893 type_contents(cx, t).is_durable(cx)
1896 pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool {
1897 type_contents(cx, t).is_owned(cx)
1900 pub fn type_is_const(cx: ctxt, t: ty::t) -> bool {
1901 type_contents(cx, t).is_const(cx)
1904 pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
1905 let ty_id = type_id(ty);
1906 match cx.tc_cache.find(&ty_id) {
1907 Some(tc) => { return *tc; }
1911 let mut cache = HashMap::new();
1912 let result = tc_ty(cx, ty, &mut cache);
1913 cx.tc_cache.insert(ty_id, result);
1918 cache: &mut HashMap<uint, TypeContents>) -> TypeContents
1920 // Subtle: Note that we are *not* using cx.tc_cache here but rather a
1921 // private cache for this walk. This is needed in the case of cyclic
1924 // struct List { next: ~Option<List>, ... }
1926 // When computing the type contents of such a type, we wind up deeply
1927 // recursing as we go. So when we encounter the recursive reference
1928 // to List, we temporarily use TC_NONE as its contents. Later we'll
1929 // patch up the cache with the correct value, once we've computed it
1930 // (this is basically a co-inductive process, if that helps). So in
1931 // the end we'll compute TC_OWNED_POINTER, in this case.
1933 // The problem is, as we are doing the computation, we will also
1934 // compute an *intermediate* contents for, e.g., Option<List> of
1935 // TC_NONE. This is ok during the computation of List itself, but if
1936 // we stored this intermediate value into cx.tc_cache, then later
1937 // requests for the contents of Option<List> would also yield TC_NONE
1938 // which is incorrect. This value was computed based on the crutch
1939 // value for the type contents of list. The correct value is
1940 // TC_OWNED_POINTER. This manifested as issue #4821.
1941 let ty_id = type_id(ty);
1942 match cache.find(&ty_id) {
1943 Some(tc) => { return *tc; }
1946 match cx.tc_cache.find(&ty_id) { // Must check both caches!
1947 Some(tc) => { return *tc; }
1950 cache.insert(ty_id, TC_NONE);
1952 let _i = indenter();
1954 let mut result = match get(ty).sty {
1955 // Scalar and unique types are sendable, constant, and owned
1956 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1957 ty_bare_fn(_) | ty_ptr(_) => {
1961 ty_estr(vstore_uniq) => {
1965 ty_closure(ref c) => {
1970 TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
1973 ty_trait(_, _, UniqTraitStore, _) => {
1977 ty_trait(_, _, BoxTraitStore, mutbl) => {
1979 ast::m_mutbl => TC_MANAGED + TC_MUTABLE,
1984 ty_trait(_, _, RegionTraitStore(r), mutbl) => {
1985 borrowed_contents(r, mutbl)
1989 borrowed_contents(r, mt.mutbl) +
1990 nonowned(tc_mt(cx, mt, cache))
1994 TC_OWNED_POINTER + tc_mt(cx, mt, cache)
1997 ty_evec(mt, vstore_uniq) => {
1998 TC_OWNED_VEC + tc_mt(cx, mt, cache)
2001 ty_evec(mt, vstore_box) => {
2002 TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
2005 ty_evec(mt, vstore_slice(r)) => {
2006 borrowed_contents(r, mt.mutbl) +
2007 nonowned(tc_mt(cx, mt, cache))
2010 ty_evec(mt, vstore_fixed(_)) => {
2011 tc_mt(cx, mt, cache)
2014 ty_estr(vstore_box) => {
2018 ty_estr(vstore_slice(r)) => {
2019 borrowed_contents(r, m_imm)
2022 ty_estr(vstore_fixed(_)) => {
2026 ty_struct(did, ref substs) => {
2027 let flds = struct_fields(cx, did, substs);
2028 let flds_tc = flds.foldl(
2030 |tc, f| tc + tc_mt(cx, f.mt, cache));
2031 if ty::has_dtor(cx, did) {
2038 ty_tup(ref tys) => {
2039 tys.foldl(TC_NONE, |tc, ty| *tc + tc_ty(cx, *ty, cache))
2042 ty_enum(did, ref substs) => {
2043 let variants = substd_enum_variants(cx, did, substs);
2044 if variants.is_empty() {
2045 // we somewhat arbitrary declare that empty enums
2049 variants.foldl(TC_NONE, |tc, variant| {
2052 |tc, arg_ty| *tc + tc_ty(cx, *arg_ty, cache))
2058 // We only ever ask for the kind of types that are defined in
2059 // the current crate; therefore, the only type parameters that
2060 // could be in scope are those defined in the current crate.
2061 // If this assertion failures, it is likely because of a
2062 // failure in the cross-crate inlining code to translate a
2064 assert!(p.def_id.crate == ast::local_crate);
2066 type_param_def_to_contents(
2067 cx, cx.ty_param_defs.get(&p.def_id.node))
2071 // Currently, self is not bounded, so we must assume the
2072 // worst. But in the future we should examine the super
2075 // FIXME(#4678)---self should just be a ty param
2080 // This occurs during coherence, but shouldn't occur at other
2085 ty_opaque_box => TC_MANAGED,
2086 ty_unboxed_vec(mt) => tc_mt(cx, mt, cache),
2087 ty_opaque_closure_ptr(sigil) => {
2089 ast::BorrowedSigil => TC_BORROWED_POINTER,
2090 ast::ManagedSigil => TC_MANAGED,
2091 ast::OwnedSigil => TC_OWNED_CLOSURE
2098 cx.sess.bug(~"Asked to compute contents of fictitious type");
2102 if type_size(cx, ty) > 4 {
2103 result = result + TC_BIG;
2106 cache.insert(ty_id, result);
2112 cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2114 let mc = if mt.mutbl == m_mutbl {TC_MUTABLE} else {TC_NONE};
2115 mc + tc_ty(cx, mt.ty, cache)
2118 fn borrowed_contents(region: ty::Region,
2119 mutbl: ast::mutability) -> TypeContents
2121 let mc = if mutbl == m_mutbl {
2122 TC_MUTABLE + TC_BORROWED_MUT
2126 let rc = if region != ty::re_static {
2134 fn nonowned(pointee: TypeContents) -> TypeContents {
2137 * Given a non-owning pointer to some type `T` with
2138 * contents `pointee` (like `@T` or
2139 * `&T`), returns the relevant bits that
2140 * apply to the owner of the pointer.
2143 let mask = TC_MUTABLE.bits | TC_BORROWED_POINTER.bits;
2144 TypeContents {bits: pointee.bits & mask}
2147 fn closure_contents(cty: &ClosureTy) -> TypeContents {
2148 let st = match cty.sigil {
2149 ast::BorrowedSigil => TC_BORROWED_POINTER,
2150 ast::ManagedSigil => TC_MANAGED,
2151 ast::OwnedSigil => TC_OWNED_CLOSURE
2153 let rt = borrowed_contents(cty.region, m_imm);
2154 let ot = match cty.onceness {
2155 ast::Once => TC_ONCE_CLOSURE,
2156 ast::Many => TC_NONE
2161 fn type_param_def_to_contents(cx: ctxt,
2162 type_param_def: &TypeParameterDef) -> TypeContents
2164 debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx));
2165 let _i = indenter();
2167 let r = type_param_def.bounds.foldl(TC_ALL, |tc, bound| {
2168 debug!("tc = %s, bound = %?", tc.to_str(), bound);
2170 bound_copy => tc - TypeContents::nonimplicitly_copyable(cx),
2171 bound_durable => tc - TypeContents::nondurable(cx),
2172 bound_owned => tc - TypeContents::nonowned(cx),
2173 bound_const => tc - TypeContents::nonconst(cx),
2174 bound_trait(_) => *tc
2178 debug!("result = %s", r.to_str());
2182 /// gives a rough estimate of how much space it takes to represent
2183 /// an instance of `ty`. Used for the mode transition.
2184 fn type_size(cx: ctxt, ty: t) -> uint {
2186 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
2187 ty_ptr(_) | ty_box(_) | ty_uniq(_) | ty_estr(vstore_uniq) |
2188 ty_trait(*) | ty_rptr(*) | ty_evec(_, vstore_uniq) |
2189 ty_evec(_, vstore_box) | ty_estr(vstore_box) => {
2193 ty_evec(_, vstore_slice(_)) |
2194 ty_estr(vstore_slice(_)) |
2200 ty_evec(t, vstore_fixed(n)) => {
2201 type_size(cx, t.ty) * n
2204 ty_estr(vstore_fixed(n)) => {
2208 ty_struct(did, ref substs) => {
2209 let flds = struct_fields(cx, did, substs);
2210 flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2213 ty_tup(ref tys) => {
2214 tys.foldl(0, |s, t| *s + type_size(cx, *t))
2217 ty_enum(did, ref substs) => {
2218 let variants = substd_enum_variants(cx, did, substs);
2219 variants.foldl( // find max size of any variant
2223 // find size of this variant:
2224 v.args.foldl(0, |s, a| *s + type_size(cx, *a))))
2227 ty_param(_) | ty_self(_) => {
2232 cx.sess.bug(~"Asked to compute kind of a type variable");
2235 ty_opaque_closure_ptr(_) => 1,
2237 ty_unboxed_vec(_) => 10,
2239 cx.sess.bug(~"Asked to compute kind of fictitious type");
2245 pub fn type_moves_by_default(cx: ctxt, ty: t) -> bool {
2246 type_contents(cx, ty).moves_by_default(cx)
2249 // True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2250 pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
2251 fn type_requires(cx: ctxt, seen: &mut ~[def_id],
2252 r_ty: t, ty: t) -> bool {
2253 debug!("type_requires(%s, %s)?",
2254 ::util::ppaux::ty_to_str(cx, r_ty),
2255 ::util::ppaux::ty_to_str(cx, ty));
2258 get(r_ty).sty == get(ty).sty ||
2259 subtypes_require(cx, seen, r_ty, ty)
2262 debug!("type_requires(%s, %s)? %b",
2263 ::util::ppaux::ty_to_str(cx, r_ty),
2264 ::util::ppaux::ty_to_str(cx, ty),
2269 fn subtypes_require(cx: ctxt, seen: &mut ~[def_id],
2270 r_ty: t, ty: t) -> bool {
2271 debug!("subtypes_require(%s, %s)?",
2272 ::util::ppaux::ty_to_str(cx, r_ty),
2273 ::util::ppaux::ty_to_str(cx, ty));
2275 let r = match get(ty).sty {
2291 ty_opaque_closure_ptr(_) |
2293 ty_unboxed_vec(_) => {
2298 ty_rptr(_, ref mt) => {
2299 return type_requires(cx, seen, r_ty, mt.ty);
2303 false // unsafe ptrs can always be NULL
2306 ty_trait(_, _, _, _) => {
2310 ty_struct(ref did, _) if vec::contains(*seen, did) => {
2314 ty_struct(did, ref substs) => {
2316 let r = vec::any(struct_fields(cx, did, substs),
2317 |f| type_requires(cx, seen, r_ty, f.mt.ty));
2323 ts.any(|t| type_requires(cx, seen, r_ty, *t))
2326 ty_enum(ref did, _) if vec::contains(*seen, did) => {
2330 ty_enum(did, ref substs) => {
2332 let vs = enum_variants(cx, did);
2333 let r = vec::len(*vs) > 0u && vec::all(*vs, |variant| {
2334 vec::any(variant.args, |aty| {
2335 let sty = subst(cx, substs, *aty);
2336 type_requires(cx, seen, r_ty, sty)
2344 debug!("subtypes_require(%s, %s)? %b",
2345 ::util::ppaux::ty_to_str(cx, r_ty),
2346 ::util::ppaux::ty_to_str(cx, ty),
2352 let seen = @mut ~[];
2353 !subtypes_require(cx, seen, r_ty, r_ty)
2356 pub fn type_structurally_contains(cx: ctxt,
2358 test: &fn(x: &sty) -> bool)
2360 let sty = &get(ty).sty;
2361 debug!("type_structurally_contains: %s",
2362 ::util::ppaux::ty_to_str(cx, ty));
2363 if test(sty) { return true; }
2365 ty_enum(did, ref substs) => {
2366 for vec::each(*enum_variants(cx, did)) |variant| {
2367 for variant.args.each |aty| {
2368 let sty = subst(cx, substs, *aty);
2369 if type_structurally_contains(cx, sty, test) { return true; }
2374 ty_struct(did, ref substs) => {
2375 for lookup_struct_fields(cx, did).each |field| {
2376 let ft = lookup_field_type(cx, did, field.id, substs);
2377 if type_structurally_contains(cx, ft, test) { return true; }
2384 if type_structurally_contains(cx, *tt, test) { return true; }
2388 ty_evec(ref mt, vstore_fixed(_)) => {
2389 return type_structurally_contains(cx, mt.ty, test);
2395 pub fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
2396 return type_structurally_contains(cx, ty, |sty| {
2399 ty_evec(_, vstore_uniq) |
2400 ty_estr(vstore_uniq) => true,
2406 pub fn type_is_integral(ty: t) -> bool {
2408 ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
2413 pub fn type_is_char(ty: t) -> bool {
2415 ty_int(ty_char) => true,
2420 pub fn type_is_fp(ty: t) -> bool {
2422 ty_infer(FloatVar(_)) | ty_float(_) => true,
2427 pub fn type_is_numeric(ty: t) -> bool {
2428 return type_is_integral(ty) || type_is_fp(ty);
2431 pub fn type_is_signed(ty: t) -> bool {
2438 // Whether a type is Plain Old Data -- meaning it does not contain pointers
2439 // that the cycle collector might care about.
2440 pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
2441 let mut result = true;
2444 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
2445 ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
2447 ty_box(_) | ty_uniq(_) | ty_closure(_) |
2448 ty_estr(vstore_uniq) | ty_estr(vstore_box) |
2449 ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
2450 ty_trait(_, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
2452 ty_enum(did, ref substs) => {
2453 let variants = enum_variants(cx, did);
2454 for vec::each(*variants) |variant| {
2455 let tup_ty = mk_tup(cx, /*bad*/copy variant.args);
2457 // Perform any type parameter substitutions.
2458 let tup_ty = subst(cx, substs, tup_ty);
2459 if !type_is_pod(cx, tup_ty) { result = false; }
2462 ty_tup(ref elts) => {
2463 for elts.each |elt| { if !type_is_pod(cx, *elt) { result = false; } }
2465 ty_estr(vstore_fixed(_)) => result = true,
2466 ty_evec(ref mt, vstore_fixed(_)) | ty_unboxed_vec(ref mt) => {
2467 result = type_is_pod(cx, mt.ty);
2469 ty_param(_) => result = false,
2470 ty_opaque_closure_ptr(_) => result = true,
2471 ty_struct(did, ref substs) => {
2472 result = vec::any(lookup_struct_fields(cx, did), |f| {
2473 let fty = ty::lookup_item_type(cx, f.id);
2474 let sty = subst(cx, substs, fty.ty);
2475 type_is_pod(cx, sty)
2479 ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2483 ty_infer(*) | ty_self(*) | ty_err => {
2484 cx.sess.bug(~"non concrete type in type_is_pod");
2491 pub fn type_is_enum(ty: t) -> bool {
2493 ty_enum(_, _) => return true,
2498 // Whether a type is enum like, that is a enum type with only nullary
2500 pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2502 ty_enum(did, _) => {
2503 let variants = enum_variants(cx, did);
2504 if variants.len() == 0 {
2507 variants.all(|v| v.args.len() == 0)
2514 pub fn type_param(ty: t) -> Option<uint> {
2516 ty_param(p) => return Some(p.idx),
2517 _ => {/* fall through */ }
2522 // Returns the type and mutability of *t.
2524 // The parameter `explicit` indicates if this is an *explicit* dereference.
2525 // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
2526 pub fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
2527 deref_sty(cx, &get(t).sty, explicit)
2530 pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
2532 ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
2536 ty_ptr(mt) if explicit => {
2540 ty_enum(did, ref substs) => {
2541 let variants = enum_variants(cx, did);
2542 if vec::len(*variants) == 1u && vec::len(variants[0].args) == 1u {
2543 let v_t = subst(cx, substs, variants[0].args[0]);
2544 Some(mt {ty: v_t, mutbl: ast::m_imm})
2550 ty_struct(did, ref substs) => {
2551 let fields = struct_fields(cx, did, substs);
2552 if fields.len() == 1 && fields[0].ident ==
2553 syntax::parse::token::special_idents::unnamed_field {
2554 Some(mt {ty: fields[0].mt.ty, mutbl: ast::m_imm})
2564 pub fn type_autoderef(cx: ctxt, t: t) -> t {
2567 match deref(cx, t, false) {
2569 Some(mt) => t = mt.ty
2574 // Returns the type and mutability of t[i]
2575 pub fn index(t: t) -> Option<mt> {
2576 index_sty(&get(t).sty)
2579 pub fn index_sty(sty: &sty) -> Option<mt> {
2581 ty_evec(mt, _) => Some(mt),
2582 ty_estr(_) => Some(mt {ty: mk_u8(), mutbl: ast::m_imm}),
2588 * Enforces an arbitrary but consistent total ordering over
2589 * free regions. This is needed for establishing a consistent
2590 * LUB in region_inference. */
2591 impl cmp::TotalOrd for FreeRegion {
2592 fn cmp(&self, other: &FreeRegion) -> Ordering {
2593 cmp::cmp2(&self.scope_id, &self.bound_region,
2594 &other.scope_id, &other.bound_region)
2598 impl cmp::TotalEq for FreeRegion {
2599 fn equals(&self, other: &FreeRegion) -> bool {
2605 * Enforces an arbitrary but consistent total ordering over
2606 * bound regions. This is needed for establishing a consistent
2607 * LUB in region_inference. */
2608 impl cmp::TotalOrd for bound_region {
2609 fn cmp(&self, other: &bound_region) -> Ordering {
2610 match (self, other) {
2611 (&ty::br_self, &ty::br_self) => cmp::Equal,
2612 (&ty::br_self, _) => cmp::Less,
2614 (&ty::br_anon(ref a1), &ty::br_anon(ref a2)) => a1.cmp(a2),
2615 (&ty::br_anon(*), _) => cmp::Less,
2617 (&ty::br_named(ref a1), &ty::br_named(ref a2)) => a1.repr.cmp(&a2.repr),
2618 (&ty::br_named(*), _) => cmp::Less,
2620 (&ty::br_cap_avoid(ref a1, @ref b1),
2621 &ty::br_cap_avoid(ref a2, @ref b2)) => cmp::cmp2(a1, b1, a2, b2),
2622 (&ty::br_cap_avoid(*), _) => cmp::Less,
2624 (&ty::br_fresh(ref a1), &ty::br_fresh(ref a2)) => a1.cmp(a2),
2625 (&ty::br_fresh(*), _) => cmp::Less,
2630 impl cmp::TotalEq for bound_region {
2631 fn equals(&self, other: &bound_region) -> bool {
2636 impl to_bytes::IterBytes for vstore {
2637 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2639 vstore_fixed(ref u) =>
2640 to_bytes::iter_bytes_2(&0u8, u, lsb0, f),
2642 vstore_uniq => 1u8.iter_bytes(lsb0, f),
2643 vstore_box => 2u8.iter_bytes(lsb0, f),
2645 vstore_slice(ref r) =>
2646 to_bytes::iter_bytes_2(&3u8, r, lsb0, f),
2651 impl to_bytes::IterBytes for substs {
2652 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2653 to_bytes::iter_bytes_3(&self.self_r,
2659 impl to_bytes::IterBytes for mt {
2660 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2661 to_bytes::iter_bytes_2(&self.ty,
2662 &self.mutbl, lsb0, f)
2666 impl to_bytes::IterBytes for field {
2667 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2668 to_bytes::iter_bytes_2(&self.ident,
2673 impl to_bytes::IterBytes for FnSig {
2674 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2675 to_bytes::iter_bytes_2(&self.inputs,
2681 impl to_bytes::IterBytes for sty {
2682 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2684 ty_nil => 0u8.iter_bytes(lsb0, f),
2685 ty_bool => 1u8.iter_bytes(lsb0, f),
2688 to_bytes::iter_bytes_2(&2u8, t, lsb0, f),
2691 to_bytes::iter_bytes_2(&3u8, t, lsb0, f),
2694 to_bytes::iter_bytes_2(&4u8, t, lsb0, f),
2697 to_bytes::iter_bytes_2(&5u8, v, lsb0, f),
2699 ty_enum(ref did, ref substs) =>
2700 to_bytes::iter_bytes_3(&6u8, did, substs, lsb0, f),
2703 to_bytes::iter_bytes_2(&7u8, mt, lsb0, f),
2705 ty_evec(ref mt, ref v) =>
2706 to_bytes::iter_bytes_3(&8u8, mt, v, lsb0, f),
2708 ty_unboxed_vec(ref mt) =>
2709 to_bytes::iter_bytes_2(&9u8, mt, lsb0, f),
2712 to_bytes::iter_bytes_2(&10u8, ts, lsb0, f),
2714 ty_bare_fn(ref ft) =>
2715 to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
2717 ty_self(ref did) => to_bytes::iter_bytes_2(&13u8, did, lsb0, f),
2720 to_bytes::iter_bytes_2(&14u8, v, lsb0, f),
2723 to_bytes::iter_bytes_2(&15u8, p, lsb0, f),
2725 ty_type => 16u8.iter_bytes(lsb0, f),
2726 ty_bot => 17u8.iter_bytes(lsb0, f),
2729 to_bytes::iter_bytes_2(&18u8, mt, lsb0, f),
2732 to_bytes::iter_bytes_2(&19u8, mt, lsb0, f),
2734 ty_trait(ref did, ref substs, ref v, ref mutbl) =>
2735 to_bytes::iter_bytes_5(&20u8, did, substs, v, mutbl, lsb0, f),
2737 ty_opaque_closure_ptr(ref ck) =>
2738 to_bytes::iter_bytes_2(&21u8, ck, lsb0, f),
2740 ty_opaque_box => 22u8.iter_bytes(lsb0, f),
2742 ty_struct(ref did, ref substs) =>
2743 to_bytes::iter_bytes_3(&23u8, did, substs, lsb0, f),
2745 ty_rptr(ref r, ref mt) =>
2746 to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f),
2748 ty_err => 25u8.iter_bytes(lsb0, f),
2750 ty_closure(ref ct) =>
2751 to_bytes::iter_bytes_2(&26u8, ct, lsb0, f),
2756 pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef {
2757 match cx.trait_refs.find(&id) {
2759 None => cx.sess.bug(
2760 fmt!("node_id_to_trait_ref: no trait ref for node `%s`",
2761 ast_map::node_id_to_str(cx.items, id,
2762 cx.sess.parse_sess.interner)))
2766 pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
2767 //io::println(fmt!("%?/%?", id, cx.node_types.len()));
2768 match cx.node_types.find(&(id as uint)) {
2770 None => cx.sess.bug(
2771 fmt!("node_id_to_type: no type for node `%s`",
2772 ast_map::node_id_to_str(cx.items, id,
2773 cx.sess.parse_sess.interner)))
2777 pub fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
2778 match cx.node_type_substs.find(&id) {
2780 Some(ts) => return /*bad*/ copy *ts
2784 fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
2785 cx.node_type_substs.contains_key(&id)
2788 pub fn ty_fn_sig(fty: t) -> FnSig {
2789 match get(fty).sty {
2790 ty_bare_fn(ref f) => copy f.sig,
2791 ty_closure(ref f) => copy f.sig,
2793 fail!(fmt!("ty_fn_sig() called on non-fn type: %?", s))
2798 // Type accessors for substructures of types
2799 pub fn ty_fn_args(fty: t) -> ~[arg] {
2800 match get(fty).sty {
2801 ty_bare_fn(ref f) => copy f.sig.inputs,
2802 ty_closure(ref f) => copy f.sig.inputs,
2804 fail!(fmt!("ty_fn_args() called on non-fn type: %?", s))
2809 pub fn ty_closure_sigil(fty: t) -> Sigil {
2810 match get(fty).sty {
2811 ty_closure(ref f) => f.sigil,
2813 fail!(fmt!("ty_closure_sigil() called on non-closure type: %?",
2819 pub fn ty_fn_purity(fty: t) -> ast::purity {
2820 match get(fty).sty {
2821 ty_bare_fn(ref f) => f.purity,
2822 ty_closure(ref f) => f.purity,
2824 fail!(fmt!("ty_fn_purity() called on non-fn type: %?", s))
2829 pub fn ty_fn_ret(fty: t) -> t {
2830 match get(fty).sty {
2831 ty_bare_fn(ref f) => f.sig.output,
2832 ty_closure(ref f) => f.sig.output,
2834 fail!(fmt!("ty_fn_ret() called on non-fn type: %?", s))
2839 pub fn is_fn_ty(fty: t) -> bool {
2840 match get(fty).sty {
2841 ty_bare_fn(_) => true,
2842 ty_closure(_) => true,
2847 pub fn ty_vstore(ty: t) -> vstore {
2849 ty_evec(_, vstore) => vstore,
2850 ty_estr(vstore) => vstore,
2851 ref s => fail!(fmt!("ty_vstore() called on invalid sty: %?", s))
2855 pub fn ty_region(tcx: ctxt,
2860 ty_evec(_, vstore_slice(r)) => r,
2861 ty_estr(vstore_slice(r)) => r,
2865 fmt!("ty_region() invoked on in appropriate ty: %?", s));
2870 pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
2873 * Returns a new function type based on `fn_type` but returning a value of
2874 * type `ret_type` instead. */
2876 match ty::get(fn_type).sty {
2877 ty::ty_closure(ref fty) => {
2878 ty::mk_closure(tcx, ClosureTy {
2879 sig: FnSig {output: ret_type, ..copy fty.sig},
2885 "replace_fn_ret() invoked with non-fn-type: %s",
2886 ty_to_str(tcx, fn_type)));
2891 // Returns a vec of all the input and output types of fty.
2892 pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
2893 vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
2896 // Type accessors for AST nodes
2897 pub fn block_ty(cx: ctxt, b: &ast::blk) -> t {
2898 return node_id_to_type(cx, b.node.id);
2902 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
2903 // doesn't provide type parameter substitutions.
2904 pub fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
2905 return node_id_to_type(cx, pat.id);
2909 // Returns the type of an expression as a monotype.
2911 // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
2912 // some cases, we insert `AutoAdjustment` annotations such as auto-deref or
2913 // auto-ref. The type returned by this function does not consider such
2914 // adjustments. See `expr_ty_adjusted()` instead.
2916 // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
2917 // ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
2918 // instead of "fn(t) -> T with T = int". If this isn't what you want, see
2919 // expr_ty_params_and_ty() below.
2920 pub fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
2921 return node_id_to_type(cx, expr.id);
2924 pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t {
2927 * Returns the type of `expr`, considering any `AutoAdjustment`
2928 * entry recorded for that expression.
2930 * It would almost certainly be better to store the adjusted ty in with
2931 * the `AutoAdjustment`, but I opted not to do this because it would
2932 * require serializing and deserializing the type and, although that's not
2933 * hard to do, I just hate that code so much I didn't want to touch it
2934 * unless it was to fix it properly, which seemed a distraction from the
2935 * task at hand! -nmatsakis
2938 let unadjusted_ty = expr_ty(cx, expr);
2939 adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find(&expr.id))
2942 pub fn adjust_ty(cx: ctxt,
2944 unadjusted_ty: ty::t,
2945 adjustment: Option<&@AutoAdjustment>) -> ty::t
2947 /*! See `expr_ty_adjusted` */
2949 return match adjustment {
2950 None => unadjusted_ty,
2952 Some(&@AutoAddEnv(r, s)) => {
2953 match ty::get(unadjusted_ty).sty {
2954 ty::ty_bare_fn(ref b) => {
2957 ty::ClosureTy {purity: b.purity,
2959 onceness: ast::Many,
2965 fmt!("add_env adjustment on non-bare-fn: %?", b));
2970 Some(&@AutoDerefRef(ref adj)) => {
2971 let mut adjusted_ty = unadjusted_ty;
2973 for uint::range(0, adj.autoderefs) |i| {
2974 match ty::deref(cx, adjusted_ty, true) {
2975 Some(mt) => { adjusted_ty = mt.ty; }
2979 fmt!("The %uth autoderef failed: %s",
2987 None => adjusted_ty,
2988 Some(ref autoref) => {
2989 match autoref.kind {
2991 mk_rptr(cx, autoref.region,
2992 mt {ty: adjusted_ty,
2993 mutbl: autoref.mutbl})
2997 borrow_vec(cx, span, autoref, adjusted_ty)
3000 AutoBorrowVecRef => {
3001 adjusted_ty = borrow_vec(cx, span, autoref,
3003 mk_rptr(cx, autoref.region,
3004 mt {ty: adjusted_ty, mutbl: ast::m_imm})
3008 borrow_fn(cx, span, autoref, adjusted_ty)
3016 fn borrow_vec(cx: ctxt, span: span,
3017 autoref: &AutoRef, ty: ty::t) -> ty::t {
3020 ty::mk_evec(cx, mt {ty: mt.ty, mutbl: autoref.mutbl},
3021 vstore_slice(autoref.region))
3025 ty::mk_estr(cx, vstore_slice(autoref.region))
3031 fmt!("borrow-vec associated with bad sty: %?",
3037 fn borrow_fn(cx: ctxt, span: span,
3038 autoref: &AutoRef, ty: ty::t) -> ty::t {
3040 ty_closure(ref fty) => {
3041 ty::mk_closure(cx, ClosureTy {
3042 sigil: BorrowedSigil,
3043 region: autoref.region,
3051 fmt!("borrow-fn associated with bad sty: %?",
3058 pub struct ParamsTy {
3063 pub fn expr_ty_params_and_ty(cx: ctxt,
3067 params: node_id_to_type_params(cx, expr.id),
3068 ty: node_id_to_type(cx, expr.id)
3072 pub fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
3073 return node_id_has_type_params(cx, expr.id);
3076 pub fn method_call_type_param_defs(
3078 method_map: typeck::method_map,
3079 id: ast::node_id) -> Option<@~[TypeParameterDef]>
3081 do method_map.find(&id).map |method| {
3082 match method.origin {
3083 typeck::method_static(did) => {
3084 // n.b.: When we encode impl methods, the bounds
3085 // that we encode include both the impl bounds
3086 // and then the method bounds themselves...
3087 ty::lookup_item_type(tcx, did).generics.type_param_defs
3089 typeck::method_param(typeck::method_param {
3091 method_num: n_mth, _}) |
3092 typeck::method_trait(trt_id, n_mth, _) |
3093 typeck::method_self(trt_id, n_mth) |
3094 typeck::method_super(trt_id, n_mth) => {
3095 // ...trait methods bounds, in contrast, include only the
3096 // method bounds, so we must preprend the tps from the
3097 // trait itself. This ought to be harmonized.
3098 let trait_type_param_defs =
3099 ty::lookup_trait_def(tcx, trt_id).generics.type_param_defs;
3101 copy *trait_type_param_defs,
3102 *ty::trait_method(tcx, trt_id, n_mth).generics.type_param_defs)
3108 pub fn resolve_expr(tcx: ctxt, expr: @ast::expr) -> ast::def {
3109 match tcx.def_map.find(&expr.id) {
3112 tcx.sess.span_bug(expr.span, fmt!(
3113 "No def-map entry for expr %?", expr.id));
3118 pub fn expr_is_lval(tcx: ctxt,
3119 method_map: typeck::method_map,
3120 e: @ast::expr) -> bool {
3121 match expr_kind(tcx, method_map, e) {
3123 RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
3127 /// We categorize expressions into three kinds. The distinction between
3128 /// lvalue/rvalue is fundamental to the language. The distinction between the
3129 /// two kinds of rvalues is an artifact of trans which reflects how we will
3130 /// generate code for that kind of expression. See trans/expr.rs for more
3139 pub fn expr_kind(tcx: ctxt,
3140 method_map: typeck::method_map,
3141 expr: @ast::expr) -> ExprKind {
3142 if method_map.contains_key(&expr.id) {
3143 // Overloaded operations are generally calls, and hence they are
3144 // generated via DPS. However, assign_op (e.g., `x += y`) is an
3145 // exception, as its result is always unit.
3146 return match expr.node {
3147 ast::expr_assign_op(*) => RvalueStmtExpr,
3153 ast::expr_path(*) => {
3154 match resolve_expr(tcx, expr) {
3155 ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3157 // Fn pointers are just scalar values.
3158 ast::def_fn(*) | ast::def_static_method(*) => RvalueDatumExpr,
3160 // Note: there is actually a good case to be made that
3161 // def_args, particularly those of immediate type, ought to
3162 // considered rvalues.
3164 ast::def_binding(*) |
3168 ast::def_self(*) => LvalueExpr,
3171 tcx.sess.span_bug(expr.span, fmt!(
3172 "Uncategorized def for expr %?: %?",
3178 ast::expr_unary(ast::deref, _) |
3179 ast::expr_field(*) |
3180 ast::expr_index(*) => {
3185 ast::expr_method_call(*) |
3186 ast::expr_struct(*) |
3189 ast::expr_match(*) |
3190 ast::expr_fn_block(*) |
3191 ast::expr_loop_body(*) |
3192 ast::expr_do_body(*) |
3193 ast::expr_block(*) |
3195 ast::expr_repeat(*) |
3196 ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) |
3197 ast::expr_vstore(_, ast::expr_vstore_slice) |
3198 ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3199 ast::expr_vec(*) => {
3203 ast::expr_cast(*) => {
3204 match tcx.node_types.find(&(expr.id as uint)) {
3206 if ty::type_is_immediate(t) {
3213 // Technically, it should not happen that the expr is not
3214 // present within the table. However, it DOES happen
3215 // during type check, because the final types from the
3216 // expressions are not yet recorded in the tcx. At that
3217 // time, though, we are only interested in knowing lvalue
3218 // vs rvalue. It would be better to base this decision on
3219 // the AST type in cast node---but (at the time of this
3220 // writing) it's not easy to distinguish casts to traits
3221 // from other casts based on the AST. This should be
3222 // easier in the future, when casts to traits would like
3223 // like @Foo, ~Foo, or &Foo.
3229 ast::expr_break(*) |
3230 ast::expr_again(*) |
3233 ast::expr_while(*) |
3235 ast::expr_assign(*) |
3237 ast::expr_inline_asm(*) |
3238 ast::expr_assign_op(*) => {
3242 ast::expr_lit(_) | // Note: lit_str is carved out above
3243 ast::expr_unary(*) |
3244 ast::expr_addr_of(*) |
3245 ast::expr_binary(*) |
3246 ast::expr_vstore(_, ast::expr_vstore_box) |
3247 ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3248 ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3252 ast::expr_paren(e) => expr_kind(tcx, method_map, e),
3254 ast::expr_mac(*) => {
3257 "macro expression remains after expansion");
3262 pub fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
3264 ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
3267 ast::stmt_mac(*) => fail!(~"unexpanded macro in trans")
3271 pub fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3273 for fields.each |f| { if f.ident == id { return Some(i); } i += 1u; }
3277 pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
3280 for fields.each |f| { if f.ident == id { return i; } i += 1u; }
3282 "No field named `%s` found in the list of fields `%?`",
3283 *tcx.sess.str_of(id),
3284 fields.map(|f| tcx.sess.str_of(f.ident))));
3287 pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option<uint> {
3288 vec::position(meths, |m| m.ident == id)
3291 /// Returns a vector containing the indices of all type parameters that appear
3292 /// in `ty`. The vector may contain duplicates. Probably should be converted
3293 /// to a bitset or some other representation.
3294 pub fn param_tys_in_type(ty: t) -> ~[param_ty] {
3296 do walk_ty(ty) |ty| {
3307 pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3308 // Returns a vec of all the type variables occurring in `ty`. It may
3309 // contain duplicates. (Integral type vars aren't counted.)
3310 fn vars_in_type(ty: t) -> ~[TyVid] {
3312 do walk_ty(ty) |ty| {
3314 ty_infer(TyVar(v)) => rslt.push(v),
3322 if !type_needs_infer(rt) { return; }
3325 if vec::contains(vars_in_type(rt), &vid) {
3326 // Maybe this should be span_err -- however, there's an
3327 // assertion later on that the type doesn't contain
3328 // variables, so in this case we have to be sure to die.
3330 (sp, ~"type inference failed because I \
3331 could not find a type\n that's both of the form "
3332 + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) +
3333 ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) +
3334 ~" - such a type would have to be infinitely large.");
3338 pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3340 ty_nil | ty_bot | ty_bool | ty_int(_) |
3341 ty_uint(_) | ty_float(_) | ty_estr(_) |
3342 ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
3343 ::util::ppaux::ty_to_str(cx, t)
3346 ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
3347 ty_box(_) => ~"@-ptr",
3348 ty_uniq(_) => ~"~-ptr",
3349 ty_evec(_, _) => ~"vector",
3350 ty_unboxed_vec(_) => ~"unboxed vector",
3351 ty_ptr(_) => ~"*-ptr",
3352 ty_rptr(_, _) => ~"&-ptr",
3353 ty_bare_fn(_) => ~"extern fn",
3354 ty_closure(_) => ~"fn",
3355 ty_trait(id, _, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3356 ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
3357 ty_tup(_) => ~"tuple",
3358 ty_infer(TyVar(_)) => ~"inferred type",
3359 ty_infer(IntVar(_)) => ~"integral variable",
3360 ty_infer(FloatVar(_)) => ~"floating-point variable",
3361 ty_param(_) => ~"type parameter",
3362 ty_self(_) => ~"self",
3363 ty_err => ~"type error"
3367 pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3370 * Explains the source of a type err in a short,
3371 * human readable way. This is meant to be placed in
3372 * parentheses after some larger message. You should
3373 * also invoke `note_and_explain_type_err()` afterwards
3374 * to present additional details, particularly when
3375 * it comes to lifetime-related errors. */
3377 fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3382 terr_trait => ~"trait"
3387 terr_mismatch => ~"types differ",
3388 terr_purity_mismatch(values) => {
3389 fmt!("expected %s fn but found %s fn",
3390 values.expected.to_str(), values.found.to_str())
3392 terr_abi_mismatch(values) => {
3393 fmt!("expected %s fn but found %s fn",
3394 values.expected.to_str(), values.found.to_str())
3396 terr_onceness_mismatch(values) => {
3397 fmt!("expected %s fn but found %s fn",
3398 values.expected.to_str(), values.found.to_str())
3400 terr_sigil_mismatch(values) => {
3401 fmt!("expected %s closure, found %s closure",
3402 values.expected.to_str(),
3403 values.found.to_str())
3405 terr_mutability => ~"values differ in mutability",
3406 terr_box_mutability => ~"boxed values differ in mutability",
3407 terr_vec_mutability => ~"vectors differ in mutability",
3408 terr_ptr_mutability => ~"pointers differ in mutability",
3409 terr_ref_mutability => ~"references differ in mutability",
3410 terr_ty_param_size(values) => {
3411 fmt!("expected a type with %? type params \
3412 but found one with %? type params",
3413 values.expected, values.found)
3415 terr_tuple_size(values) => {
3416 fmt!("expected a tuple with %? elements \
3417 but found one with %? elements",
3418 values.expected, values.found)
3420 terr_record_size(values) => {
3421 fmt!("expected a record with %? fields \
3422 but found one with %? fields",
3423 values.expected, values.found)
3425 terr_record_mutability => {
3426 ~"record elements differ in mutability"
3428 terr_record_fields(values) => {
3429 fmt!("expected a record with field `%s` but found one with field \
3431 *cx.sess.str_of(values.expected),
3432 *cx.sess.str_of(values.found))
3434 terr_arg_count => ~"incorrect number of function parameters",
3435 terr_regions_does_not_outlive(*) => {
3436 fmt!("lifetime mismatch")
3438 terr_regions_not_same(*) => {
3439 fmt!("lifetimes are not the same")
3441 terr_regions_no_overlap(*) => {
3442 fmt!("lifetimes do not intersect")
3444 terr_regions_insufficiently_polymorphic(br, _) => {
3445 fmt!("expected bound lifetime parameter %s, \
3446 but found concrete lifetime",
3447 bound_region_to_str(cx, br))
3449 terr_regions_overly_polymorphic(br, _) => {
3450 fmt!("expected concrete lifetime, \
3451 but found bound lifetime parameter %s",
3452 bound_region_to_str(cx, br))
3454 terr_vstores_differ(k, ref values) => {
3455 fmt!("%s storage differs: expected %s but found %s",
3456 terr_vstore_kind_to_str(k),
3457 vstore_to_str(cx, (*values).expected),
3458 vstore_to_str(cx, (*values).found))
3460 terr_trait_stores_differ(_, ref values) => {
3461 fmt!("trait storage differs: expected %s but found %s",
3462 trait_store_to_str(cx, (*values).expected),
3463 trait_store_to_str(cx, (*values).found))
3465 terr_in_field(err, fname) => {
3466 fmt!("in field `%s`, %s", *cx.sess.str_of(fname),
3467 type_err_to_str(cx, err))
3469 terr_sorts(values) => {
3470 fmt!("expected %s but found %s",
3471 ty_sort_str(cx, values.expected),
3472 ty_sort_str(cx, values.found))
3474 terr_traits(values) => {
3475 fmt!("expected trait %s but found trait %s",
3476 item_path_str(cx, values.expected),
3477 item_path_str(cx, values.found))
3479 terr_self_substs => {
3480 ~"inconsistent self substitution" // XXX this is more of a bug
3482 terr_integer_as_char => {
3483 fmt!("expected an integral type but found char")
3485 terr_int_mismatch(ref values) => {
3486 fmt!("expected %s but found %s",
3487 values.expected.to_str(),
3488 values.found.to_str())
3490 terr_float_mismatch(ref values) => {
3491 fmt!("expected %s but found %s",
3492 values.expected.to_str(),
3493 values.found.to_str())
3498 pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
3500 terr_regions_does_not_outlive(subregion, superregion) => {
3501 note_and_explain_region(cx, ~"", subregion, ~"...");
3502 note_and_explain_region(cx, ~"...does not necessarily outlive ",
3505 terr_regions_not_same(region1, region2) => {
3506 note_and_explain_region(cx, ~"", region1, ~"...");
3507 note_and_explain_region(cx, ~"...is not the same lifetime as ",
3510 terr_regions_no_overlap(region1, region2) => {
3511 note_and_explain_region(cx, ~"", region1, ~"...");
3512 note_and_explain_region(cx, ~"...does not overlap ",
3515 terr_regions_insufficiently_polymorphic(_, conc_region) => {
3516 note_and_explain_region(cx,
3517 ~"concrete lifetime that was found is ",
3520 terr_regions_overly_polymorphic(_, conc_region) => {
3521 note_and_explain_region(cx,
3522 ~"expected concrete lifetime is ",
3529 pub fn def_has_ty_params(def: ast::def) -> bool {
3531 ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
3537 pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
3539 match cx.items.find(&id.node) {
3540 Some(&ast_map::node_item(@ast::item {
3541 node: item_trait(_, _, ref ms),
3544 match ast_util::split_trait_methods(*ms) {
3545 (_, p) => p.map(|method| method.ident)
3547 _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3551 csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
3555 pub fn trait_supertraits(cx: ctxt,
3556 id: ast::def_id) -> @~[@TraitRef]
3559 match cx.supertraits.find(&id) {
3560 Some(&trait_refs) => { return trait_refs; }
3561 None => {} // Continue.
3564 // Not in the cache. It had better be in the metadata, which means it
3565 // shouldn't be local.
3566 assert!(!is_local(id));
3568 // Get the supertraits out of the metadata and create the
3569 // TraitRef for each.
3570 let result = @csearch::get_supertraits(cx, id);
3571 cx.supertraits.insert(id, result);
3575 pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef] {
3576 let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
3577 supertrait_refs.map(
3578 |supertrait_ref| @supertrait_ref.subst(cx, &trait_ref.substs))
3581 fn lookup_locally_or_in_crate_store<V:Copy>(
3583 def_id: ast::def_id,
3584 map: &mut HashMap<ast::def_id, V>,
3585 load_external: &fn() -> V) -> V
3589 * Helper for looking things up in the various maps
3590 * that are populated during typeck::collect (e.g.,
3591 * `cx.methods`, `cx.tcache`, etc). All of these share
3592 * the pattern that if the id is local, it should have
3593 * been loaded into the map by the `typeck::collect` phase.
3594 * If the def-id is external, then we have to go consult
3595 * the crate loading code (and cache the result for the future).
3598 match map.find(&def_id) {
3599 Some(&v) => { return v; }
3603 if def_id.crate == ast::local_crate {
3604 fail!(fmt!("No def'n found for %? in tcx.%s",
3607 let v = load_external();
3608 map.insert(def_id, v);
3612 pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @method {
3613 let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx];
3614 ty::method(cx, method_def_id)
3617 pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] {
3618 match cx.trait_methods_cache.find(&trait_did) {
3619 Some(&methods) => methods,
3621 let def_ids = ty::trait_method_def_ids(cx, trait_did);
3622 let methods = @def_ids.map(|d| ty::method(cx, *d));
3623 cx.trait_methods_cache.insert(trait_did, methods);
3629 pub fn method(cx: ctxt, id: ast::def_id) -> @method {
3630 lookup_locally_or_in_crate_store(
3631 "methods", id, cx.methods,
3632 || @csearch::get_method(cx, id))
3635 pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
3636 lookup_locally_or_in_crate_store(
3637 "methods", id, cx.trait_method_def_ids,
3638 || @csearch::get_trait_method_def_ids(cx.cstore, id))
3641 pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] {
3642 if id.crate == ast::local_crate {
3643 debug!("(impl_traits) searching for trait impl %?", id);
3644 match cx.items.find(&id.node) {
3645 Some(&ast_map::node_item(@ast::item {
3646 node: ast::item_impl(_, opt_trait, _, _),
3650 Some(t) => ~[ty::node_id_to_trait_ref(cx, t.ref_id)],
3657 csearch::get_impl_traits(cx, id)
3661 pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3663 ty_trait(id, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
3668 /// Returns the def ID of the constructor for the given tuple-like struct, or
3669 /// None if the struct is not tuple-like. Fails if the given def ID does not
3670 /// refer to a struct at all.
3671 fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option<ast::def_id> {
3672 if struct_did.crate != ast::local_crate {
3673 // XXX: Cross-crate functionality.
3674 cx.sess.unimpl(~"constructor ID of cross-crate tuple structs");
3677 match cx.items.find(&struct_did.node) {
3678 Some(&ast_map::node_item(item, _)) => {
3680 ast::item_struct(struct_def, _) => {
3681 struct_def.ctor_id.map(|ctor_id|
3682 ast_util::local_def(*ctor_id))
3684 _ => cx.sess.bug(~"called struct_ctor_id on non-struct")
3687 _ => cx.sess.bug(~"called struct_ctor_id on non-struct")
3692 pub struct VariantInfo_ {
3701 pub type VariantInfo = @VariantInfo_;
3703 pub fn substd_enum_variants(cx: ctxt,
3707 do vec::map(*enum_variants(cx, id)) |variant_info| {
3708 let substd_args = vec::map(variant_info.args,
3709 |aty| subst(cx, substs, *aty));
3711 let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3713 @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
3714 ../*bad*/copy **variant_info}
3718 pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
3719 ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner)
3728 fn is_not_present(&const self) -> bool {
3734 fn is_present(&const self) -> bool {
3735 !self.is_not_present()
3739 /* If struct_id names a struct with a dtor, return Some(the dtor's id).
3740 Otherwise return none. */
3741 pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
3742 match cx.destructor_for_type.find(&struct_id) {
3743 Some(&method_def_id) => TraitDtor(method_def_id),
3748 pub fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
3749 ty_dtor(cx, struct_id).is_present()
3752 pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
3753 if id.crate != ast::local_crate {
3754 csearch::get_item_path(cx, id)
3756 // FIXME (#5521): uncomment this code and don't have a catch-all at the
3757 // end of the match statement. Favor explicitly listing
3759 // let node = cx.items.get(&id.node);
3761 match *cx.items.get(&id.node) {
3762 ast_map::node_item(item, path) => {
3763 let item_elt = match item.node {
3764 item_mod(_) | item_foreign_mod(_) => {
3765 ast_map::path_mod(item.ident)
3768 ast_map::path_name(item.ident)
3771 vec::append_one(/*bad*/copy *path, item_elt)
3774 ast_map::node_foreign_item(nitem, _, _, path) => {
3775 vec::append_one(/*bad*/copy *path,
3776 ast_map::path_name(nitem.ident))
3779 ast_map::node_method(method, _, path) => {
3780 vec::append_one(/*bad*/copy *path,
3781 ast_map::path_name(method.ident))
3783 ast_map::node_trait_method(trait_method, _, path) => {
3784 let method = ast_util::trait_method_to_ty_method(&*trait_method);
3785 vec::append_one(/*bad*/copy *path,
3786 ast_map::path_name(method.ident))
3789 ast_map::node_variant(ref variant, _, path) => {
3790 vec::append_one(vec::from_slice(vec::init(*path)),
3791 ast_map::path_name((*variant).node.name))
3794 ast_map::node_struct_ctor(_, item, path) => {
3795 vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident))
3799 cx.sess.bug(fmt!("cannot find item_path for node %?", node));
3805 pub fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
3806 enum_variants(cx, id).len() == 1
3809 pub fn type_is_empty(cx: ctxt, t: t) -> bool {
3810 match ty::get(t).sty {
3811 ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
3816 pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3817 match cx.enum_var_cache.find(&id) {
3818 Some(&variants) => return variants,
3819 _ => { /* fallthrough */ }
3822 let result = if ast::local_crate != id.crate {
3823 @csearch::get_enum_variants(cx, id)
3826 Although both this code and check_enum_variants in typeck/check
3827 call eval_const_expr, it should never get called twice for the same
3828 expr, since check_enum_variants also updates the enum_var_cache
3830 match *cx.items.get(&id.node) {
3831 ast_map::node_item(@ast::item {
3832 node: ast::item_enum(ref enum_definition, _),
3835 let mut disr_val = -1;
3836 @vec::map(enum_definition.variants, |variant| {
3837 match variant.node.kind {
3838 ast::tuple_variant_kind(ref args) => {
3839 let ctor_ty = node_id_to_type(cx, variant.node.id);
3841 if args.len() > 0u {
3842 ty_fn_args(ctor_ty).map(|a| a.ty)
3847 match variant.node.disr_expr {
3849 disr_val = match const_eval::eval_const_expr(cx,
3851 const_eval::const_int(val) => val as int,
3852 _ => cx.sess.bug(~"tag_variants: bad disr expr")
3857 @VariantInfo_{args: arg_tys,
3859 name: variant.node.name,
3860 id: ast_util::local_def(variant.node.id),
3862 vis: variant.node.vis
3865 ast::struct_variant_kind(_) => {
3866 fail!(~"struct variant kinds unimpl in enum_variants")
3871 _ => cx.sess.bug(~"tag_variants: id not bound to an enum")
3874 cx.enum_var_cache.insert(id, result);
3879 // Returns information about the enum variant with the given ID:
3880 pub fn enum_variant_with_id(cx: ctxt,
3881 enum_id: ast::def_id,
3882 variant_id: ast::def_id)
3884 let variants = enum_variants(cx, enum_id);
3886 while i < variants.len() {
3887 let variant = variants[i];
3888 if variant.id == variant_id { return variant; }
3891 cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");
3895 // If the given item is in an external crate, looks up its type and adds it to
3896 // the type cache. Returns the type parameters and type.
3897 pub fn lookup_item_type(cx: ctxt,
3899 -> ty_param_bounds_and_ty {
3900 lookup_locally_or_in_crate_store(
3901 "tcache", did, cx.tcache,
3902 || csearch::get_type(cx, did))
3905 /// Given the did of a trait, returns its canonical trait ref.
3906 pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
3907 match cx.trait_defs.find(&did) {
3908 Some(&trait_def) => {
3909 // The item is in this crate. The caller should have added it to the
3910 // type cache already
3914 assert!(did.crate != ast::local_crate);
3915 let trait_def = @csearch::get_trait_def(cx, did);
3916 cx.trait_defs.insert(did, trait_def);
3922 // Determine whether an item is annotated with #[packed] or not
3923 pub fn lookup_packed(tcx: ctxt,
3924 did: def_id) -> bool {
3926 match tcx.items.find(&did.node) {
3928 &ast_map::node_item(@ast::item {
3931 }, _)) => attr::attrs_contains_name(*attrs, "packed"),
3932 _ => tcx.sess.bug(fmt!("lookup_packed: %? is not an item",
3936 let mut ret = false;
3937 do csearch::get_item_attrs(tcx.cstore, did) |meta_items| {
3938 ret = attr::contains_name(meta_items, "packed");
3944 // Look up a field ID, whether or not it's local
3945 // Takes a list of type substs in case the struct is generic
3946 pub fn lookup_field_type(tcx: ctxt,
3951 let t = if id.crate == ast::local_crate {
3952 node_id_to_type(tcx, id.node)
3955 match tcx.tcache.find(&id) {
3956 Some(tpt) => tpt.ty,
3958 let tpt = csearch::get_field_type(tcx, struct_id, id);
3959 tcx.tcache.insert(id, tpt);
3964 subst(tcx, substs, t)
3967 // Look up the list of field names and IDs for a given struct
3968 // Fails if the id is not bound to a struct.
3969 pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
3970 if did.crate == ast::local_crate {
3971 match cx.items.find(&did.node) {
3972 Some(&ast_map::node_item(i,_)) => {
3974 ast::item_struct(struct_def, _) => {
3975 struct_field_tys(struct_def.fields)
3977 _ => cx.sess.bug(~"struct ID bound to non-struct")
3980 Some(&ast_map::node_variant(ref variant, _, _)) => {
3981 match (*variant).node.kind {
3982 ast::struct_variant_kind(struct_def) => {
3983 struct_field_tys(struct_def.fields)
3986 cx.sess.bug(~"struct ID bound to enum variant that isn't \
3993 fmt!("struct ID not bound to an item: %s",
3994 ast_map::node_id_to_str(cx.items, did.node,
3995 cx.sess.parse_sess.interner)));
4000 return csearch::get_struct_fields(cx.sess.cstore, did);
4004 pub fn lookup_struct_field(cx: ctxt,
4005 parent: ast::def_id,
4006 field_id: ast::def_id)
4008 match vec::find(lookup_struct_fields(cx, parent),
4009 |f| f.id.node == field_id.node) {
4011 None => cx.sess.bug(~"struct ID not found in parent's fields")
4015 fn struct_field_tys(fields: &[@struct_field]) -> ~[field_ty] {
4016 do fields.map |field| {
4017 match field.node.kind {
4018 named_field(ident, mutability, visibility) => {
4021 id: ast_util::local_def(field.node.id),
4023 mutability: mutability,
4029 syntax::parse::token::special_idents::unnamed_field,
4030 id: ast_util::local_def(field.node.id),
4032 mutability: ast::struct_immutable,
4039 // Return a list of fields corresponding to the struct's items
4040 // (as if the struct was a record). trans uses this
4041 // Takes a list of substs with which to instantiate field types
4042 // Keep in mind that this function reports that all fields are
4043 // mutable, regardless of how they were declared. It's meant to
4044 // be used in trans.
4045 pub fn struct_mutable_fields(cx: ctxt,
4049 struct_item_fields(cx, did, substs, |_mt| m_mutbl)
4052 // Same as struct_mutable_fields, but doesn't change
4054 pub fn struct_fields(cx: ctxt,
4058 struct_item_fields(cx, did, substs, |mt| match mt {
4059 struct_mutable => m_mutbl,
4060 struct_immutable => m_imm })
4064 fn struct_item_fields(cx:ctxt,
4067 frob_mutability: &fn(struct_mutability) -> mutability)
4069 do lookup_struct_fields(cx, did).map |f| {
4070 // consider all instance vars mut, because the
4071 // constructor may mutate all vars
4075 ty: lookup_field_type(cx, did, f.id, substs),
4076 mutbl: frob_mutability(f.mutability)
4082 pub fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
4083 static tycat_other: int = 0;
4084 static tycat_bool: int = 1;
4085 static tycat_int: int = 2;
4086 static tycat_float: int = 3;
4087 static tycat_struct: int = 4;
4088 static tycat_bot: int = 5;
4090 static opcat_add: int = 0;
4091 static opcat_sub: int = 1;
4092 static opcat_mult: int = 2;
4093 static opcat_shift: int = 3;
4094 static opcat_rel: int = 4;
4095 static opcat_eq: int = 5;
4096 static opcat_bit: int = 6;
4097 static opcat_logic: int = 7;
4099 fn opcat(op: ast::binop) -> int {
4101 ast::add => opcat_add,
4102 ast::subtract => opcat_sub,
4103 ast::mul => opcat_mult,
4104 ast::div => opcat_mult,
4105 ast::rem => opcat_mult,
4106 ast::and => opcat_logic,
4107 ast::or => opcat_logic,
4108 ast::bitxor => opcat_bit,
4109 ast::bitand => opcat_bit,
4110 ast::bitor => opcat_bit,
4111 ast::shl => opcat_shift,
4112 ast::shr => opcat_shift,
4113 ast::eq => opcat_eq,
4114 ast::ne => opcat_eq,
4115 ast::lt => opcat_rel,
4116 ast::le => opcat_rel,
4117 ast::ge => opcat_rel,
4118 ast::gt => opcat_rel
4122 fn tycat(ty: t) -> int {
4124 ty_bool => tycat_bool,
4125 ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4126 ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
4127 ty_tup(_) | ty_enum(_, _) => tycat_struct,
4128 ty_bot => tycat_bot,
4133 static t: bool = true;
4134 static f: bool = false;
4140 /*other*/ ~[f, f, f, f, f, f, f, f],
4141 /*bool*/ ~[f, f, f, f, t, t, t, t],
4142 /*int*/ ~[t, t, t, t, t, t, t, f],
4143 /*float*/ ~[t, t, t, f, t, t, f, f],
4144 /*bot*/ ~[f, f, f, f, f, f, f, f],
4145 /*struct*/ ~[t, t, t, t, f, f, t, t]];
4147 return tbl[tycat(ty)][opcat(op)];
4150 pub fn ty_params_to_tys(tcx: ty::ctxt, generics: &ast::Generics) -> ~[t] {
4151 vec::from_fn(generics.ty_params.len(), |i| {
4152 let id = generics.ty_params.get(i).id;
4153 ty::mk_param(tcx, i, ast_util::local_def(id))
4157 /// Returns an equivalent type with all the typedefs and self regions removed.
4158 pub fn normalize_ty(cx: ctxt, t: t) -> t {
4159 fn normalize_mt(cx: ctxt, mt: mt) -> mt {
4160 mt { ty: normalize_ty(cx, mt.ty), mutbl: mt.mutbl }
4162 fn normalize_vstore(vstore: vstore) -> vstore {
4164 vstore_fixed(*) | vstore_uniq | vstore_box => vstore,
4165 vstore_slice(_) => vstore_slice(re_static)
4169 match cx.normalized_cache.find(&t) {
4170 Some(&t) => return t,
4174 let t = match get(t).sty {
4175 ty_evec(mt, vstore) =>
4176 // This type has a vstore. Get rid of it
4177 mk_evec(cx, normalize_mt(cx, mt), normalize_vstore(vstore)),
4180 // This type has a vstore. Get rid of it
4181 mk_estr(cx, normalize_vstore(vstore)),
4184 // This type has a region. Get rid of it
4185 mk_rptr(cx, re_static, normalize_mt(cx, mt)),
4187 ty_closure(ref closure_ty) => {
4188 mk_closure(cx, ClosureTy {
4189 region: ty::re_static,
4194 ty_enum(did, ref r) =>
4197 // Use re_static since trans doesn't care about regions
4200 self_r: Some(ty::re_static),
4202 tps: /*bad*/copy (*r).tps
4208 ty_struct(did, ref r) =>
4212 mk_struct(cx, did, substs {self_r: Some(ty::re_static),
4214 tps: /*bad*/copy (*r).tps}),
4223 let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) });
4224 let t_norm = mk_t(cx, sty);
4225 cx.normalized_cache.insert(t, t_norm);
4229 // Returns the repeat count for a repeating vector expression.
4230 pub fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr) -> uint {
4231 match const_eval::eval_const_expr_partial(tcx, count_expr) {
4232 Ok(ref const_val) => match *const_val {
4233 const_eval::const_int(count) => return count as uint,
4234 const_eval::const_uint(count) => return count as uint,
4235 const_eval::const_float(count) => {
4236 tcx.sess.span_err(count_expr.span,
4237 "expected signed or unsigned integer for \
4238 repeat count but found float");
4239 return count as uint;
4241 const_eval::const_str(_) => {
4242 tcx.sess.span_err(count_expr.span,
4243 "expected signed or unsigned integer for \
4244 repeat count but found string");
4247 const_eval::const_bool(_) => {
4248 tcx.sess.span_err(count_expr.span,
4249 "expected signed or unsigned integer for \
4250 repeat count but found boolean");
4255 tcx.sess.span_err(count_expr.span,
4256 "expected constant integer for repeat count \
4257 but found variable");
4263 // Determine what purity to check a nested function under
4264 pub fn determine_inherited_purity(parent: (ast::purity, ast::node_id),
4265 child: (ast::purity, ast::node_id),
4266 child_sigil: ast::Sigil)
4267 -> (ast::purity, ast::node_id) {
4268 // If the closure is a stack closure and hasn't had some non-standard
4269 // purity inferred for it, then check it under its parent's purity.
4270 // Otherwise, use its own
4272 ast::BorrowedSigil if child.first() == ast::impure_fn => parent,
4277 // Iterate over a type parameter's bounded traits and any supertraits
4278 // of those traits, ignoring kinds.
4279 // Here, the supertraits are the transitive closure of the supertrait
4280 // relation on the supertraits from each bounded trait's constraint
4282 pub fn each_bound_trait_and_supertraits(tcx: ctxt,
4283 bounds: param_bounds,
4284 f: &fn(&TraitRef) -> bool) {
4285 for bounds.each |bound| {
4286 let bound_trait_ref = match *bound {
4287 ty::bound_trait(bound_t) => bound_t,
4289 ty::bound_copy | ty::bound_owned |
4290 ty::bound_const | ty::bound_durable => {
4291 loop; // skip non-trait bounds
4295 let mut supertrait_set = HashMap::new();
4296 let mut trait_refs = ~[];
4299 // Seed the worklist with the trait from the bound
4300 supertrait_set.insert(bound_trait_ref.def_id, ());
4301 trait_refs.push(bound_trait_ref);
4303 // Add the given trait ty to the hash map
4304 while i < trait_refs.len() {
4305 debug!("each_bound_trait_and_supertraits(i=%?, trait_ref=%s)",
4306 i, trait_refs[i].repr(tcx));
4308 if !f(trait_refs[i]) {
4312 // Add supertraits to supertrait_set
4313 let supertrait_refs = trait_ref_supertraits(tcx, trait_refs[i]);
4314 for supertrait_refs.each |&supertrait_ref| {
4315 debug!("each_bound_trait_and_supertraits(supertrait_ref=%s)",
4316 supertrait_ref.repr(tcx));
4318 let d_id = supertrait_ref.def_id;
4319 if !supertrait_set.contains_key(&d_id) {
4320 // FIXME(#5527) Could have same trait multiple times
4321 supertrait_set.insert(d_id, ());
4322 trait_refs.push(supertrait_ref);
4331 pub fn count_traits_and_supertraits(tcx: ctxt,
4332 type_param_defs: &[TypeParameterDef]) -> uint {
4334 for type_param_defs.each |type_param_def| {
4335 for each_bound_trait_and_supertraits(tcx, type_param_def.bounds) |_| {
4342 // Given a trait and a type, returns the impl of that type
4343 pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
4344 match tcx.trait_impls.find(&trait_id) {
4345 Some(ty_to_impl) => match ty_to_impl.find(&self_ty) {
4346 Some(the_impl) => the_impl.did,
4347 None => // try autoderef!
4348 match deref(tcx, self_ty, false) {
4349 Some(some_ty) => get_impl_id(tcx, trait_id, some_ty.ty),
4350 None => tcx.sess.bug(~"get_impl_id: no impl of trait for \
4354 None => tcx.sess.bug(~"get_impl_id: trait isn't in trait_impls")
4358 pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
4359 let ty_visitor_name = special_idents::ty_visitor;
4360 assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name));
4361 let trait_ref = *tcx.intrinsic_traits.get(&ty_visitor_name);
4363 mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore, ast::m_imm))