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 // Converts s to its machine type equivalent
1257 pub fn mach_sty(cfg: @session::config, t: t) -> sty {
1259 ty_int(ast::ty_i) => ty_int(cfg.int_type),
1260 ty_uint(ast::ty_u) => ty_uint(cfg.uint_type),
1261 ty_float(ast::ty_f) => ty_float(cfg.float_type),
1262 ref s => (/*bad*/copy *s)
1266 pub fn walk_ty(ty: t, f: &fn(t)) {
1267 maybe_walk_ty(ty, |t| { f(t); true });
1270 pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
1275 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1276 ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
1277 ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
1279 ty_box(ref tm) | ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) |
1280 ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
1281 maybe_walk_ty(tm.ty, f);
1283 ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1284 ty_trait(_, ref substs, _, _) => {
1285 for (*substs).tps.each |subty| { maybe_walk_ty(*subty, f); }
1287 ty_tup(ref ts) => { for ts.each |tt| { maybe_walk_ty(*tt, f); } }
1288 ty_bare_fn(ref ft) => {
1289 for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
1290 maybe_walk_ty(ft.sig.output, f);
1292 ty_closure(ref ft) => {
1293 for ft.sig.inputs.each |a| { maybe_walk_ty(a.ty, f); }
1294 maybe_walk_ty(ft.sig.output, f);
1299 pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: &fn(t) -> t) -> t {
1300 mk_t(tcx, fold_sty(sty, foldop))
1303 pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
1304 let args = do sig.inputs.map |arg| {
1311 bound_lifetime_names: copy sig.bound_lifetime_names,
1313 output: fldop(sig.output)
1317 pub fn fold_bare_fn_ty(fty: &BareFnTy, fldop: &fn(t) -> t) -> BareFnTy {
1318 BareFnTy {sig: fold_sig(&fty.sig, fldop),
1323 fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
1324 fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs {
1325 substs {self_r: substs.self_r,
1326 self_ty: substs.self_ty.map(|t| fldop(*t)),
1327 tps: substs.tps.map(|t| fldop(*t))}
1332 ty_box(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1334 ty_uniq(ref tm) => {
1335 ty_uniq(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1338 ty_ptr(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1340 ty_unboxed_vec(ref tm) => {
1341 ty_unboxed_vec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1343 ty_evec(ref tm, vst) => {
1344 ty_evec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
1346 ty_enum(tid, ref substs) => {
1347 ty_enum(tid, fold_substs(substs, fldop))
1349 ty_trait(did, ref substs, st, mutbl) => {
1350 ty_trait(did, fold_substs(substs, fldop), st, mutbl)
1353 let new_ts = ts.map(|tt| fldop(*tt));
1356 ty_bare_fn(ref f) => {
1357 ty_bare_fn(fold_bare_fn_ty(f, fldop))
1359 ty_closure(ref f) => {
1360 let sig = fold_sig(&f.sig, fldop);
1361 ty_closure(ClosureTy {sig: sig, ..copy *f})
1363 ty_rptr(r, ref tm) => {
1364 ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1366 ty_struct(did, ref substs) => {
1367 ty_struct(did, fold_substs(substs, fldop))
1369 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1370 ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
1371 ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self(_) => {
1377 // Folds types from the bottom up.
1378 pub fn fold_ty(cx: ctxt, t0: t, fldop: &fn(t) -> t) -> t {
1379 let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), fldop));
1380 fldop(mk_t(cx, sty))
1383 pub fn walk_regions_and_ty(
1386 walkr: &fn(r: Region),
1387 walkt: &fn(t: t) -> bool) {
1390 fold_regions_and_ty(
1392 |r| { walkr(r); r },
1393 |t| { walk_regions_and_ty(cx, t, walkr, walkt); t },
1394 |t| { walk_regions_and_ty(cx, t, walkr, walkt); t });
1398 pub fn fold_regions_and_ty(
1401 fldr: &fn(r: Region) -> Region,
1402 fldfnt: &fn(t: t) -> t,
1403 fldt: &fn(t: t) -> t) -> t {
1407 fldr: &fn(r: Region) -> Region,
1408 fldt: &fn(t: t) -> t)
1411 self_r: substs.self_r.map(|r| fldr(*r)),
1412 self_ty: substs.self_ty.map(|t| fldt(*t)),
1413 tps: substs.tps.map(|t| fldt(*t))
1417 let tb = ty::get(ty);
1419 ty::ty_rptr(r, mt) => {
1421 let m_t = fldt(mt.ty);
1422 ty::mk_rptr(cx, m_r, mt {ty: m_t, mutbl: mt.mutbl})
1424 ty_estr(vstore_slice(r)) => {
1426 ty::mk_estr(cx, vstore_slice(m_r))
1428 ty_evec(mt, vstore_slice(r)) => {
1430 let m_t = fldt(mt.ty);
1431 ty::mk_evec(cx, mt {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
1433 ty_enum(def_id, ref substs) => {
1434 ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
1436 ty_struct(def_id, ref substs) => {
1437 ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
1439 ty_trait(def_id, ref substs, st, mutbl) => {
1440 ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl)
1442 ty_bare_fn(ref f) => {
1443 ty::mk_bare_fn(cx, BareFnTy {sig: fold_sig(&f.sig, fldfnt),
1446 ty_closure(ref f) => {
1447 ty::mk_closure(cx, ClosureTy {region: fldr(f.region),
1448 sig: fold_sig(&f.sig, fldfnt),
1452 fold_sty_to_ty(cx, sty, |t| fldt(t))
1457 // n.b. this function is intended to eventually replace fold_region() below,
1458 // that is why its name is so similar.
1459 pub fn fold_regions(
1462 fldr: &fn(r: Region, in_fn: bool) -> Region) -> t {
1463 fn do_fold(cx: ctxt, ty: t, in_fn: bool,
1464 fldr: &fn(Region, bool) -> Region) -> t {
1465 debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn);
1466 if !type_has_regions(ty) { return ty; }
1467 fold_regions_and_ty(
1470 |t| do_fold(cx, t, true, fldr),
1471 |t| do_fold(cx, t, in_fn, fldr))
1473 do_fold(cx, ty, false, fldr)
1476 // Substitute *only* type parameters. Used in trans where regions are erased.
1477 pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
1478 if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
1479 let tb = ty::get(typ);
1480 if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1482 ty_param(p) => tps[p.idx],
1485 None => cx.sess.bug(~"ty_self unexpected here"),
1487 subst_tps(cx, tps, self_ty_opt, self_ty)
1492 fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, self_ty_opt, t))
1497 pub fn substs_is_noop(substs: &substs) -> bool {
1498 substs.tps.len() == 0u &&
1499 substs.self_r.is_none() &&
1500 substs.self_ty.is_none()
1503 pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
1507 pub fn param_bound_to_str(cx: ctxt, pb: ¶m_bound) -> ~str {
1511 pub fn param_bounds_to_str(cx: ctxt, pbs: param_bounds) -> ~str {
1515 pub fn subst(cx: ctxt,
1519 typ.subst(cx, substs)
1524 pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
1526 pub fn type_is_bot(ty: t) -> bool {
1527 (get(ty).flags & (has_ty_bot as uint)) != 0
1530 pub fn type_is_error(ty: t) -> bool {
1531 (get(ty).flags & (has_ty_err as uint)) != 0
1534 pub fn type_needs_subst(ty: t) -> bool {
1535 tbox_has_flag(get(ty), needs_subst)
1538 pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
1539 tref.substs.self_ty.any(|&t| type_is_error(t)) ||
1540 tref.substs.tps.any(|&t| type_is_error(t))
1543 pub fn type_is_ty_var(ty: t) -> bool {
1545 ty_infer(TyVar(_)) => true,
1550 pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
1552 pub fn type_is_structural(ty: t) -> bool {
1554 ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_closure(_) | ty_trait(*) |
1555 ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
1556 ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
1562 pub fn type_is_sequence(ty: t) -> bool {
1564 ty_estr(_) | ty_evec(_, _) => true,
1569 pub fn type_is_str(ty: t) -> bool {
1576 pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
1578 ty_estr(_) => return mk_mach_uint(ast::ty_u8),
1579 ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
1581 ~"sequence_element_type called on non-sequence value"),
1585 pub fn get_element_type(ty: t, i: uint) -> t {
1587 ty_tup(ref ts) => return ts[i],
1588 _ => fail!(~"get_element_type called on invalid type")
1592 pub fn type_is_box(ty: t) -> bool {
1594 ty_box(_) => return true,
1599 pub fn type_is_boxed(ty: t) -> bool {
1601 ty_box(_) | ty_opaque_box |
1602 ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
1607 pub fn type_is_region_ptr(ty: t) -> bool {
1609 ty_rptr(_, _) => true,
1614 pub fn type_is_slice(ty: t) -> bool {
1616 ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true,
1621 pub fn type_is_unique_box(ty: t) -> bool {
1623 ty_uniq(_) => return true,
1628 pub fn type_is_unsafe_ptr(ty: t) -> bool {
1630 ty_ptr(_) => return true,
1635 pub fn type_is_vec(ty: t) -> bool {
1636 return match get(ty).sty {
1637 ty_evec(_, _) | ty_unboxed_vec(_) => true,
1643 pub fn type_is_unique(ty: t) -> bool {
1646 ty_evec(_, vstore_uniq) |
1647 ty_estr(vstore_uniq) |
1648 ty_opaque_closure_ptr(ast::OwnedSigil) => true,
1654 A scalar type is one that denotes an atomic datum, with no sub-components.
1655 (A ty_ptr is scalar because it represents a non-managed pointer, so its
1656 contents are abstract to rustc.)
1658 pub fn type_is_scalar(ty: t) -> bool {
1660 ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1661 ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
1662 ty_bare_fn(*) | ty_ptr(_) => true,
1667 pub fn type_is_immediate(ty: t) -> bool {
1668 return type_is_scalar(ty) || type_is_boxed(ty) ||
1669 type_is_unique(ty) || type_is_region_ptr(ty);
1672 pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1673 type_contents(cx, ty).needs_drop(cx)
1676 // Some things don't need cleanups during unwinding because the
1677 // task can free them all at once later. Currently only things
1678 // that only contain scalars and shared boxes can avoid unwind
1680 pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
1681 match cx.needs_unwind_cleanup_cache.find(&ty) {
1682 Some(&result) => return result,
1686 let mut tycache = HashSet::new();
1687 let needs_unwind_cleanup =
1688 type_needs_unwind_cleanup_(cx, ty, &mut tycache, false);
1689 cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup);
1690 return needs_unwind_cleanup;
1693 fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
1694 tycache: &mut HashSet<t>,
1695 encountered_box: bool) -> bool {
1697 // Prevent infinite recursion
1698 if !tycache.insert(ty) {
1702 let mut encountered_box = encountered_box;
1703 let mut needs_unwind_cleanup = false;
1704 do maybe_walk_ty(ty) |ty| {
1705 let old_encountered_box = encountered_box;
1706 let result = match get(ty).sty {
1707 ty_box(_) | ty_opaque_box => {
1708 encountered_box = true;
1711 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1712 ty_tup(_) | ty_ptr(_) => {
1715 ty_enum(did, ref substs) => {
1716 for vec::each(*enum_variants(cx, did)) |v| {
1717 for v.args.each |aty| {
1718 let t = subst(cx, substs, *aty);
1719 needs_unwind_cleanup |=
1720 type_needs_unwind_cleanup_(cx, t, tycache,
1724 !needs_unwind_cleanup
1727 ty_estr(vstore_uniq) |
1728 ty_estr(vstore_box) |
1729 ty_evec(_, vstore_uniq) |
1730 ty_evec(_, vstore_box)
1732 // Once we're inside a box, the annihilator will find
1733 // it and destroy it.
1734 if !encountered_box {
1735 needs_unwind_cleanup = true;
1742 needs_unwind_cleanup = true;
1747 encountered_box = old_encountered_box;
1751 return needs_unwind_cleanup;
1755 * Type contents is how the type checker reasons about kinds.
1756 * They track what kinds of things are found within a type. You can
1757 * think of them as kind of an "anti-kind". They track the kinds of values
1758 * and thinks that are contained in types. Having a larger contents for
1759 * a type tends to rule that type *out* from various kinds. For example,
1760 * a type that contains a borrowed pointer is not sendable.
1762 * The reason we compute type contents and not kinds is that it is
1763 * easier for me (nmatsakis) to think about what is contained within
1764 * a type than to think about what is *not* contained within a type.
1766 pub struct TypeContents {
1770 pub impl TypeContents {
1771 fn intersects(&self, tc: TypeContents) -> bool {
1772 (self.bits & tc.bits) != 0
1775 fn is_copy(&self, cx: ctxt) -> bool {
1776 !self.intersects(TypeContents::noncopyable(cx))
1779 fn noncopyable(_cx: ctxt) -> TypeContents {
1780 TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_OWNED_CLOSURE +
1784 fn is_durable(&self, cx: ctxt) -> bool {
1785 !self.intersects(TypeContents::nondurable(cx))
1788 fn nondurable(_cx: ctxt) -> TypeContents {
1792 fn is_owned(&self, cx: ctxt) -> bool {
1793 !self.intersects(TypeContents::nonowned(cx))
1796 fn nonowned(_cx: ctxt) -> TypeContents {
1797 TC_MANAGED + TC_BORROWED_POINTER
1800 fn contains_managed(&self) -> bool {
1801 self.intersects(TC_MANAGED)
1804 fn is_const(&self, cx: ctxt) -> bool {
1805 !self.intersects(TypeContents::nonconst(cx))
1808 fn nonconst(_cx: ctxt) -> TypeContents {
1812 fn moves_by_default(&self, cx: ctxt) -> bool {
1813 self.intersects(TypeContents::nonimplicitly_copyable(cx))
1816 fn nonimplicitly_copyable(cx: ctxt) -> TypeContents {
1817 let base = TypeContents::noncopyable(cx) + TC_OWNED_POINTER;
1818 if cx.vecs_implicitly_copyable {base} else {base + TC_OWNED_VEC}
1821 fn is_safe_for_default_mode(&self, cx: ctxt) -> bool {
1822 !self.intersects(TypeContents::nondefault_mode(cx))
1825 fn nondefault_mode(cx: ctxt) -> TypeContents {
1826 let tc = TypeContents::nonimplicitly_copyable(cx);
1827 tc + TC_BIG + TC_OWNED_VEC // disregard cx.vecs_implicitly_copyable
1830 fn needs_drop(&self, cx: ctxt) -> bool {
1831 let tc = TC_MANAGED + TC_DTOR + TypeContents::owned(cx);
1835 fn owned(_cx: ctxt) -> TypeContents {
1836 //! Any kind of owned contents.
1837 TC_OWNED_CLOSURE + TC_OWNED_POINTER + TC_OWNED_VEC
1841 impl ops::Add<TypeContents,TypeContents> for TypeContents {
1842 fn add(&self, other: &TypeContents) -> TypeContents {
1843 TypeContents {bits: self.bits | other.bits}
1847 impl ops::Sub<TypeContents,TypeContents> for TypeContents {
1848 fn sub(&self, other: &TypeContents) -> TypeContents {
1849 TypeContents {bits: self.bits & !other.bits}
1853 impl ToStr for TypeContents {
1854 fn to_str(&self) -> ~str {
1855 fmt!("TypeContents(%s)", u32::to_str_radix(self.bits, 2))
1859 /// Constant for a type containing nothing of interest.
1860 static TC_NONE: TypeContents = TypeContents{bits:0b0000_00000000};
1862 /// Contains a borrowed value with a lifetime other than static
1863 static TC_BORROWED_POINTER: TypeContents = TypeContents{bits:0b0000_00000001};
1865 /// Contains an owned pointer (~T) but not slice of some kind
1866 static TC_OWNED_POINTER: TypeContents = TypeContents{bits:0b000000000010};
1868 /// Contains an owned vector ~[] or owned string ~str
1869 static TC_OWNED_VEC: TypeContents = TypeContents{bits:0b000000000100};
1871 /// Contains a ~fn() or a ~Trait, which is non-copyable.
1872 static TC_OWNED_CLOSURE: TypeContents = TypeContents{bits:0b000000001000};
1874 /// Type with a destructor
1875 static TC_DTOR: TypeContents = TypeContents{bits:0b000000010000};
1877 /// Contains a managed value
1878 static TC_MANAGED: TypeContents = TypeContents{bits:0b000000100000};
1880 /// &mut with any region
1881 static TC_BORROWED_MUT: TypeContents = TypeContents{bits:0b000001000000};
1883 /// Mutable content, whether owned or by ref
1884 static TC_MUTABLE: TypeContents = TypeContents{bits:0b000010000000};
1886 /// Mutable content, whether owned or by ref
1887 static TC_ONCE_CLOSURE: TypeContents = TypeContents{bits:0b000100000000};
1889 /// Something we estimate to be "big"
1890 static TC_BIG: TypeContents = TypeContents{bits:0b001000000000};
1892 /// An enum with no variants.
1893 static TC_EMPTY_ENUM: TypeContents = TypeContents{bits:0b010000000000};
1895 /// All possible contents.
1896 static TC_ALL: TypeContents = TypeContents{bits:0b011111111111};
1898 pub fn type_is_copyable(cx: ctxt, t: ty::t) -> bool {
1899 type_contents(cx, t).is_copy(cx)
1902 pub fn type_is_durable(cx: ctxt, t: ty::t) -> bool {
1903 type_contents(cx, t).is_durable(cx)
1906 pub fn type_is_owned(cx: ctxt, t: ty::t) -> bool {
1907 type_contents(cx, t).is_owned(cx)
1910 pub fn type_is_const(cx: ctxt, t: ty::t) -> bool {
1911 type_contents(cx, t).is_const(cx)
1914 pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
1915 let ty_id = type_id(ty);
1916 match cx.tc_cache.find(&ty_id) {
1917 Some(tc) => { return *tc; }
1921 let mut cache = HashMap::new();
1922 let result = tc_ty(cx, ty, &mut cache);
1923 cx.tc_cache.insert(ty_id, result);
1928 cache: &mut HashMap<uint, TypeContents>) -> TypeContents
1930 // Subtle: Note that we are *not* using cx.tc_cache here but rather a
1931 // private cache for this walk. This is needed in the case of cyclic
1934 // struct List { next: ~Option<List>, ... }
1936 // When computing the type contents of such a type, we wind up deeply
1937 // recursing as we go. So when we encounter the recursive reference
1938 // to List, we temporarily use TC_NONE as its contents. Later we'll
1939 // patch up the cache with the correct value, once we've computed it
1940 // (this is basically a co-inductive process, if that helps). So in
1941 // the end we'll compute TC_OWNED_POINTER, in this case.
1943 // The problem is, as we are doing the computation, we will also
1944 // compute an *intermediate* contents for, e.g., Option<List> of
1945 // TC_NONE. This is ok during the computation of List itself, but if
1946 // we stored this intermediate value into cx.tc_cache, then later
1947 // requests for the contents of Option<List> would also yield TC_NONE
1948 // which is incorrect. This value was computed based on the crutch
1949 // value for the type contents of list. The correct value is
1950 // TC_OWNED_POINTER. This manifested as issue #4821.
1951 let ty_id = type_id(ty);
1952 match cache.find(&ty_id) {
1953 Some(tc) => { return *tc; }
1956 match cx.tc_cache.find(&ty_id) { // Must check both caches!
1957 Some(tc) => { return *tc; }
1960 cache.insert(ty_id, TC_NONE);
1962 let _i = indenter();
1964 let mut result = match get(ty).sty {
1965 // Scalar and unique types are sendable, constant, and owned
1966 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1967 ty_bare_fn(_) | ty_ptr(_) => {
1971 ty_estr(vstore_uniq) => {
1975 ty_closure(ref c) => {
1980 TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
1983 ty_trait(_, _, UniqTraitStore, _) => {
1987 ty_trait(_, _, BoxTraitStore, mutbl) => {
1989 ast::m_mutbl => TC_MANAGED + TC_MUTABLE,
1994 ty_trait(_, _, RegionTraitStore(r), mutbl) => {
1995 borrowed_contents(r, mutbl)
1999 borrowed_contents(r, mt.mutbl) +
2000 nonowned(tc_mt(cx, mt, cache))
2004 TC_OWNED_POINTER + tc_mt(cx, mt, cache)
2007 ty_evec(mt, vstore_uniq) => {
2008 TC_OWNED_VEC + tc_mt(cx, mt, cache)
2011 ty_evec(mt, vstore_box) => {
2012 TC_MANAGED + nonowned(tc_mt(cx, mt, cache))
2015 ty_evec(mt, vstore_slice(r)) => {
2016 borrowed_contents(r, mt.mutbl) +
2017 nonowned(tc_mt(cx, mt, cache))
2020 ty_evec(mt, vstore_fixed(_)) => {
2021 tc_mt(cx, mt, cache)
2024 ty_estr(vstore_box) => {
2028 ty_estr(vstore_slice(r)) => {
2029 borrowed_contents(r, m_imm)
2032 ty_estr(vstore_fixed(_)) => {
2036 ty_struct(did, ref substs) => {
2037 let flds = struct_fields(cx, did, substs);
2038 let flds_tc = flds.foldl(
2040 |tc, f| tc + tc_mt(cx, f.mt, cache));
2041 if ty::has_dtor(cx, did) {
2048 ty_tup(ref tys) => {
2049 tys.foldl(TC_NONE, |tc, ty| *tc + tc_ty(cx, *ty, cache))
2052 ty_enum(did, ref substs) => {
2053 let variants = substd_enum_variants(cx, did, substs);
2054 if variants.is_empty() {
2055 // we somewhat arbitrary declare that empty enums
2059 variants.foldl(TC_NONE, |tc, variant| {
2062 |tc, arg_ty| *tc + tc_ty(cx, *arg_ty, cache))
2068 // We only ever ask for the kind of types that are defined in
2069 // the current crate; therefore, the only type parameters that
2070 // could be in scope are those defined in the current crate.
2071 // If this assertion failures, it is likely because of a
2072 // failure in the cross-crate inlining code to translate a
2074 assert!(p.def_id.crate == ast::local_crate);
2076 type_param_def_to_contents(
2077 cx, cx.ty_param_defs.get(&p.def_id.node))
2081 // Currently, self is not bounded, so we must assume the
2082 // worst. But in the future we should examine the super
2085 // FIXME(#4678)---self should just be a ty param
2090 // This occurs during coherence, but shouldn't occur at other
2095 ty_opaque_box => TC_MANAGED,
2096 ty_unboxed_vec(mt) => tc_mt(cx, mt, cache),
2097 ty_opaque_closure_ptr(sigil) => {
2099 ast::BorrowedSigil => TC_BORROWED_POINTER,
2100 ast::ManagedSigil => TC_MANAGED,
2101 ast::OwnedSigil => TC_OWNED_CLOSURE
2108 cx.sess.bug(~"Asked to compute contents of fictitious type");
2112 if type_size(cx, ty) > 4 {
2113 result = result + TC_BIG;
2116 cache.insert(ty_id, result);
2122 cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2124 let mc = if mt.mutbl == m_mutbl {TC_MUTABLE} else {TC_NONE};
2125 mc + tc_ty(cx, mt.ty, cache)
2128 fn borrowed_contents(region: ty::Region,
2129 mutbl: ast::mutability) -> TypeContents
2131 let mc = if mutbl == m_mutbl {
2132 TC_MUTABLE + TC_BORROWED_MUT
2136 let rc = if region != ty::re_static {
2144 fn nonowned(pointee: TypeContents) -> TypeContents {
2147 * Given a non-owning pointer to some type `T` with
2148 * contents `pointee` (like `@T` or
2149 * `&T`), returns the relevant bits that
2150 * apply to the owner of the pointer.
2153 let mask = TC_MUTABLE.bits | TC_BORROWED_POINTER.bits;
2154 TypeContents {bits: pointee.bits & mask}
2157 fn closure_contents(cty: &ClosureTy) -> TypeContents {
2158 let st = match cty.sigil {
2159 ast::BorrowedSigil => TC_BORROWED_POINTER,
2160 ast::ManagedSigil => TC_MANAGED,
2161 ast::OwnedSigil => TC_OWNED_CLOSURE
2163 let rt = borrowed_contents(cty.region, m_imm);
2164 let ot = match cty.onceness {
2165 ast::Once => TC_ONCE_CLOSURE,
2166 ast::Many => TC_NONE
2171 fn type_param_def_to_contents(cx: ctxt,
2172 type_param_def: &TypeParameterDef) -> TypeContents
2174 debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx));
2175 let _i = indenter();
2177 let r = type_param_def.bounds.foldl(TC_ALL, |tc, bound| {
2178 debug!("tc = %s, bound = %?", tc.to_str(), bound);
2180 bound_copy => tc - TypeContents::nonimplicitly_copyable(cx),
2181 bound_durable => tc - TypeContents::nondurable(cx),
2182 bound_owned => tc - TypeContents::nonowned(cx),
2183 bound_const => tc - TypeContents::nonconst(cx),
2184 bound_trait(_) => *tc
2188 debug!("result = %s", r.to_str());
2192 /// gives a rough estimate of how much space it takes to represent
2193 /// an instance of `ty`. Used for the mode transition.
2194 fn type_size(cx: ctxt, ty: t) -> uint {
2196 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
2197 ty_ptr(_) | ty_box(_) | ty_uniq(_) | ty_estr(vstore_uniq) |
2198 ty_trait(*) | ty_rptr(*) | ty_evec(_, vstore_uniq) |
2199 ty_evec(_, vstore_box) | ty_estr(vstore_box) => {
2203 ty_evec(_, vstore_slice(_)) |
2204 ty_estr(vstore_slice(_)) |
2210 ty_evec(t, vstore_fixed(n)) => {
2211 type_size(cx, t.ty) * n
2214 ty_estr(vstore_fixed(n)) => {
2218 ty_struct(did, ref substs) => {
2219 let flds = struct_fields(cx, did, substs);
2220 flds.foldl(0, |s, f| *s + type_size(cx, f.mt.ty))
2223 ty_tup(ref tys) => {
2224 tys.foldl(0, |s, t| *s + type_size(cx, *t))
2227 ty_enum(did, ref substs) => {
2228 let variants = substd_enum_variants(cx, did, substs);
2229 variants.foldl( // find max size of any variant
2233 // find size of this variant:
2234 v.args.foldl(0, |s, a| *s + type_size(cx, *a))))
2237 ty_param(_) | ty_self(_) => {
2242 cx.sess.bug(~"Asked to compute kind of a type variable");
2245 ty_opaque_closure_ptr(_) => 1,
2247 ty_unboxed_vec(_) => 10,
2249 cx.sess.bug(~"Asked to compute kind of fictitious type");
2255 pub fn type_moves_by_default(cx: ctxt, ty: t) -> bool {
2256 type_contents(cx, ty).moves_by_default(cx)
2259 // True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2260 pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
2261 fn type_requires(cx: ctxt, seen: &mut ~[def_id],
2262 r_ty: t, ty: t) -> bool {
2263 debug!("type_requires(%s, %s)?",
2264 ::util::ppaux::ty_to_str(cx, r_ty),
2265 ::util::ppaux::ty_to_str(cx, ty));
2268 get(r_ty).sty == get(ty).sty ||
2269 subtypes_require(cx, seen, r_ty, ty)
2272 debug!("type_requires(%s, %s)? %b",
2273 ::util::ppaux::ty_to_str(cx, r_ty),
2274 ::util::ppaux::ty_to_str(cx, ty),
2279 fn subtypes_require(cx: ctxt, seen: &mut ~[def_id],
2280 r_ty: t, ty: t) -> bool {
2281 debug!("subtypes_require(%s, %s)?",
2282 ::util::ppaux::ty_to_str(cx, r_ty),
2283 ::util::ppaux::ty_to_str(cx, ty));
2285 let r = match get(ty).sty {
2301 ty_opaque_closure_ptr(_) |
2303 ty_unboxed_vec(_) => {
2308 ty_rptr(_, ref mt) => {
2309 return type_requires(cx, seen, r_ty, mt.ty);
2313 false // unsafe ptrs can always be NULL
2316 ty_trait(_, _, _, _) => {
2320 ty_struct(ref did, _) if vec::contains(*seen, did) => {
2324 ty_struct(did, ref substs) => {
2326 let r = vec::any(struct_fields(cx, did, substs),
2327 |f| type_requires(cx, seen, r_ty, f.mt.ty));
2333 ts.any(|t| type_requires(cx, seen, r_ty, *t))
2336 ty_enum(ref did, _) if vec::contains(*seen, did) => {
2340 ty_enum(did, ref substs) => {
2342 let vs = enum_variants(cx, did);
2343 let r = vec::len(*vs) > 0u && vec::all(*vs, |variant| {
2344 vec::any(variant.args, |aty| {
2345 let sty = subst(cx, substs, *aty);
2346 type_requires(cx, seen, r_ty, sty)
2354 debug!("subtypes_require(%s, %s)? %b",
2355 ::util::ppaux::ty_to_str(cx, r_ty),
2356 ::util::ppaux::ty_to_str(cx, ty),
2362 let seen = @mut ~[];
2363 !subtypes_require(cx, seen, r_ty, r_ty)
2366 pub fn type_structurally_contains(cx: ctxt,
2368 test: &fn(x: &sty) -> bool)
2370 let sty = &get(ty).sty;
2371 debug!("type_structurally_contains: %s",
2372 ::util::ppaux::ty_to_str(cx, ty));
2373 if test(sty) { return true; }
2375 ty_enum(did, ref substs) => {
2376 for vec::each(*enum_variants(cx, did)) |variant| {
2377 for variant.args.each |aty| {
2378 let sty = subst(cx, substs, *aty);
2379 if type_structurally_contains(cx, sty, test) { return true; }
2384 ty_struct(did, ref substs) => {
2385 for lookup_struct_fields(cx, did).each |field| {
2386 let ft = lookup_field_type(cx, did, field.id, substs);
2387 if type_structurally_contains(cx, ft, test) { return true; }
2394 if type_structurally_contains(cx, *tt, test) { return true; }
2398 ty_evec(ref mt, vstore_fixed(_)) => {
2399 return type_structurally_contains(cx, mt.ty, test);
2405 pub fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
2406 return type_structurally_contains(cx, ty, |sty| {
2409 ty_evec(_, vstore_uniq) |
2410 ty_estr(vstore_uniq) => true,
2416 pub fn type_is_integral(ty: t) -> bool {
2418 ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
2423 pub fn type_is_char(ty: t) -> bool {
2425 ty_int(ty_char) => true,
2430 pub fn type_is_fp(ty: t) -> bool {
2432 ty_infer(FloatVar(_)) | ty_float(_) => true,
2437 pub fn type_is_numeric(ty: t) -> bool {
2438 return type_is_integral(ty) || type_is_fp(ty);
2441 pub fn type_is_signed(ty: t) -> bool {
2448 // Whether a type is Plain Old Data -- meaning it does not contain pointers
2449 // that the cycle collector might care about.
2450 pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
2451 let mut result = true;
2454 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
2455 ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
2457 ty_box(_) | ty_uniq(_) | ty_closure(_) |
2458 ty_estr(vstore_uniq) | ty_estr(vstore_box) |
2459 ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
2460 ty_trait(_, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
2462 ty_enum(did, ref substs) => {
2463 let variants = enum_variants(cx, did);
2464 for vec::each(*variants) |variant| {
2465 let tup_ty = mk_tup(cx, /*bad*/copy variant.args);
2467 // Perform any type parameter substitutions.
2468 let tup_ty = subst(cx, substs, tup_ty);
2469 if !type_is_pod(cx, tup_ty) { result = false; }
2472 ty_tup(ref elts) => {
2473 for elts.each |elt| { if !type_is_pod(cx, *elt) { result = false; } }
2475 ty_estr(vstore_fixed(_)) => result = true,
2476 ty_evec(ref mt, vstore_fixed(_)) | ty_unboxed_vec(ref mt) => {
2477 result = type_is_pod(cx, mt.ty);
2479 ty_param(_) => result = false,
2480 ty_opaque_closure_ptr(_) => result = true,
2481 ty_struct(did, ref substs) => {
2482 result = vec::any(lookup_struct_fields(cx, did), |f| {
2483 let fty = ty::lookup_item_type(cx, f.id);
2484 let sty = subst(cx, substs, fty.ty);
2485 type_is_pod(cx, sty)
2489 ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2493 ty_infer(*) | ty_self(*) | ty_err => {
2494 cx.sess.bug(~"non concrete type in type_is_pod");
2501 pub fn type_is_enum(ty: t) -> bool {
2503 ty_enum(_, _) => return true,
2508 // Whether a type is enum like, that is a enum type with only nullary
2510 pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2512 ty_enum(did, _) => {
2513 let variants = enum_variants(cx, did);
2514 let some_n_ary = vec::any(*variants, |v| vec::len(v.args) > 0u);
2521 pub fn type_param(ty: t) -> Option<uint> {
2523 ty_param(p) => return Some(p.idx),
2524 _ => {/* fall through */ }
2529 // Returns the type and mutability of *t.
2531 // The parameter `explicit` indicates if this is an *explicit* dereference.
2532 // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
2533 pub fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
2534 deref_sty(cx, &get(t).sty, explicit)
2537 pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
2539 ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
2543 ty_ptr(mt) if explicit => {
2547 ty_enum(did, ref substs) => {
2548 let variants = enum_variants(cx, did);
2549 if vec::len(*variants) == 1u && vec::len(variants[0].args) == 1u {
2550 let v_t = subst(cx, substs, variants[0].args[0]);
2551 Some(mt {ty: v_t, mutbl: ast::m_imm})
2557 ty_struct(did, ref substs) => {
2558 let fields = struct_fields(cx, did, substs);
2559 if fields.len() == 1 && fields[0].ident ==
2560 syntax::parse::token::special_idents::unnamed_field {
2561 Some(mt {ty: fields[0].mt.ty, mutbl: ast::m_imm})
2571 pub fn type_autoderef(cx: ctxt, t: t) -> t {
2574 match deref(cx, t, false) {
2576 Some(mt) => t = mt.ty
2581 // Returns the type and mutability of t[i]
2582 pub fn index(t: t) -> Option<mt> {
2583 index_sty(&get(t).sty)
2586 pub fn index_sty(sty: &sty) -> Option<mt> {
2588 ty_evec(mt, _) => Some(mt),
2589 ty_estr(_) => Some(mt {ty: mk_u8(), mutbl: ast::m_imm}),
2595 * Enforces an arbitrary but consistent total ordering over
2596 * free regions. This is needed for establishing a consistent
2597 * LUB in region_inference. */
2598 impl cmp::TotalOrd for FreeRegion {
2599 fn cmp(&self, other: &FreeRegion) -> Ordering {
2600 cmp::cmp2(&self.scope_id, &self.bound_region,
2601 &other.scope_id, &other.bound_region)
2605 impl cmp::TotalEq for FreeRegion {
2606 fn equals(&self, other: &FreeRegion) -> bool {
2612 * Enforces an arbitrary but consistent total ordering over
2613 * bound regions. This is needed for establishing a consistent
2614 * LUB in region_inference. */
2615 impl cmp::TotalOrd for bound_region {
2616 fn cmp(&self, other: &bound_region) -> Ordering {
2617 match (self, other) {
2618 (&ty::br_self, &ty::br_self) => cmp::Equal,
2619 (&ty::br_self, _) => cmp::Less,
2621 (&ty::br_anon(ref a1), &ty::br_anon(ref a2)) => a1.cmp(a2),
2622 (&ty::br_anon(*), _) => cmp::Less,
2624 (&ty::br_named(ref a1), &ty::br_named(ref a2)) => a1.repr.cmp(&a2.repr),
2625 (&ty::br_named(*), _) => cmp::Less,
2627 (&ty::br_cap_avoid(ref a1, @ref b1),
2628 &ty::br_cap_avoid(ref a2, @ref b2)) => cmp::cmp2(a1, b1, a2, b2),
2629 (&ty::br_cap_avoid(*), _) => cmp::Less,
2631 (&ty::br_fresh(ref a1), &ty::br_fresh(ref a2)) => a1.cmp(a2),
2632 (&ty::br_fresh(*), _) => cmp::Less,
2637 impl cmp::TotalEq for bound_region {
2638 fn equals(&self, other: &bound_region) -> bool {
2643 impl to_bytes::IterBytes for vstore {
2644 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2646 vstore_fixed(ref u) =>
2647 to_bytes::iter_bytes_2(&0u8, u, lsb0, f),
2649 vstore_uniq => 1u8.iter_bytes(lsb0, f),
2650 vstore_box => 2u8.iter_bytes(lsb0, f),
2652 vstore_slice(ref r) =>
2653 to_bytes::iter_bytes_2(&3u8, r, lsb0, f),
2658 impl to_bytes::IterBytes for substs {
2659 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2660 to_bytes::iter_bytes_3(&self.self_r,
2666 impl to_bytes::IterBytes for mt {
2667 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2668 to_bytes::iter_bytes_2(&self.ty,
2669 &self.mutbl, lsb0, f)
2673 impl to_bytes::IterBytes for field {
2674 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2675 to_bytes::iter_bytes_2(&self.ident,
2680 impl to_bytes::IterBytes for FnSig {
2681 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2682 to_bytes::iter_bytes_2(&self.inputs,
2688 impl to_bytes::IterBytes for sty {
2689 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) {
2691 ty_nil => 0u8.iter_bytes(lsb0, f),
2692 ty_bool => 1u8.iter_bytes(lsb0, f),
2695 to_bytes::iter_bytes_2(&2u8, t, lsb0, f),
2698 to_bytes::iter_bytes_2(&3u8, t, lsb0, f),
2701 to_bytes::iter_bytes_2(&4u8, t, lsb0, f),
2704 to_bytes::iter_bytes_2(&5u8, v, lsb0, f),
2706 ty_enum(ref did, ref substs) =>
2707 to_bytes::iter_bytes_3(&6u8, did, substs, lsb0, f),
2710 to_bytes::iter_bytes_2(&7u8, mt, lsb0, f),
2712 ty_evec(ref mt, ref v) =>
2713 to_bytes::iter_bytes_3(&8u8, mt, v, lsb0, f),
2715 ty_unboxed_vec(ref mt) =>
2716 to_bytes::iter_bytes_2(&9u8, mt, lsb0, f),
2719 to_bytes::iter_bytes_2(&10u8, ts, lsb0, f),
2721 ty_bare_fn(ref ft) =>
2722 to_bytes::iter_bytes_2(&12u8, ft, lsb0, f),
2724 ty_self(ref did) => to_bytes::iter_bytes_2(&13u8, did, lsb0, f),
2727 to_bytes::iter_bytes_2(&14u8, v, lsb0, f),
2730 to_bytes::iter_bytes_2(&15u8, p, lsb0, f),
2732 ty_type => 16u8.iter_bytes(lsb0, f),
2733 ty_bot => 17u8.iter_bytes(lsb0, f),
2736 to_bytes::iter_bytes_2(&18u8, mt, lsb0, f),
2739 to_bytes::iter_bytes_2(&19u8, mt, lsb0, f),
2741 ty_trait(ref did, ref substs, ref v, ref mutbl) =>
2742 to_bytes::iter_bytes_5(&20u8, did, substs, v, mutbl, lsb0, f),
2744 ty_opaque_closure_ptr(ref ck) =>
2745 to_bytes::iter_bytes_2(&21u8, ck, lsb0, f),
2747 ty_opaque_box => 22u8.iter_bytes(lsb0, f),
2749 ty_struct(ref did, ref substs) =>
2750 to_bytes::iter_bytes_3(&23u8, did, substs, lsb0, f),
2752 ty_rptr(ref r, ref mt) =>
2753 to_bytes::iter_bytes_3(&24u8, r, mt, lsb0, f),
2755 ty_err => 25u8.iter_bytes(lsb0, f),
2757 ty_closure(ref ct) =>
2758 to_bytes::iter_bytes_2(&26u8, ct, lsb0, f),
2763 pub fn node_id_to_trait_ref(cx: ctxt, id: ast::node_id) -> @ty::TraitRef {
2764 match cx.trait_refs.find(&id) {
2766 None => cx.sess.bug(
2767 fmt!("node_id_to_trait_ref: no trait ref for node `%s`",
2768 ast_map::node_id_to_str(cx.items, id,
2769 cx.sess.parse_sess.interner)))
2773 pub fn node_id_to_type(cx: ctxt, id: ast::node_id) -> t {
2774 //io::println(fmt!("%?/%?", id, cx.node_types.len()));
2775 match cx.node_types.find(&(id as uint)) {
2777 None => cx.sess.bug(
2778 fmt!("node_id_to_type: no type for node `%s`",
2779 ast_map::node_id_to_str(cx.items, id,
2780 cx.sess.parse_sess.interner)))
2784 pub fn node_id_to_type_params(cx: ctxt, id: ast::node_id) -> ~[t] {
2785 match cx.node_type_substs.find(&id) {
2787 Some(ts) => return /*bad*/ copy *ts
2791 fn node_id_has_type_params(cx: ctxt, id: ast::node_id) -> bool {
2792 cx.node_type_substs.contains_key(&id)
2795 pub fn ty_fn_sig(fty: t) -> FnSig {
2796 match get(fty).sty {
2797 ty_bare_fn(ref f) => copy f.sig,
2798 ty_closure(ref f) => copy f.sig,
2800 fail!(fmt!("ty_fn_sig() called on non-fn type: %?", s))
2805 // Type accessors for substructures of types
2806 pub fn ty_fn_args(fty: t) -> ~[arg] {
2807 match get(fty).sty {
2808 ty_bare_fn(ref f) => copy f.sig.inputs,
2809 ty_closure(ref f) => copy f.sig.inputs,
2811 fail!(fmt!("ty_fn_args() called on non-fn type: %?", s))
2816 pub fn ty_closure_sigil(fty: t) -> Sigil {
2817 match get(fty).sty {
2818 ty_closure(ref f) => f.sigil,
2820 fail!(fmt!("ty_closure_sigil() called on non-closure type: %?",
2826 pub fn ty_fn_purity(fty: t) -> ast::purity {
2827 match get(fty).sty {
2828 ty_bare_fn(ref f) => f.purity,
2829 ty_closure(ref f) => f.purity,
2831 fail!(fmt!("ty_fn_purity() called on non-fn type: %?", s))
2836 pub fn ty_fn_ret(fty: t) -> t {
2837 match get(fty).sty {
2838 ty_bare_fn(ref f) => f.sig.output,
2839 ty_closure(ref f) => f.sig.output,
2841 fail!(fmt!("ty_fn_ret() called on non-fn type: %?", s))
2846 pub fn is_fn_ty(fty: t) -> bool {
2847 match get(fty).sty {
2848 ty_bare_fn(_) => true,
2849 ty_closure(_) => true,
2854 pub fn ty_vstore(ty: t) -> vstore {
2856 ty_evec(_, vstore) => vstore,
2857 ty_estr(vstore) => vstore,
2858 ref s => fail!(fmt!("ty_vstore() called on invalid sty: %?", s))
2862 pub fn ty_region(tcx: ctxt,
2867 ty_evec(_, vstore_slice(r)) => r,
2868 ty_estr(vstore_slice(r)) => r,
2872 fmt!("ty_region() invoked on in appropriate ty: %?", s));
2877 pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
2880 * Returns a new function type based on `fn_type` but returning a value of
2881 * type `ret_type` instead. */
2883 match ty::get(fn_type).sty {
2884 ty::ty_closure(ref fty) => {
2885 ty::mk_closure(tcx, ClosureTy {
2886 sig: FnSig {output: ret_type, ..copy fty.sig},
2892 "replace_fn_ret() invoked with non-fn-type: %s",
2893 ty_to_str(tcx, fn_type)));
2898 // Returns a vec of all the input and output types of fty.
2899 pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
2900 vec::append_one(sig.inputs.map(|a| a.ty), sig.output)
2903 // Type accessors for AST nodes
2904 pub fn block_ty(cx: ctxt, b: &ast::blk) -> t {
2905 return node_id_to_type(cx, b.node.id);
2909 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
2910 // doesn't provide type parameter substitutions.
2911 pub fn pat_ty(cx: ctxt, pat: @ast::pat) -> t {
2912 return node_id_to_type(cx, pat.id);
2916 // Returns the type of an expression as a monotype.
2918 // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
2919 // some cases, we insert `AutoAdjustment` annotations such as auto-deref or
2920 // auto-ref. The type returned by this function does not consider such
2921 // adjustments. See `expr_ty_adjusted()` instead.
2923 // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
2924 // ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
2925 // instead of "fn(t) -> T with T = int". If this isn't what you want, see
2926 // expr_ty_params_and_ty() below.
2927 pub fn expr_ty(cx: ctxt, expr: @ast::expr) -> t {
2928 return node_id_to_type(cx, expr.id);
2931 pub fn expr_ty_adjusted(cx: ctxt, expr: @ast::expr) -> t {
2934 * Returns the type of `expr`, considering any `AutoAdjustment`
2935 * entry recorded for that expression.
2937 * It would almost certainly be better to store the adjusted ty in with
2938 * the `AutoAdjustment`, but I opted not to do this because it would
2939 * require serializing and deserializing the type and, although that's not
2940 * hard to do, I just hate that code so much I didn't want to touch it
2941 * unless it was to fix it properly, which seemed a distraction from the
2942 * task at hand! -nmatsakis
2945 let unadjusted_ty = expr_ty(cx, expr);
2946 adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find(&expr.id))
2949 pub fn adjust_ty(cx: ctxt,
2951 unadjusted_ty: ty::t,
2952 adjustment: Option<&@AutoAdjustment>) -> ty::t
2954 /*! See `expr_ty_adjusted` */
2956 return match adjustment {
2957 None => unadjusted_ty,
2959 Some(&@AutoAddEnv(r, s)) => {
2960 match ty::get(unadjusted_ty).sty {
2961 ty::ty_bare_fn(ref b) => {
2964 ty::ClosureTy {purity: b.purity,
2966 onceness: ast::Many,
2972 fmt!("add_env adjustment on non-bare-fn: %?", b));
2977 Some(&@AutoDerefRef(ref adj)) => {
2978 let mut adjusted_ty = unadjusted_ty;
2980 for uint::range(0, adj.autoderefs) |i| {
2981 match ty::deref(cx, adjusted_ty, true) {
2982 Some(mt) => { adjusted_ty = mt.ty; }
2986 fmt!("The %uth autoderef failed: %s",
2994 None => adjusted_ty,
2995 Some(ref autoref) => {
2996 match autoref.kind {
2998 mk_rptr(cx, autoref.region,
2999 mt {ty: adjusted_ty,
3000 mutbl: autoref.mutbl})
3004 borrow_vec(cx, span, autoref, adjusted_ty)
3007 AutoBorrowVecRef => {
3008 adjusted_ty = borrow_vec(cx, span, autoref,
3010 mk_rptr(cx, autoref.region,
3011 mt {ty: adjusted_ty, mutbl: ast::m_imm})
3015 borrow_fn(cx, span, autoref, adjusted_ty)
3023 fn borrow_vec(cx: ctxt, span: span,
3024 autoref: &AutoRef, ty: ty::t) -> ty::t {
3027 ty::mk_evec(cx, mt {ty: mt.ty, mutbl: autoref.mutbl},
3028 vstore_slice(autoref.region))
3032 ty::mk_estr(cx, vstore_slice(autoref.region))
3038 fmt!("borrow-vec associated with bad sty: %?",
3044 fn borrow_fn(cx: ctxt, span: span,
3045 autoref: &AutoRef, ty: ty::t) -> ty::t {
3047 ty_closure(ref fty) => {
3048 ty::mk_closure(cx, ClosureTy {
3049 sigil: BorrowedSigil,
3050 region: autoref.region,
3058 fmt!("borrow-fn associated with bad sty: %?",
3065 pub struct ParamsTy {
3070 pub fn expr_ty_params_and_ty(cx: ctxt,
3074 params: node_id_to_type_params(cx, expr.id),
3075 ty: node_id_to_type(cx, expr.id)
3079 pub fn expr_has_ty_params(cx: ctxt, expr: @ast::expr) -> bool {
3080 return node_id_has_type_params(cx, expr.id);
3083 pub fn method_call_type_param_defs(
3085 method_map: typeck::method_map,
3086 id: ast::node_id) -> Option<@~[TypeParameterDef]>
3088 do method_map.find(&id).map |method| {
3089 match method.origin {
3090 typeck::method_static(did) => {
3091 // n.b.: When we encode impl methods, the bounds
3092 // that we encode include both the impl bounds
3093 // and then the method bounds themselves...
3094 ty::lookup_item_type(tcx, did).generics.type_param_defs
3096 typeck::method_param(typeck::method_param {
3098 method_num: n_mth, _}) |
3099 typeck::method_trait(trt_id, n_mth, _) |
3100 typeck::method_self(trt_id, n_mth) |
3101 typeck::method_super(trt_id, n_mth) => {
3102 // ...trait methods bounds, in contrast, include only the
3103 // method bounds, so we must preprend the tps from the
3104 // trait itself. This ought to be harmonized.
3105 let trait_type_param_defs =
3106 ty::lookup_trait_def(tcx, trt_id).generics.type_param_defs;
3108 copy *trait_type_param_defs,
3109 *ty::trait_method(tcx, trt_id, n_mth).generics.type_param_defs)
3115 pub fn resolve_expr(tcx: ctxt, expr: @ast::expr) -> ast::def {
3116 match tcx.def_map.find(&expr.id) {
3119 tcx.sess.span_bug(expr.span, fmt!(
3120 "No def-map entry for expr %?", expr.id));
3125 pub fn expr_is_lval(tcx: ctxt,
3126 method_map: typeck::method_map,
3127 e: @ast::expr) -> bool {
3128 match expr_kind(tcx, method_map, e) {
3130 RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
3134 /// We categorize expressions into three kinds. The distinction between
3135 /// lvalue/rvalue is fundamental to the language. The distinction between the
3136 /// two kinds of rvalues is an artifact of trans which reflects how we will
3137 /// generate code for that kind of expression. See trans/expr.rs for more
3146 pub fn expr_kind(tcx: ctxt,
3147 method_map: typeck::method_map,
3148 expr: @ast::expr) -> ExprKind {
3149 if method_map.contains_key(&expr.id) {
3150 // Overloaded operations are generally calls, and hence they are
3151 // generated via DPS. However, assign_op (e.g., `x += y`) is an
3152 // exception, as its result is always unit.
3153 return match expr.node {
3154 ast::expr_assign_op(*) => RvalueStmtExpr,
3160 ast::expr_path(*) => {
3161 match resolve_expr(tcx, expr) {
3162 ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3164 // Fn pointers are just scalar values.
3165 ast::def_fn(*) | ast::def_static_method(*) => RvalueDatumExpr,
3167 // Note: there is actually a good case to be made that
3168 // def_args, particularly those of immediate type, ought to
3169 // considered rvalues.
3171 ast::def_binding(*) |
3175 ast::def_self(*) => LvalueExpr,
3178 tcx.sess.span_bug(expr.span, fmt!(
3179 "Uncategorized def for expr %?: %?",
3185 ast::expr_unary(ast::deref, _) |
3186 ast::expr_field(*) |
3187 ast::expr_index(*) => {
3192 ast::expr_method_call(*) |
3193 ast::expr_struct(*) |
3196 ast::expr_match(*) |
3197 ast::expr_fn_block(*) |
3198 ast::expr_loop_body(*) |
3199 ast::expr_do_body(*) |
3200 ast::expr_block(*) |
3202 ast::expr_repeat(*) |
3203 ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) |
3204 ast::expr_vstore(_, ast::expr_vstore_slice) |
3205 ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3206 ast::expr_vec(*) => {
3210 ast::expr_cast(*) => {
3211 match tcx.node_types.find(&(expr.id as uint)) {
3213 if ty::type_is_immediate(t) {
3220 // Technically, it should not happen that the expr is not
3221 // present within the table. However, it DOES happen
3222 // during type check, because the final types from the
3223 // expressions are not yet recorded in the tcx. At that
3224 // time, though, we are only interested in knowing lvalue
3225 // vs rvalue. It would be better to base this decision on
3226 // the AST type in cast node---but (at the time of this
3227 // writing) it's not easy to distinguish casts to traits
3228 // from other casts based on the AST. This should be
3229 // easier in the future, when casts to traits would like
3230 // like @Foo, ~Foo, or &Foo.
3236 ast::expr_break(*) |
3237 ast::expr_again(*) |
3240 ast::expr_while(*) |
3242 ast::expr_assign(*) |
3244 ast::expr_inline_asm(*) |
3245 ast::expr_assign_op(*) => {
3249 ast::expr_lit(_) | // Note: lit_str is carved out above
3250 ast::expr_unary(*) |
3251 ast::expr_addr_of(*) |
3252 ast::expr_binary(*) |
3253 ast::expr_vstore(_, ast::expr_vstore_box) |
3254 ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3255 ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3259 ast::expr_paren(e) => expr_kind(tcx, method_map, e),
3261 ast::expr_mac(*) => {
3264 ~"macro expression remains after expansion");
3269 pub fn stmt_node_id(s: @ast::stmt) -> ast::node_id {
3271 ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
3274 ast::stmt_mac(*) => fail!(~"unexpanded macro in trans")
3278 pub fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3280 for fields.each |f| { if f.ident == id { return Some(i); } i += 1u; }
3284 pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
3287 for fields.each |f| { if f.ident == id { return i; } i += 1u; }
3289 "No field named `%s` found in the list of fields `%?`",
3290 *tcx.sess.str_of(id),
3291 fields.map(|f| tcx.sess.str_of(f.ident))));
3294 pub fn method_idx(id: ast::ident, meths: &[@method]) -> Option<uint> {
3295 vec::position(meths, |m| m.ident == id)
3298 /// Returns a vector containing the indices of all type parameters that appear
3299 /// in `ty`. The vector may contain duplicates. Probably should be converted
3300 /// to a bitset or some other representation.
3301 pub fn param_tys_in_type(ty: t) -> ~[param_ty] {
3303 do walk_ty(ty) |ty| {
3314 pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3315 // Returns a vec of all the type variables occurring in `ty`. It may
3316 // contain duplicates. (Integral type vars aren't counted.)
3317 fn vars_in_type(ty: t) -> ~[TyVid] {
3319 do walk_ty(ty) |ty| {
3321 ty_infer(TyVar(v)) => rslt.push(v),
3329 if !type_needs_infer(rt) { return; }
3332 if vec::contains(vars_in_type(rt), &vid) {
3333 // Maybe this should be span_err -- however, there's an
3334 // assertion later on that the type doesn't contain
3335 // variables, so in this case we have to be sure to die.
3337 (sp, ~"type inference failed because I \
3338 could not find a type\n that's both of the form "
3339 + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) +
3340 ~" and of the form " + ::util::ppaux::ty_to_str(tcx, rt) +
3341 ~" - such a type would have to be infinitely large.");
3345 pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3347 ty_nil | ty_bot | ty_bool | ty_int(_) |
3348 ty_uint(_) | ty_float(_) | ty_estr(_) |
3349 ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
3350 ::util::ppaux::ty_to_str(cx, t)
3353 ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
3354 ty_box(_) => ~"@-ptr",
3355 ty_uniq(_) => ~"~-ptr",
3356 ty_evec(_, _) => ~"vector",
3357 ty_unboxed_vec(_) => ~"unboxed vector",
3358 ty_ptr(_) => ~"*-ptr",
3359 ty_rptr(_, _) => ~"&-ptr",
3360 ty_bare_fn(_) => ~"extern fn",
3361 ty_closure(_) => ~"fn",
3362 ty_trait(id, _, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3363 ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
3364 ty_tup(_) => ~"tuple",
3365 ty_infer(TyVar(_)) => ~"inferred type",
3366 ty_infer(IntVar(_)) => ~"integral variable",
3367 ty_infer(FloatVar(_)) => ~"floating-point variable",
3368 ty_param(_) => ~"type parameter",
3369 ty_self(_) => ~"self",
3370 ty_err => ~"type error"
3374 pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3377 * Explains the source of a type err in a short,
3378 * human readable way. This is meant to be placed in
3379 * parentheses after some larger message. You should
3380 * also invoke `note_and_explain_type_err()` afterwards
3381 * to present additional details, particularly when
3382 * it comes to lifetime-related errors. */
3384 fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3389 terr_trait => ~"trait"
3394 terr_mismatch => ~"types differ",
3395 terr_purity_mismatch(values) => {
3396 fmt!("expected %s fn but found %s fn",
3397 values.expected.to_str(), values.found.to_str())
3399 terr_abi_mismatch(values) => {
3400 fmt!("expected %s fn but found %s fn",
3401 values.expected.to_str(), values.found.to_str())
3403 terr_onceness_mismatch(values) => {
3404 fmt!("expected %s fn but found %s fn",
3405 values.expected.to_str(), values.found.to_str())
3407 terr_sigil_mismatch(values) => {
3408 fmt!("expected %s closure, found %s closure",
3409 values.expected.to_str(),
3410 values.found.to_str())
3412 terr_mutability => ~"values differ in mutability",
3413 terr_box_mutability => ~"boxed values differ in mutability",
3414 terr_vec_mutability => ~"vectors differ in mutability",
3415 terr_ptr_mutability => ~"pointers differ in mutability",
3416 terr_ref_mutability => ~"references differ in mutability",
3417 terr_ty_param_size(values) => {
3418 fmt!("expected a type with %? type params \
3419 but found one with %? type params",
3420 values.expected, values.found)
3422 terr_tuple_size(values) => {
3423 fmt!("expected a tuple with %? elements \
3424 but found one with %? elements",
3425 values.expected, values.found)
3427 terr_record_size(values) => {
3428 fmt!("expected a record with %? fields \
3429 but found one with %? fields",
3430 values.expected, values.found)
3432 terr_record_mutability => {
3433 ~"record elements differ in mutability"
3435 terr_record_fields(values) => {
3436 fmt!("expected a record with field `%s` but found one with field \
3438 *cx.sess.str_of(values.expected),
3439 *cx.sess.str_of(values.found))
3441 terr_arg_count => ~"incorrect number of function parameters",
3442 terr_regions_does_not_outlive(*) => {
3443 fmt!("lifetime mismatch")
3445 terr_regions_not_same(*) => {
3446 fmt!("lifetimes are not the same")
3448 terr_regions_no_overlap(*) => {
3449 fmt!("lifetimes do not intersect")
3451 terr_regions_insufficiently_polymorphic(br, _) => {
3452 fmt!("expected bound lifetime parameter %s, \
3453 but found concrete lifetime",
3454 bound_region_to_str(cx, br))
3456 terr_regions_overly_polymorphic(br, _) => {
3457 fmt!("expected concrete lifetime, \
3458 but found bound lifetime parameter %s",
3459 bound_region_to_str(cx, br))
3461 terr_vstores_differ(k, ref values) => {
3462 fmt!("%s storage differs: expected %s but found %s",
3463 terr_vstore_kind_to_str(k),
3464 vstore_to_str(cx, (*values).expected),
3465 vstore_to_str(cx, (*values).found))
3467 terr_trait_stores_differ(_, ref values) => {
3468 fmt!("trait storage differs: expected %s but found %s",
3469 trait_store_to_str(cx, (*values).expected),
3470 trait_store_to_str(cx, (*values).found))
3472 terr_in_field(err, fname) => {
3473 fmt!("in field `%s`, %s", *cx.sess.str_of(fname),
3474 type_err_to_str(cx, err))
3476 terr_sorts(values) => {
3477 fmt!("expected %s but found %s",
3478 ty_sort_str(cx, values.expected),
3479 ty_sort_str(cx, values.found))
3481 terr_traits(values) => {
3482 fmt!("expected trait %s but found trait %s",
3483 item_path_str(cx, values.expected),
3484 item_path_str(cx, values.found))
3486 terr_self_substs => {
3487 ~"inconsistent self substitution" // XXX this is more of a bug
3489 terr_integer_as_char => {
3490 fmt!("expected an integral type but found char")
3492 terr_int_mismatch(ref values) => {
3493 fmt!("expected %s but found %s",
3494 values.expected.to_str(),
3495 values.found.to_str())
3497 terr_float_mismatch(ref values) => {
3498 fmt!("expected %s but found %s",
3499 values.expected.to_str(),
3500 values.found.to_str())
3505 pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
3507 terr_regions_does_not_outlive(subregion, superregion) => {
3508 note_and_explain_region(cx, ~"", subregion, ~"...");
3509 note_and_explain_region(cx, ~"...does not necessarily outlive ",
3512 terr_regions_not_same(region1, region2) => {
3513 note_and_explain_region(cx, ~"", region1, ~"...");
3514 note_and_explain_region(cx, ~"...is not the same lifetime as ",
3517 terr_regions_no_overlap(region1, region2) => {
3518 note_and_explain_region(cx, ~"", region1, ~"...");
3519 note_and_explain_region(cx, ~"...does not overlap ",
3522 terr_regions_insufficiently_polymorphic(_, conc_region) => {
3523 note_and_explain_region(cx,
3524 ~"concrete lifetime that was found is ",
3527 terr_regions_overly_polymorphic(_, conc_region) => {
3528 note_and_explain_region(cx,
3529 ~"expected concrete lifetime is ",
3536 pub fn def_has_ty_params(def: ast::def) -> bool {
3538 ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
3544 pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[ast::ident] {
3546 match cx.items.find(&id.node) {
3547 Some(&ast_map::node_item(@ast::item {
3548 node: item_trait(_, _, ref ms),
3551 match ast_util::split_trait_methods(*ms) {
3552 (_, p) => p.map(|method| method.ident)
3554 _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3558 csearch::get_provided_trait_methods(cx, id).map(|ifo| ifo.ty.ident)
3562 pub fn trait_supertraits(cx: ctxt,
3563 id: ast::def_id) -> @~[@TraitRef]
3566 match cx.supertraits.find(&id) {
3567 Some(&trait_refs) => { return trait_refs; }
3568 None => {} // Continue.
3571 // Not in the cache. It had better be in the metadata, which means it
3572 // shouldn't be local.
3573 assert!(!is_local(id));
3575 // Get the supertraits out of the metadata and create the
3576 // TraitRef for each.
3577 let result = @csearch::get_supertraits(cx, id);
3578 cx.supertraits.insert(id, result);
3582 pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef] {
3583 let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
3584 supertrait_refs.map(
3585 |supertrait_ref| @supertrait_ref.subst(cx, &trait_ref.substs))
3588 fn lookup_locally_or_in_crate_store<V:Copy>(
3590 def_id: ast::def_id,
3591 map: &mut HashMap<ast::def_id, V>,
3592 load_external: &fn() -> V) -> V
3596 * Helper for looking things up in the various maps
3597 * that are populated during typeck::collect (e.g.,
3598 * `cx.methods`, `cx.tcache`, etc). All of these share
3599 * the pattern that if the id is local, it should have
3600 * been loaded into the map by the `typeck::collect` phase.
3601 * If the def-id is external, then we have to go consult
3602 * the crate loading code (and cache the result for the future).
3605 match map.find(&def_id) {
3606 Some(&v) => { return v; }
3610 if def_id.crate == ast::local_crate {
3611 fail!(fmt!("No def'n found for %? in tcx.%s",
3614 let v = load_external();
3615 map.insert(def_id, v);
3619 pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @method {
3620 let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx];
3621 ty::method(cx, method_def_id)
3624 pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@method] {
3625 match cx.trait_methods_cache.find(&trait_did) {
3626 Some(&methods) => methods,
3628 let def_ids = ty::trait_method_def_ids(cx, trait_did);
3629 let methods = @def_ids.map(|d| ty::method(cx, *d));
3630 cx.trait_methods_cache.insert(trait_did, methods);
3636 pub fn method(cx: ctxt, id: ast::def_id) -> @method {
3637 lookup_locally_or_in_crate_store(
3638 "methods", id, cx.methods,
3639 || @csearch::get_method(cx, id))
3642 pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
3643 lookup_locally_or_in_crate_store(
3644 "methods", id, cx.trait_method_def_ids,
3645 || @csearch::get_trait_method_def_ids(cx.cstore, id))
3648 pub fn impl_trait_refs(cx: ctxt, id: ast::def_id) -> ~[@TraitRef] {
3649 if id.crate == ast::local_crate {
3650 debug!("(impl_traits) searching for trait impl %?", id);
3651 match cx.items.find(&id.node) {
3652 Some(&ast_map::node_item(@ast::item {
3653 node: ast::item_impl(_, opt_trait, _, _),
3657 Some(t) => ~[ty::node_id_to_trait_ref(cx, t.ref_id)],
3664 csearch::get_impl_traits(cx, id)
3668 pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3670 ty_trait(id, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
3675 /// Returns the def ID of the constructor for the given tuple-like struct, or
3676 /// None if the struct is not tuple-like. Fails if the given def ID does not
3677 /// refer to a struct at all.
3678 fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option<ast::def_id> {
3679 if struct_did.crate != ast::local_crate {
3680 // XXX: Cross-crate functionality.
3681 cx.sess.unimpl(~"constructor ID of cross-crate tuple structs");
3684 match cx.items.find(&struct_did.node) {
3685 Some(&ast_map::node_item(item, _)) => {
3687 ast::item_struct(struct_def, _) => {
3688 struct_def.ctor_id.map(|ctor_id|
3689 ast_util::local_def(*ctor_id))
3691 _ => cx.sess.bug(~"called struct_ctor_id on non-struct")
3694 _ => cx.sess.bug(~"called struct_ctor_id on non-struct")
3699 pub struct VariantInfo_ {
3708 pub type VariantInfo = @VariantInfo_;
3710 pub fn substd_enum_variants(cx: ctxt,
3714 do vec::map(*enum_variants(cx, id)) |variant_info| {
3715 let substd_args = vec::map(variant_info.args,
3716 |aty| subst(cx, substs, *aty));
3718 let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3720 @VariantInfo_{args: substd_args, ctor_ty: substd_ctor_ty,
3721 ../*bad*/copy **variant_info}
3725 pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
3726 ast_map::path_to_str(item_path(cx, id), cx.sess.parse_sess.interner)
3736 fn is_not_present(&const self) -> bool {
3742 fn is_present(&const self) -> bool {
3743 !self.is_not_present()
3747 /* If struct_id names a struct with a dtor, return Some(the dtor's id).
3748 Otherwise return none. */
3749 pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
3750 match cx.destructor_for_type.find(&struct_id) {
3751 Some(&method_def_id) => TraitDtor(method_def_id),
3756 pub fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
3757 ty_dtor(cx, struct_id).is_present()
3760 pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
3761 if id.crate != ast::local_crate {
3762 csearch::get_item_path(cx, id)
3764 // FIXME (#5521): uncomment this code and don't have a catch-all at the
3765 // end of the match statement. Favor explicitly listing
3767 // let node = cx.items.get(&id.node);
3769 match *cx.items.get(&id.node) {
3770 ast_map::node_item(item, path) => {
3771 let item_elt = match item.node {
3772 item_mod(_) | item_foreign_mod(_) => {
3773 ast_map::path_mod(item.ident)
3776 ast_map::path_name(item.ident)
3779 vec::append_one(/*bad*/copy *path, item_elt)
3782 ast_map::node_foreign_item(nitem, _, _, path) => {
3783 vec::append_one(/*bad*/copy *path,
3784 ast_map::path_name(nitem.ident))
3787 ast_map::node_method(method, _, path) => {
3788 vec::append_one(/*bad*/copy *path,
3789 ast_map::path_name(method.ident))
3791 ast_map::node_trait_method(trait_method, _, path) => {
3792 let method = ast_util::trait_method_to_ty_method(&*trait_method);
3793 vec::append_one(/*bad*/copy *path,
3794 ast_map::path_name(method.ident))
3797 ast_map::node_variant(ref variant, _, path) => {
3798 vec::append_one(vec::from_slice(vec::init(*path)),
3799 ast_map::path_name((*variant).node.name))
3802 ast_map::node_struct_ctor(_, item, path) => {
3803 vec::append_one(/*bad*/copy *path, ast_map::path_name(item.ident))
3807 cx.sess.bug(fmt!("cannot find item_path for node %?", node));
3813 pub fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
3814 enum_variants(cx, id).len() == 1
3817 pub fn type_is_empty(cx: ctxt, t: t) -> bool {
3818 match ty::get(t).sty {
3819 ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
3824 pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[VariantInfo] {
3825 match cx.enum_var_cache.find(&id) {
3826 Some(&variants) => return variants,
3827 _ => { /* fallthrough */ }
3830 let result = if ast::local_crate != id.crate {
3831 @csearch::get_enum_variants(cx, id)
3834 Although both this code and check_enum_variants in typeck/check
3835 call eval_const_expr, it should never get called twice for the same
3836 expr, since check_enum_variants also updates the enum_var_cache
3838 match *cx.items.get(&id.node) {
3839 ast_map::node_item(@ast::item {
3840 node: ast::item_enum(ref enum_definition, _),
3843 let mut disr_val = -1;
3844 @vec::map(enum_definition.variants, |variant| {
3845 match variant.node.kind {
3846 ast::tuple_variant_kind(ref args) => {
3847 let ctor_ty = node_id_to_type(cx, variant.node.id);
3849 if args.len() > 0u {
3850 ty_fn_args(ctor_ty).map(|a| a.ty)
3855 match variant.node.disr_expr {
3857 disr_val = match const_eval::eval_const_expr(cx,
3859 const_eval::const_int(val) => val as int,
3860 _ => cx.sess.bug(~"tag_variants: bad disr expr")
3865 @VariantInfo_{args: arg_tys,
3867 name: variant.node.name,
3868 id: ast_util::local_def(variant.node.id),
3870 vis: variant.node.vis
3873 ast::struct_variant_kind(_) => {
3874 fail!(~"struct variant kinds unimpl in enum_variants")
3879 _ => cx.sess.bug(~"tag_variants: id not bound to an enum")
3882 cx.enum_var_cache.insert(id, result);
3887 // Returns information about the enum variant with the given ID:
3888 pub fn enum_variant_with_id(cx: ctxt,
3889 enum_id: ast::def_id,
3890 variant_id: ast::def_id)
3892 let variants = enum_variants(cx, enum_id);
3894 while i < variants.len() {
3895 let variant = variants[i];
3896 if variant.id == variant_id { return variant; }
3899 cx.sess.bug(~"enum_variant_with_id(): no variant exists with that ID");
3903 // If the given item is in an external crate, looks up its type and adds it to
3904 // the type cache. Returns the type parameters and type.
3905 pub fn lookup_item_type(cx: ctxt,
3907 -> ty_param_bounds_and_ty {
3908 lookup_locally_or_in_crate_store(
3909 "tcache", did, cx.tcache,
3910 || csearch::get_type(cx, did))
3913 /// Given the did of a trait, returns its canonical trait ref.
3914 pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
3915 match cx.trait_defs.find(&did) {
3916 Some(&trait_def) => {
3917 // The item is in this crate. The caller should have added it to the
3918 // type cache already
3922 assert!(did.crate != ast::local_crate);
3923 let trait_def = @csearch::get_trait_def(cx, did);
3924 cx.trait_defs.insert(did, trait_def);
3930 // Determine whether an item is annotated with #[packed] or not
3931 pub fn lookup_packed(tcx: ctxt,
3932 did: def_id) -> bool {
3934 match tcx.items.find(&did.node) {
3936 &ast_map::node_item(@ast::item {
3939 }, _)) => attr::attrs_contains_name(*attrs, "packed"),
3940 _ => tcx.sess.bug(fmt!("lookup_packed: %? is not an item",
3944 let mut ret = false;
3945 do csearch::get_item_attrs(tcx.cstore, did) |meta_items| {
3946 ret = attr::contains_name(meta_items, "packed");
3952 // Look up a field ID, whether or not it's local
3953 // Takes a list of type substs in case the struct is generic
3954 pub fn lookup_field_type(tcx: ctxt,
3959 let t = if id.crate == ast::local_crate {
3960 node_id_to_type(tcx, id.node)
3963 match tcx.tcache.find(&id) {
3964 Some(tpt) => tpt.ty,
3966 let tpt = csearch::get_field_type(tcx, struct_id, id);
3967 tcx.tcache.insert(id, tpt);
3972 subst(tcx, substs, t)
3975 // Look up the list of field names and IDs for a given struct
3976 // Fails if the id is not bound to a struct.
3977 pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
3978 if did.crate == ast::local_crate {
3979 match cx.items.find(&did.node) {
3980 Some(&ast_map::node_item(i,_)) => {
3982 ast::item_struct(struct_def, _) => {
3983 struct_field_tys(struct_def.fields)
3985 _ => cx.sess.bug(~"struct ID bound to non-struct")
3988 Some(&ast_map::node_variant(ref variant, _, _)) => {
3989 match (*variant).node.kind {
3990 ast::struct_variant_kind(struct_def) => {
3991 struct_field_tys(struct_def.fields)
3994 cx.sess.bug(~"struct ID bound to enum variant that isn't \
4001 fmt!("struct ID not bound to an item: %s",
4002 ast_map::node_id_to_str(cx.items, did.node,
4003 cx.sess.parse_sess.interner)));
4008 return csearch::get_struct_fields(cx.sess.cstore, did);
4012 pub fn lookup_struct_field(cx: ctxt,
4013 parent: ast::def_id,
4014 field_id: ast::def_id)
4016 match vec::find(lookup_struct_fields(cx, parent),
4017 |f| f.id.node == field_id.node) {
4019 None => cx.sess.bug(~"struct ID not found in parent's fields")
4023 fn struct_field_tys(fields: &[@struct_field]) -> ~[field_ty] {
4024 do fields.map |field| {
4025 match field.node.kind {
4026 named_field(ident, mutability, visibility) => {
4029 id: ast_util::local_def(field.node.id),
4031 mutability: mutability,
4037 syntax::parse::token::special_idents::unnamed_field,
4038 id: ast_util::local_def(field.node.id),
4040 mutability: ast::struct_immutable,
4047 // Return a list of fields corresponding to the struct's items
4048 // (as if the struct was a record). trans uses this
4049 // Takes a list of substs with which to instantiate field types
4050 // Keep in mind that this function reports that all fields are
4051 // mutable, regardless of how they were declared. It's meant to
4052 // be used in trans.
4053 pub fn struct_mutable_fields(cx: ctxt,
4057 struct_item_fields(cx, did, substs, |_mt| m_mutbl)
4060 // Same as struct_mutable_fields, but doesn't change
4062 pub fn struct_fields(cx: ctxt,
4066 struct_item_fields(cx, did, substs, |mt| match mt {
4067 struct_mutable => m_mutbl,
4068 struct_immutable => m_imm })
4072 fn struct_item_fields(cx:ctxt,
4075 frob_mutability: &fn(struct_mutability) -> mutability)
4077 do lookup_struct_fields(cx, did).map |f| {
4078 // consider all instance vars mut, because the
4079 // constructor may mutate all vars
4083 ty: lookup_field_type(cx, did, f.id, substs),
4084 mutbl: frob_mutability(f.mutability)
4090 pub fn is_binopable(_cx: ctxt, ty: t, op: ast::binop) -> bool {
4091 static tycat_other: int = 0;
4092 static tycat_bool: int = 1;
4093 static tycat_int: int = 2;
4094 static tycat_float: int = 3;
4095 static tycat_struct: int = 4;
4096 static tycat_bot: int = 5;
4098 static opcat_add: int = 0;
4099 static opcat_sub: int = 1;
4100 static opcat_mult: int = 2;
4101 static opcat_shift: int = 3;
4102 static opcat_rel: int = 4;
4103 static opcat_eq: int = 5;
4104 static opcat_bit: int = 6;
4105 static opcat_logic: int = 7;
4107 fn opcat(op: ast::binop) -> int {
4109 ast::add => opcat_add,
4110 ast::subtract => opcat_sub,
4111 ast::mul => opcat_mult,
4112 ast::div => opcat_mult,
4113 ast::rem => opcat_mult,
4114 ast::and => opcat_logic,
4115 ast::or => opcat_logic,
4116 ast::bitxor => opcat_bit,
4117 ast::bitand => opcat_bit,
4118 ast::bitor => opcat_bit,
4119 ast::shl => opcat_shift,
4120 ast::shr => opcat_shift,
4121 ast::eq => opcat_eq,
4122 ast::ne => opcat_eq,
4123 ast::lt => opcat_rel,
4124 ast::le => opcat_rel,
4125 ast::ge => opcat_rel,
4126 ast::gt => opcat_rel
4130 fn tycat(ty: t) -> int {
4132 ty_bool => tycat_bool,
4133 ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4134 ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
4135 ty_tup(_) | ty_enum(_, _) => tycat_struct,
4136 ty_bot => tycat_bot,
4141 static t: bool = true;
4142 static f: bool = false;
4148 /*other*/ ~[f, f, f, f, f, f, f, f],
4149 /*bool*/ ~[f, f, f, f, t, t, t, t],
4150 /*int*/ ~[t, t, t, t, t, t, t, f],
4151 /*float*/ ~[t, t, t, f, t, t, f, f],
4152 /*bot*/ ~[f, f, f, f, f, f, f, f],
4153 /*struct*/ ~[t, t, t, t, f, f, t, t]];
4155 return tbl[tycat(ty)][opcat(op)];
4158 pub fn ty_params_to_tys(tcx: ty::ctxt, generics: &ast::Generics) -> ~[t] {
4159 vec::from_fn(generics.ty_params.len(), |i| {
4160 let id = generics.ty_params.get(i).id;
4161 ty::mk_param(tcx, i, ast_util::local_def(id))
4165 /// Returns an equivalent type with all the typedefs and self regions removed.
4166 pub fn normalize_ty(cx: ctxt, t: t) -> t {
4167 fn normalize_mt(cx: ctxt, mt: mt) -> mt {
4168 mt { ty: normalize_ty(cx, mt.ty), mutbl: mt.mutbl }
4170 fn normalize_vstore(vstore: vstore) -> vstore {
4172 vstore_fixed(*) | vstore_uniq | vstore_box => vstore,
4173 vstore_slice(_) => vstore_slice(re_static)
4177 match cx.normalized_cache.find(&t) {
4178 Some(&t) => return t,
4182 let t = match get(t).sty {
4183 ty_evec(mt, vstore) =>
4184 // This type has a vstore. Get rid of it
4185 mk_evec(cx, normalize_mt(cx, mt), normalize_vstore(vstore)),
4188 // This type has a vstore. Get rid of it
4189 mk_estr(cx, normalize_vstore(vstore)),
4192 // This type has a region. Get rid of it
4193 mk_rptr(cx, re_static, normalize_mt(cx, mt)),
4195 ty_closure(ref closure_ty) => {
4196 mk_closure(cx, ClosureTy {
4197 region: ty::re_static,
4202 ty_enum(did, ref r) =>
4205 // Use re_static since trans doesn't care about regions
4208 self_r: Some(ty::re_static),
4210 tps: /*bad*/copy (*r).tps
4216 ty_struct(did, ref r) =>
4220 mk_struct(cx, did, substs {self_r: Some(ty::re_static),
4222 tps: /*bad*/copy (*r).tps}),
4231 let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) });
4232 let t_norm = mk_t(cx, sty);
4233 cx.normalized_cache.insert(t, t_norm);
4237 // Returns the repeat count for a repeating vector expression.
4238 pub fn eval_repeat_count(tcx: ctxt, count_expr: @ast::expr) -> uint {
4239 match const_eval::eval_const_expr_partial(tcx, count_expr) {
4240 Ok(ref const_val) => match *const_val {
4241 const_eval::const_int(count) => return count as uint,
4242 const_eval::const_uint(count) => return count as uint,
4243 const_eval::const_float(count) => {
4244 tcx.sess.span_err(count_expr.span,
4245 ~"expected signed or unsigned integer for \
4246 repeat count but found float");
4247 return count as uint;
4249 const_eval::const_str(_) => {
4250 tcx.sess.span_err(count_expr.span,
4251 ~"expected signed or unsigned integer for \
4252 repeat count but found string");
4255 const_eval::const_bool(_) => {
4256 tcx.sess.span_err(count_expr.span,
4257 ~"expected signed or unsigned integer for \
4258 repeat count but found boolean");
4263 tcx.sess.span_err(count_expr.span,
4264 ~"expected constant integer for repeat count \
4265 but found variable");
4271 // Determine what purity to check a nested function under
4272 pub fn determine_inherited_purity(parent: (ast::purity, ast::node_id),
4273 child: (ast::purity, ast::node_id),
4274 child_sigil: ast::Sigil)
4275 -> (ast::purity, ast::node_id) {
4276 // If the closure is a stack closure and hasn't had some non-standard
4277 // purity inferred for it, then check it under its parent's purity.
4278 // Otherwise, use its own
4280 ast::BorrowedSigil if child.first() == ast::impure_fn => parent,
4285 // Iterate over a type parameter's bounded traits and any supertraits
4286 // of those traits, ignoring kinds.
4287 // Here, the supertraits are the transitive closure of the supertrait
4288 // relation on the supertraits from each bounded trait's constraint
4290 pub fn each_bound_trait_and_supertraits(tcx: ctxt,
4291 bounds: param_bounds,
4292 f: &fn(&TraitRef) -> bool) {
4293 for bounds.each |bound| {
4294 let bound_trait_ref = match *bound {
4295 ty::bound_trait(bound_t) => bound_t,
4297 ty::bound_copy | ty::bound_owned |
4298 ty::bound_const | ty::bound_durable => {
4299 loop; // skip non-trait bounds
4303 let mut supertrait_set = HashMap::new();
4304 let mut trait_refs = ~[];
4307 // Seed the worklist with the trait from the bound
4308 supertrait_set.insert(bound_trait_ref.def_id, ());
4309 trait_refs.push(bound_trait_ref);
4311 // Add the given trait ty to the hash map
4312 while i < trait_refs.len() {
4313 debug!("each_bound_trait_and_supertraits(i=%?, trait_ref=%s)",
4314 i, trait_refs[i].repr(tcx));
4316 if !f(trait_refs[i]) {
4320 // Add supertraits to supertrait_set
4321 let supertrait_refs = trait_ref_supertraits(tcx, trait_refs[i]);
4322 for supertrait_refs.each |&supertrait_ref| {
4323 debug!("each_bound_trait_and_supertraits(supertrait_ref=%s)",
4324 supertrait_ref.repr(tcx));
4326 let d_id = supertrait_ref.def_id;
4327 if !supertrait_set.contains_key(&d_id) {
4328 // FIXME(#5527) Could have same trait multiple times
4329 supertrait_set.insert(d_id, ());
4330 trait_refs.push(supertrait_ref);
4339 pub fn count_traits_and_supertraits(tcx: ctxt,
4340 type_param_defs: &[TypeParameterDef]) -> uint {
4342 for type_param_defs.each |type_param_def| {
4343 for each_bound_trait_and_supertraits(tcx, type_param_def.bounds) |_| {
4350 // Given a trait and a type, returns the impl of that type
4351 pub fn get_impl_id(tcx: ctxt, trait_id: def_id, self_ty: t) -> def_id {
4352 match tcx.trait_impls.find(&trait_id) {
4353 Some(ty_to_impl) => match ty_to_impl.find(&self_ty) {
4354 Some(the_impl) => the_impl.did,
4355 None => // try autoderef!
4356 match deref(tcx, self_ty, false) {
4357 Some(some_ty) => get_impl_id(tcx, trait_id, some_ty.ty),
4358 None => tcx.sess.bug(~"get_impl_id: no impl of trait for \
4362 None => tcx.sess.bug(~"get_impl_id: trait isn't in trait_impls")
4366 pub fn visitor_object_ty(tcx: ctxt) -> (@TraitRef, t) {
4367 let ty_visitor_name = special_idents::ty_visitor;
4368 assert!(tcx.intrinsic_traits.contains_key(&ty_visitor_name));
4369 let trait_ref = *tcx.intrinsic_traits.get(&ty_visitor_name);
4371 mk_trait(tcx, trait_ref.def_id, copy trait_ref.substs, BoxTraitStore, ast::m_imm))
4377 // indent-tabs-mode: nil
4378 // c-basic-offset: 4
4379 // buffer-file-coding-system: utf-8-unix