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;
16 use middle::lang_items::{TyDescStructLangItem, TyVisitorTraitLangItem};
17 use middle::lang_items::OpaqueStructLangItem;
21 use middle::subst::Subst;
24 use util::ppaux::{note_and_explain_region, bound_region_ptr_to_str};
25 use util::ppaux::{trait_store_to_str, ty_to_str, vstore_to_str};
26 use util::ppaux::{Repr, UserString};
27 use util::common::{indenter};
28 use util::enum_set::{EnumSet, CLike};
32 use std::hashmap::{HashMap, HashSet};
34 use std::ptr::to_unsafe_ptr;
36 use std::to_str::ToStr;
40 use syntax::ast_util::is_local;
43 use syntax::codemap::span;
45 use syntax::parse::token;
46 use syntax::{ast, ast_map};
47 use syntax::opt_vec::OptVec;
49 use syntax::abi::AbiSet;
52 pub static INITIAL_DISCRIMINANT_VALUE: uint = 0;
56 #[deriving(Eq, IterBytes)]
64 generics: ty::Generics,
65 transformed_self_ty: Option<ty::t>,
67 explicit_self: ast::explicit_self_,
70 container_id: ast::def_id,
72 // If this method is provided, we need to know where it came from
73 provided_source: Option<ast::def_id>
77 pub fn new(ident: ast::ident,
78 generics: ty::Generics,
79 transformed_self_ty: Option<ty::t>,
81 explicit_self: ast::explicit_self_,
84 container_id: ast::def_id,
85 provided_source: Option<ast::def_id>)
87 // Check the invariants.
88 if explicit_self == ast::sty_static {
89 assert!(transformed_self_ty.is_none());
91 assert!(transformed_self_ty.is_some());
97 transformed_self_ty: transformed_self_ty,
99 explicit_self: explicit_self,
102 container_id: container_id,
103 provided_source: provided_source
114 #[deriving(Clone, Eq, IterBytes)]
117 mutbl: ast::mutability,
120 #[deriving(Clone, Eq, Encodable, Decodable, IterBytes, ToStr)]
128 #[deriving(Clone, Eq, IterBytes, Encodable, Decodable, ToStr)]
129 pub enum TraitStore {
130 BoxTraitStore, // @Trait
131 UniqTraitStore, // ~Trait
132 RegionTraitStore(Region), // &Trait
135 // XXX: This should probably go away at some point. Maybe after destructors
137 #[deriving(Clone, Eq, Encodable, Decodable)]
143 pub struct field_ty {
146 vis: ast::visibility,
149 // Contains information needed to resolve types and (in the future) look up
150 // the types of AST nodes.
151 #[deriving(Eq,IterBytes)]
152 pub struct creader_cache_key {
158 type creader_cache = @mut HashMap<creader_cache_key, t>;
164 // NB: Do not replace this with #[deriving(Eq)]. The automatically-derived
165 // implementation will not recurse through sty and you will get stack
167 impl cmp::Eq for intern_key {
168 fn eq(&self, other: &intern_key) -> bool {
170 *self.sty == *other.sty
173 fn ne(&self, other: &intern_key) -> bool {
178 // NB: Do not replace this with #[deriving(IterBytes)], as above. (Figured
179 // this out the hard way.)
180 impl to_bytes::IterBytes for intern_key {
181 fn iter_bytes(&self, lsb0: bool, f: to_bytes::Cb) -> bool {
183 (*self.sty).iter_bytes(lsb0, f)
188 pub enum ast_ty_to_ty_cache_entry {
189 atttce_unresolved, /* not resolved yet */
190 atttce_resolved(t) /* resolved to a type, irrespective of region */
193 pub type opt_region_variance = Option<region_variance>;
195 #[deriving(Clone, Eq, Decodable, Encodable)]
196 pub enum region_variance {
202 #[deriving(Decodable, Encodable)]
203 pub enum AutoAdjustment {
204 AutoAddEnv(ty::Region, ast::Sigil),
205 AutoDerefRef(AutoDerefRef)
208 #[deriving(Decodable, Encodable)]
209 pub struct AutoDerefRef {
211 autoref: Option<AutoRef>
214 #[deriving(Decodable, Encodable)]
216 /// Convert from T to &T
217 AutoPtr(Region, ast::mutability),
219 /// Convert from @[]/~[]/&[] to &[] (or str)
220 AutoBorrowVec(Region, ast::mutability),
222 /// Convert from @[]/~[]/&[] to &&[] (or str)
223 AutoBorrowVecRef(Region, ast::mutability),
225 /// Convert from @fn()/~fn()/&fn() to &fn()
226 AutoBorrowFn(Region),
228 /// Convert from T to *T
229 AutoUnsafe(ast::mutability)
232 pub type ctxt = @ctxt_;
235 diag: @syntax::diagnostic::span_handler,
236 interner: @mut HashMap<intern_key, ~t_box_>,
238 cstore: @mut metadata::cstore::CStore,
239 sess: session::Session,
240 def_map: resolve::DefMap,
242 region_maps: @mut middle::region::RegionMaps,
243 region_paramd_items: middle::region::region_paramd_items,
245 // Stores the types for various nodes in the AST. Note that this table
246 // is not guaranteed to be populated until after typeck. See
247 // typeck::check::fn_ctxt for details.
248 node_types: node_type_table,
250 // Stores the type parameters which were substituted to obtain the type
251 // of this node. This only applies to nodes that refer to entities
252 // parameterized by type parameters, such as generic fns, types, or
254 node_type_substs: @mut HashMap<NodeId, ~[t]>,
256 // Maps from a method to the method "descriptor"
257 methods: @mut HashMap<def_id, @Method>,
259 // Maps from a trait def-id to a list of the def-ids of its methods
260 trait_method_def_ids: @mut HashMap<def_id, @~[def_id]>,
262 // A cache for the trait_methods() routine
263 trait_methods_cache: @mut HashMap<def_id, @~[@Method]>,
265 impl_trait_cache: @mut HashMap<ast::def_id, Option<@ty::TraitRef>>,
267 trait_refs: @mut HashMap<NodeId, @TraitRef>,
268 trait_defs: @mut HashMap<def_id, @TraitDef>,
271 intrinsic_defs: @mut HashMap<ast::def_id, t>,
272 freevars: freevars::freevar_map,
274 rcache: creader_cache,
275 ccache: constness_cache,
276 short_names_cache: @mut HashMap<t, @str>,
277 needs_unwind_cleanup_cache: @mut HashMap<t, bool>,
278 tc_cache: @mut HashMap<uint, TypeContents>,
279 ast_ty_to_ty_cache: @mut HashMap<NodeId, ast_ty_to_ty_cache_entry>,
280 enum_var_cache: @mut HashMap<def_id, @~[@VariantInfo]>,
281 ty_param_defs: @mut HashMap<ast::NodeId, TypeParameterDef>,
282 adjustments: @mut HashMap<ast::NodeId, @AutoAdjustment>,
283 normalized_cache: @mut HashMap<t, t>,
284 lang_items: middle::lang_items::LanguageItems,
285 // A mapping of fake provided method def_ids to the default implementation
286 provided_method_sources: @mut HashMap<ast::def_id, ast::def_id>,
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 list of impls of that trait.
299 trait_impls: @mut HashMap<ast::def_id, @mut ~[@Impl]>,
301 // Maps a def_id of a type to a list of its inherent impls.
302 // Contains implementations of methods that are inherent to a type.
303 // Methods in these implementations don't need to be exported.
304 inherent_impls: @mut HashMap<ast::def_id, @mut ~[@Impl]>,
306 // Maps a def_id of an impl to an Impl structure.
307 // Note that this contains all of the impls that we know about,
308 // including ones in other crates. It's not clear that this is the best
310 impls: @mut HashMap<ast::def_id, @Impl>,
312 // Set of used unsafe nodes (functions or blocks). Unsafe nodes not
313 // present in this set can be warned about.
314 used_unsafe: @mut HashSet<ast::NodeId>,
316 // Set of nodes which mark locals as mutable which end up getting used at
317 // some point. Local variable definitions not in this set can be warned
319 used_mut_nodes: @mut HashSet<ast::NodeId>,
321 // vtable resolution information for impl declarations
322 impl_vtables: typeck::impl_vtable_map
333 // a meta-flag: subst may be required if the type has parameters, a self
334 // type, or references bound regions
335 needs_subst = 1 | 2 | 8
338 pub type t_box = &'static t_box_;
346 // To reduce refcounting cost, we're representing types as unsafe pointers
347 // throughout the compiler. These are simply casted t_box values. Use ty::get
348 // to cast them back to a box. (Without the cast, compiler performance suffers
349 // ~15%.) This does mean that a t value relies on the ctxt to keep its box
350 // alive, and using ty::get is unsafe when the ctxt is no longer alive.
352 pub type t = *t_opaque;
355 fn to_str(&self) -> ~str {
360 pub fn get(t: t) -> t_box {
362 let t2: t_box = cast::transmute(t);
367 pub fn tbox_has_flag(tb: t_box, flag: tbox_flag) -> bool {
368 (tb.flags & (flag as uint)) != 0u
370 pub fn type_has_params(t: t) -> bool {
371 tbox_has_flag(get(t), has_params)
373 pub fn type_has_self(t: t) -> bool { tbox_has_flag(get(t), has_self) }
374 pub fn type_needs_infer(t: t) -> bool {
375 tbox_has_flag(get(t), needs_infer)
377 pub fn type_has_regions(t: t) -> bool {
378 tbox_has_flag(get(t), has_regions)
380 pub fn type_id(t: t) -> uint { get(t).id }
382 #[deriving(Clone, Eq, IterBytes)]
383 pub struct BareFnTy {
389 #[deriving(Clone, Eq, IterBytes)]
390 pub struct ClosureTy {
393 onceness: ast::Onceness,
395 bounds: BuiltinBounds,
400 * Signature of a function type, which I have arbitrarily
401 * decided to use to refer to the input/output types.
403 * - `lifetimes` is the list of region names bound in this fn.
404 * - `inputs` is the list of arguments and their modes.
405 * - `output` is the return type. */
406 #[deriving(Clone, Eq, IterBytes)]
408 bound_lifetime_names: OptVec<ast::ident>,
413 #[deriving(Clone, Eq, IterBytes)]
414 pub struct param_ty {
419 /// Representation of regions:
420 #[deriving(Clone, Eq, IterBytes, Encodable, Decodable, ToStr)]
422 /// Bound regions are found (primarily) in function types. They indicate
423 /// region parameters that have yet to be replaced with actual regions
424 /// (analogous to type parameters, except that due to the monomorphic
425 /// nature of our type system, bound type parameters are always replaced
426 /// with fresh type variables whenever an item is referenced, so type
427 /// parameters only appear "free" in types. Regions in contrast can
428 /// appear free or bound.). When a function is called, all bound regions
429 /// tied to that function's node-id are replaced with fresh region
430 /// variables whose value is then inferred.
431 re_bound(bound_region),
433 /// When checking a function body, the types of all arguments and so forth
434 /// that refer to bound region parameters are modified to refer to free
435 /// region parameters.
438 /// A concrete region naming some expression within the current function.
441 /// Static data that has an "infinite" lifetime. Top in the region lattice.
444 /// A region variable. Should not exist after typeck.
445 re_infer(InferRegion),
447 /// Empty lifetime is for data that is never accessed.
448 /// Bottom in the region lattice. We treat re_empty somewhat
449 /// specially; at least right now, we do not generate instances of
450 /// it during the GLB computations, but rather
451 /// generate an error instead. This is to improve error messages.
452 /// The only way to get an instance of re_empty is to have a region
453 /// variable with no constraints.
458 pub fn is_bound(&self) -> bool {
460 &re_bound(*) => true,
466 #[deriving(Clone, Eq, IterBytes, Encodable, Decodable, ToStr)]
467 pub struct FreeRegion {
469 bound_region: bound_region
472 #[deriving(Clone, Eq, IterBytes, Encodable, Decodable, ToStr)]
473 pub enum bound_region {
474 /// The self region for structs, impls (&T in a type defn or &'self T)
477 /// An anonymous region parameter for a given fn (&T)
480 /// Named region parameters for functions (a in &'a T)
481 br_named(ast::ident),
483 /// Fresh bound identifiers created during GLB computations.
487 * Handles capture-avoiding substitution in a rather subtle case. If you
488 * have a closure whose argument types are being inferred based on the
489 * expected type, and the expected type includes bound regions, then we
490 * will wrap those bound regions in a br_cap_avoid() with the id of the
491 * fn expression. This ensures that the names are not "captured" by the
492 * enclosing scope, which may define the same names. For an example of
493 * where this comes up, see src/test/compile-fail/regions-ret-borrowed.rs
494 * and regions-ret-borrowed-1.rs. */
495 br_cap_avoid(ast::NodeId, @bound_region),
499 * Represents the values to use when substituting lifetime parameters.
500 * If the value is `ErasedRegions`, then this subst is occurring during
501 * trans, and all region parameters will be replaced with `ty::re_static`. */
502 #[deriving(Clone, Eq, IterBytes)]
503 pub enum RegionSubsts {
505 NonerasedRegions(OptVec<ty::Region>)
509 * The type substs represents the kinds of things that can be substituted to
510 * convert a polytype into a monotype. Note however that substituting bound
511 * regions other than `self` is done through a different mechanism:
513 * - `tps` represents the type parameters in scope. They are indexed
514 * according to the order in which they were declared.
516 * - `self_r` indicates the region parameter `self` that is present on nominal
517 * types (enums, structs) declared as having a region parameter. `self_r`
518 * should always be none for types that are not region-parameterized and
519 * Some(_) for types that are. The only bound region parameter that should
520 * appear within a region-parameterized type is `self`.
522 * - `self_ty` is the type to which `self` should be remapped, if any. The
523 * `self` type is rather funny in that it can only appear on traits and is
524 * always substituted away to the implementing type for a trait. */
525 #[deriving(Clone, Eq, IterBytes)]
527 self_ty: Option<ty::t>,
529 regions: RegionSubsts,
537 macro_rules! def_prim_ty(
538 ($name:ident, $sty:expr, $id:expr) => (
539 pub static $name: t_box_ = t_box_ {
547 def_prim_ty!(TY_NIL, super::ty_nil, 0)
548 def_prim_ty!(TY_BOOL, super::ty_bool, 1)
549 def_prim_ty!(TY_INT, super::ty_int(ast::ty_i), 2)
550 def_prim_ty!(TY_CHAR, super::ty_int(ast::ty_char), 3)
551 def_prim_ty!(TY_I8, super::ty_int(ast::ty_i8), 4)
552 def_prim_ty!(TY_I16, super::ty_int(ast::ty_i16), 5)
553 def_prim_ty!(TY_I32, super::ty_int(ast::ty_i32), 6)
554 def_prim_ty!(TY_I64, super::ty_int(ast::ty_i64), 7)
555 def_prim_ty!(TY_UINT, super::ty_uint(ast::ty_u), 8)
556 def_prim_ty!(TY_U8, super::ty_uint(ast::ty_u8), 9)
557 def_prim_ty!(TY_U16, super::ty_uint(ast::ty_u16), 10)
558 def_prim_ty!(TY_U32, super::ty_uint(ast::ty_u32), 11)
559 def_prim_ty!(TY_U64, super::ty_uint(ast::ty_u64), 12)
560 def_prim_ty!(TY_FLOAT, super::ty_float(ast::ty_f), 13)
561 def_prim_ty!(TY_F32, super::ty_float(ast::ty_f32), 14)
562 def_prim_ty!(TY_F64, super::ty_float(ast::ty_f64), 15)
564 pub static TY_BOT: t_box_ = t_box_ {
567 flags: super::has_ty_bot as uint,
570 pub static TY_ERR: t_box_ = t_box_ {
573 flags: super::has_ty_err as uint,
576 pub static LAST_PRIMITIVE_ID: uint = 18;
579 // NB: If you change this, you'll probably want to change the corresponding
580 // AST structure in libsyntax/ast.rs as well.
581 #[deriving(Clone, Eq, IterBytes)]
587 ty_uint(ast::uint_ty),
588 ty_float(ast::float_ty),
590 ty_enum(def_id, substs),
596 ty_bare_fn(BareFnTy),
597 ty_closure(ClosureTy),
598 ty_trait(def_id, substs, TraitStore, ast::mutability, BuiltinBounds),
599 ty_struct(def_id, substs),
602 ty_param(param_ty), // type parameter
603 ty_self(def_id), /* special, implicit `self` type parameter;
604 * def_id is the id of the trait */
606 ty_infer(InferTy), // something used only during inference/typeck
607 ty_err, // Also only used during inference/typeck, to represent
608 // the type of an erroneous expression (helps cut down
609 // on non-useful type error messages)
611 // "Fake" types, used for trans purposes
612 ty_type, // type_desc*
613 ty_opaque_box, // used by monomorphizer to represent any @ box
614 ty_opaque_closure_ptr(Sigil), // ptr to env for &fn, @fn, ~fn
618 #[deriving(Eq, IterBytes)]
619 pub struct TraitRef {
624 #[deriving(Clone, Eq)]
625 pub enum IntVarValue {
626 IntType(ast::int_ty),
627 UintType(ast::uint_ty),
630 #[deriving(Clone, ToStr)]
631 pub enum terr_vstore_kind {
638 #[deriving(Clone, ToStr)]
639 pub struct expected_found<T> {
644 // Data structures used in type unification
645 #[deriving(Clone, ToStr)]
648 terr_purity_mismatch(expected_found<purity>),
649 terr_onceness_mismatch(expected_found<Onceness>),
650 terr_abi_mismatch(expected_found<AbiSet>),
652 terr_sigil_mismatch(expected_found<ast::Sigil>),
657 terr_tuple_size(expected_found<uint>),
658 terr_ty_param_size(expected_found<uint>),
659 terr_record_size(expected_found<uint>),
660 terr_record_mutability,
661 terr_record_fields(expected_found<ident>),
663 terr_regions_does_not_outlive(Region, Region),
664 terr_regions_not_same(Region, Region),
665 terr_regions_no_overlap(Region, Region),
666 terr_regions_insufficiently_polymorphic(bound_region, Region),
667 terr_regions_overly_polymorphic(bound_region, Region),
668 terr_vstores_differ(terr_vstore_kind, expected_found<vstore>),
669 terr_trait_stores_differ(terr_vstore_kind, expected_found<TraitStore>),
670 terr_in_field(@type_err, ast::ident),
671 terr_sorts(expected_found<t>),
672 terr_integer_as_char,
673 terr_int_mismatch(expected_found<IntVarValue>),
674 terr_float_mismatch(expected_found<ast::float_ty>),
675 terr_traits(expected_found<ast::def_id>),
676 terr_builtin_bounds(expected_found<BuiltinBounds>),
679 #[deriving(Eq, IterBytes)]
680 pub struct ParamBounds {
681 builtin_bounds: BuiltinBounds,
682 trait_bounds: ~[@TraitRef]
685 pub type BuiltinBounds = EnumSet<BuiltinBound>;
687 #[deriving(Clone, Eq, IterBytes, ToStr)]
688 pub enum BuiltinBound {
695 pub fn EmptyBuiltinBounds() -> BuiltinBounds {
699 pub fn AllBuiltinBounds() -> BuiltinBounds {
700 let mut set = EnumSet::empty();
701 set.add(BoundStatic);
703 set.add(BoundFreeze);
708 impl CLike for BuiltinBound {
709 pub fn to_uint(&self) -> uint {
712 pub fn from_uint(v: uint) -> BuiltinBound {
713 unsafe { cast::transmute(v) }
717 #[deriving(Clone, Eq, IterBytes)]
718 pub struct TyVid(uint);
720 #[deriving(Clone, Eq, IterBytes)]
721 pub struct IntVid(uint);
723 #[deriving(Clone, Eq, IterBytes)]
724 pub struct FloatVid(uint);
726 #[deriving(Clone, Eq, Encodable, Decodable, IterBytes)]
727 pub struct RegionVid {
731 #[deriving(Clone, Eq, IterBytes)]
738 #[deriving(Clone, Encodable, Decodable, IterBytes, ToStr)]
739 pub enum InferRegion {
741 ReSkolemized(uint, bound_region)
744 impl cmp::Eq for InferRegion {
745 fn eq(&self, other: &InferRegion) -> bool {
746 match ((*self), *other) {
747 (ReVar(rva), ReVar(rvb)) => {
750 (ReSkolemized(rva, _), ReSkolemized(rvb, _)) => {
756 fn ne(&self, other: &InferRegion) -> bool {
757 !((*self) == (*other))
762 fn to_uint(&self) -> uint;
766 fn to_uint(&self) -> uint { **self }
769 impl ToStr for TyVid {
770 fn to_str(&self) -> ~str { fmt!("<V%u>", self.to_uint()) }
773 impl Vid for IntVid {
774 fn to_uint(&self) -> uint { **self }
777 impl ToStr for IntVid {
778 fn to_str(&self) -> ~str { fmt!("<VI%u>", self.to_uint()) }
781 impl Vid for FloatVid {
782 fn to_uint(&self) -> uint { **self }
785 impl ToStr for FloatVid {
786 fn to_str(&self) -> ~str { fmt!("<VF%u>", self.to_uint()) }
789 impl Vid for RegionVid {
790 fn to_uint(&self) -> uint { self.id }
793 impl ToStr for RegionVid {
794 fn to_str(&self) -> ~str { fmt!("%?", self.id) }
797 impl ToStr for FnSig {
798 fn to_str(&self) -> ~str {
799 // grr, without tcx not much we can do.
804 impl ToStr for InferTy {
805 fn to_str(&self) -> ~str {
807 TyVar(ref v) => v.to_str(),
808 IntVar(ref v) => v.to_str(),
809 FloatVar(ref v) => v.to_str()
814 impl ToStr for IntVarValue {
815 fn to_str(&self) -> ~str {
817 IntType(ref v) => v.to_str(),
818 UintType(ref v) => v.to_str(),
824 pub struct TypeParameterDef {
830 /// Information about the type/lifetime parametesr associated with an item.
831 /// Analogous to ast::Generics.
833 pub struct Generics {
834 type_param_defs: @~[TypeParameterDef],
835 region_param: Option<region_variance>,
839 pub fn has_type_params(&self) -> bool {
840 !self.type_param_defs.is_empty()
846 /// - `bounds`: The list of bounds for each type parameter. The length of the
847 /// list also tells you how many type parameters there are.
849 /// - `rp`: true if the type is region-parameterized. Types can have at
850 /// most one region parameter, always called `&self`.
852 /// - `ty`: the base type. May have reference to the (unsubstituted) bound
853 /// region `&self` or to (unsubstituted) ty_param types
855 pub struct ty_param_bounds_and_ty {
860 /// As `ty_param_bounds_and_ty` but for a trait ref.
861 pub struct TraitDef {
863 trait_ref: @ty::TraitRef,
866 pub struct ty_param_substs_and_ty {
871 type type_cache = @mut HashMap<ast::def_id, ty_param_bounds_and_ty>;
873 type constness_cache = @mut HashMap<ast::def_id, const_eval::constness>;
875 pub type node_type_table = @mut HashMap<uint,t>;
877 fn mk_rcache() -> creader_cache {
878 return @mut HashMap::new();
881 pub fn new_ty_hash<V:'static>() -> @mut HashMap<t, V> {
885 pub fn mk_ctxt(s: session::Session,
888 freevars: freevars::freevar_map,
889 region_maps: @mut middle::region::RegionMaps,
890 region_paramd_items: middle::region::region_paramd_items,
891 lang_items: middle::lang_items::LanguageItems)
894 diag: s.diagnostic(),
895 interner: @mut HashMap::new(),
896 next_id: @mut primitives::LAST_PRIMITIVE_ID,
900 region_maps: region_maps,
901 region_paramd_items: region_paramd_items,
902 node_types: @mut HashMap::new(),
903 node_type_substs: @mut HashMap::new(),
904 trait_refs: @mut HashMap::new(),
905 trait_defs: @mut HashMap::new(),
907 intrinsic_defs: @mut HashMap::new(),
909 tcache: @mut HashMap::new(),
911 ccache: @mut HashMap::new(),
912 short_names_cache: new_ty_hash(),
913 needs_unwind_cleanup_cache: new_ty_hash(),
914 tc_cache: @mut HashMap::new(),
915 ast_ty_to_ty_cache: @mut HashMap::new(),
916 enum_var_cache: @mut HashMap::new(),
917 methods: @mut HashMap::new(),
918 trait_method_def_ids: @mut HashMap::new(),
919 trait_methods_cache: @mut HashMap::new(),
920 impl_trait_cache: @mut HashMap::new(),
921 ty_param_defs: @mut HashMap::new(),
922 adjustments: @mut HashMap::new(),
923 normalized_cache: new_ty_hash(),
924 lang_items: lang_items,
925 provided_method_sources: @mut HashMap::new(),
926 supertraits: @mut HashMap::new(),
927 destructor_for_type: @mut HashMap::new(),
928 destructors: @mut HashSet::new(),
929 trait_impls: @mut HashMap::new(),
930 inherent_impls: @mut HashMap::new(),
931 impls: @mut HashMap::new(),
932 used_unsafe: @mut HashSet::new(),
933 used_mut_nodes: @mut HashSet::new(),
934 impl_vtables: @mut HashMap::new(),
940 // Interns a type/name combination, stores the resulting box in cx.interner,
941 // and returns the box as cast to an unsafe ptr (see comments for t above).
942 fn mk_t(cx: ctxt, st: sty) -> t {
943 // Check for primitive types.
945 ty_nil => return mk_nil(),
946 ty_err => return mk_err(),
947 ty_bool => return mk_bool(),
948 ty_int(i) => return mk_mach_int(i),
949 ty_uint(u) => return mk_mach_uint(u),
950 ty_float(f) => return mk_mach_float(f),
954 let key = intern_key { sty: to_unsafe_ptr(&st) };
955 match cx.interner.find(&key) {
956 Some(t) => unsafe { return cast::transmute(&t.sty); },
961 fn rflags(r: Region) -> uint {
962 (has_regions as uint) | {
964 ty::re_infer(_) => needs_infer as uint,
969 fn sflags(substs: &substs) -> uint {
971 for tt in substs.tps.iter() { f |= get(*tt).flags; }
972 match substs.regions {
974 NonerasedRegions(ref regions) => {
975 for r in regions.iter() {
983 &ty_estr(vstore_slice(r)) => {
986 &ty_evec(ref mt, vstore_slice(r)) => {
988 flags |= get(mt.ty).flags;
990 &ty_nil | &ty_bool | &ty_int(_) | &ty_float(_) | &ty_uint(_) |
991 &ty_estr(_) | &ty_type | &ty_opaque_closure_ptr(_) |
992 &ty_opaque_box => (),
993 // You might think that we could just return ty_err for
994 // any type containing ty_err as a component, and get
995 // rid of the has_ty_err flag -- likewise for ty_bot (with
996 // the exception of function types that return bot).
997 // But doing so caused sporadic memory corruption, and
998 // neither I (tjc) nor nmatsakis could figure out why,
999 // so we're doing it this way.
1000 &ty_bot => flags |= has_ty_bot as uint,
1001 &ty_err => flags |= has_ty_err as uint,
1002 &ty_param(_) => flags |= has_params as uint,
1003 &ty_infer(_) => flags |= needs_infer as uint,
1004 &ty_self(_) => flags |= has_self as uint,
1005 &ty_enum(_, ref substs) | &ty_struct(_, ref substs) |
1006 &ty_trait(_, ref substs, _, _, _) => {
1007 flags |= sflags(substs);
1009 &ty_box(ref m) | &ty_uniq(ref m) | &ty_evec(ref m, _) |
1010 &ty_ptr(ref m) | &ty_unboxed_vec(ref m) => {
1011 flags |= get(m.ty).flags;
1013 &ty_rptr(r, ref m) => {
1015 flags |= get(m.ty).flags;
1017 &ty_tup(ref ts) => for tt in ts.iter() { flags |= get(*tt).flags; },
1018 &ty_bare_fn(ref f) => {
1019 for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
1020 flags |= get(f.sig.output).flags;
1021 // T -> _|_ is *not* _|_ !
1022 flags &= !(has_ty_bot as uint);
1024 &ty_closure(ref f) => {
1025 flags |= rflags(f.region);
1026 for a in f.sig.inputs.iter() { flags |= get(*a).flags; }
1027 flags |= get(f.sig.output).flags;
1028 // T -> _|_ is *not* _|_ !
1029 flags &= !(has_ty_bot as uint);
1039 let sty_ptr = to_unsafe_ptr(&t.sty);
1041 let key = intern_key {
1045 cx.interner.insert(key, t);
1050 cast::transmute::<*sty, t>(sty_ptr)
1055 pub fn mk_prim_t(primitive: &'static t_box_) -> t {
1057 cast::transmute::<&'static t_box_, t>(primitive)
1062 pub fn mk_nil() -> t { mk_prim_t(&primitives::TY_NIL) }
1065 pub fn mk_err() -> t { mk_prim_t(&primitives::TY_ERR) }
1068 pub fn mk_bot() -> t { mk_prim_t(&primitives::TY_BOT) }
1071 pub fn mk_bool() -> t { mk_prim_t(&primitives::TY_BOOL) }
1074 pub fn mk_int() -> t { mk_prim_t(&primitives::TY_INT) }
1077 pub fn mk_i8() -> t { mk_prim_t(&primitives::TY_I8) }
1080 pub fn mk_i16() -> t { mk_prim_t(&primitives::TY_I16) }
1083 pub fn mk_i32() -> t { mk_prim_t(&primitives::TY_I32) }
1086 pub fn mk_i64() -> t { mk_prim_t(&primitives::TY_I64) }
1089 pub fn mk_float() -> t { mk_prim_t(&primitives::TY_FLOAT) }
1092 pub fn mk_f32() -> t { mk_prim_t(&primitives::TY_F32) }
1095 pub fn mk_f64() -> t { mk_prim_t(&primitives::TY_F64) }
1098 pub fn mk_uint() -> t { mk_prim_t(&primitives::TY_UINT) }
1101 pub fn mk_u8() -> t { mk_prim_t(&primitives::TY_U8) }
1104 pub fn mk_u16() -> t { mk_prim_t(&primitives::TY_U16) }
1107 pub fn mk_u32() -> t { mk_prim_t(&primitives::TY_U32) }
1110 pub fn mk_u64() -> t { mk_prim_t(&primitives::TY_U64) }
1112 pub fn mk_mach_int(tm: ast::int_ty) -> t {
1114 ast::ty_i => mk_int(),
1115 ast::ty_char => mk_char(),
1116 ast::ty_i8 => mk_i8(),
1117 ast::ty_i16 => mk_i16(),
1118 ast::ty_i32 => mk_i32(),
1119 ast::ty_i64 => mk_i64(),
1123 pub fn mk_mach_uint(tm: ast::uint_ty) -> t {
1125 ast::ty_u => mk_uint(),
1126 ast::ty_u8 => mk_u8(),
1127 ast::ty_u16 => mk_u16(),
1128 ast::ty_u32 => mk_u32(),
1129 ast::ty_u64 => mk_u64(),
1133 pub fn mk_mach_float(tm: ast::float_ty) -> t {
1135 ast::ty_f => mk_float(),
1136 ast::ty_f32 => mk_f32(),
1137 ast::ty_f64 => mk_f64(),
1142 pub fn mk_char() -> t { mk_prim_t(&primitives::TY_CHAR) }
1144 pub fn mk_estr(cx: ctxt, t: vstore) -> t {
1145 mk_t(cx, ty_estr(t))
1148 pub fn mk_enum(cx: ctxt, did: ast::def_id, substs: substs) -> t {
1149 // take a copy of substs so that we own the vectors inside
1150 mk_t(cx, ty_enum(did, substs))
1153 pub fn mk_box(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_box(tm)) }
1155 pub fn mk_imm_box(cx: ctxt, ty: t) -> t {
1156 mk_box(cx, mt {ty: ty, mutbl: ast::m_imm})
1159 pub fn mk_uniq(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_uniq(tm)) }
1161 pub fn mk_imm_uniq(cx: ctxt, ty: t) -> t {
1162 mk_uniq(cx, mt {ty: ty, mutbl: ast::m_imm})
1165 pub fn mk_ptr(cx: ctxt, tm: mt) -> t { mk_t(cx, ty_ptr(tm)) }
1167 pub fn mk_rptr(cx: ctxt, r: Region, tm: mt) -> t { mk_t(cx, ty_rptr(r, tm)) }
1169 pub fn mk_mut_rptr(cx: ctxt, r: Region, ty: t) -> t {
1170 mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_mutbl})
1172 pub fn mk_imm_rptr(cx: ctxt, r: Region, ty: t) -> t {
1173 mk_rptr(cx, r, mt {ty: ty, mutbl: ast::m_imm})
1176 pub fn mk_mut_ptr(cx: ctxt, ty: t) -> t {
1177 mk_ptr(cx, mt {ty: ty, mutbl: ast::m_mutbl})
1180 pub fn mk_imm_ptr(cx: ctxt, ty: t) -> t {
1181 mk_ptr(cx, mt {ty: ty, mutbl: ast::m_imm})
1184 pub fn mk_nil_ptr(cx: ctxt) -> t {
1185 mk_ptr(cx, mt {ty: mk_nil(), mutbl: ast::m_imm})
1188 pub fn mk_evec(cx: ctxt, tm: mt, t: vstore) -> t {
1189 mk_t(cx, ty_evec(tm, t))
1192 pub fn mk_unboxed_vec(cx: ctxt, tm: mt) -> t {
1193 mk_t(cx, ty_unboxed_vec(tm))
1195 pub fn mk_mut_unboxed_vec(cx: ctxt, ty: t) -> t {
1196 mk_t(cx, ty_unboxed_vec(mt {ty: ty, mutbl: ast::m_imm}))
1199 pub fn mk_tup(cx: ctxt, ts: ~[t]) -> t { mk_t(cx, ty_tup(ts)) }
1201 pub fn mk_closure(cx: ctxt, fty: ClosureTy) -> t {
1202 mk_t(cx, ty_closure(fty))
1205 pub fn mk_bare_fn(cx: ctxt, fty: BareFnTy) -> t {
1206 mk_t(cx, ty_bare_fn(fty))
1209 pub fn mk_ctor_fn(cx: ctxt, input_tys: &[ty::t], output: ty::t) -> t {
1210 let input_args = input_tys.map(|t| *t);
1213 purity: ast::impure_fn,
1214 abis: AbiSet::Rust(),
1216 bound_lifetime_names: opt_vec::Empty,
1224 pub fn mk_trait(cx: ctxt,
1228 mutability: ast::mutability,
1229 bounds: BuiltinBounds)
1231 // take a copy of substs so that we own the vectors inside
1232 mk_t(cx, ty_trait(did, substs, store, mutability, bounds))
1235 pub fn mk_struct(cx: ctxt, struct_id: ast::def_id, substs: substs) -> t {
1236 // take a copy of substs so that we own the vectors inside
1237 mk_t(cx, ty_struct(struct_id, substs))
1240 pub fn mk_var(cx: ctxt, v: TyVid) -> t { mk_infer(cx, TyVar(v)) }
1242 pub fn mk_int_var(cx: ctxt, v: IntVid) -> t { mk_infer(cx, IntVar(v)) }
1244 pub fn mk_float_var(cx: ctxt, v: FloatVid) -> t { mk_infer(cx, FloatVar(v)) }
1246 pub fn mk_infer(cx: ctxt, it: InferTy) -> t { mk_t(cx, ty_infer(it)) }
1248 pub fn mk_self(cx: ctxt, did: ast::def_id) -> t { mk_t(cx, ty_self(did)) }
1250 pub fn mk_param(cx: ctxt, n: uint, k: def_id) -> t {
1251 mk_t(cx, ty_param(param_ty { idx: n, def_id: k }))
1254 pub fn mk_type(cx: ctxt) -> t { mk_t(cx, ty_type) }
1256 pub fn mk_opaque_closure_ptr(cx: ctxt, sigil: ast::Sigil) -> t {
1257 mk_t(cx, ty_opaque_closure_ptr(sigil))
1260 pub fn mk_opaque_box(cx: ctxt) -> t { mk_t(cx, ty_opaque_box) }
1262 pub fn walk_ty(ty: t, f: &fn(t)) {
1263 maybe_walk_ty(ty, |t| { f(t); true });
1266 pub fn maybe_walk_ty(ty: t, f: &fn(t) -> bool) {
1271 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1272 ty_estr(_) | ty_type | ty_opaque_box | ty_self(_) |
1273 ty_opaque_closure_ptr(_) | ty_infer(_) | ty_param(_) | ty_err => {
1275 ty_box(ref tm) | ty_evec(ref tm, _) | ty_unboxed_vec(ref tm) |
1276 ty_ptr(ref tm) | ty_rptr(_, ref tm) | ty_uniq(ref tm) => {
1277 maybe_walk_ty(tm.ty, f);
1279 ty_enum(_, ref substs) | ty_struct(_, ref substs) |
1280 ty_trait(_, ref substs, _, _, _) => {
1281 for subty in (*substs).tps.iter() { maybe_walk_ty(*subty, |x| f(x)); }
1283 ty_tup(ref ts) => { for tt in ts.iter() { maybe_walk_ty(*tt, |x| f(x)); } }
1284 ty_bare_fn(ref ft) => {
1285 for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
1286 maybe_walk_ty(ft.sig.output, f);
1288 ty_closure(ref ft) => {
1289 for a in ft.sig.inputs.iter() { maybe_walk_ty(*a, |x| f(x)); }
1290 maybe_walk_ty(ft.sig.output, f);
1295 pub fn fold_sty_to_ty(tcx: ty::ctxt, sty: &sty, foldop: &fn(t) -> t) -> t {
1296 mk_t(tcx, fold_sty(sty, foldop))
1299 pub fn fold_sig(sig: &FnSig, fldop: &fn(t) -> t) -> FnSig {
1300 let args = sig.inputs.map(|arg| fldop(*arg));
1303 bound_lifetime_names: sig.bound_lifetime_names.clone(),
1305 output: fldop(sig.output)
1309 pub fn fold_bare_fn_ty(fty: &BareFnTy, fldop: &fn(t) -> t) -> BareFnTy {
1310 BareFnTy {sig: fold_sig(&fty.sig, fldop),
1315 fn fold_sty(sty: &sty, fldop: &fn(t) -> t) -> sty {
1316 fn fold_substs(substs: &substs, fldop: &fn(t) -> t) -> substs {
1317 substs {regions: substs.regions.clone(),
1318 self_ty: substs.self_ty.map(|t| fldop(*t)),
1319 tps: substs.tps.map(|t| fldop(*t))}
1324 ty_box(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1326 ty_uniq(ref tm) => {
1327 ty_uniq(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1330 ty_ptr(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1332 ty_unboxed_vec(ref tm) => {
1333 ty_unboxed_vec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1335 ty_evec(ref tm, vst) => {
1336 ty_evec(mt {ty: fldop(tm.ty), mutbl: tm.mutbl}, vst)
1338 ty_enum(tid, ref substs) => {
1339 ty_enum(tid, fold_substs(substs, fldop))
1341 ty_trait(did, ref substs, st, mutbl, bounds) => {
1342 ty_trait(did, fold_substs(substs, fldop), st, mutbl, bounds)
1345 let new_ts = ts.map(|tt| fldop(*tt));
1348 ty_bare_fn(ref f) => {
1349 ty_bare_fn(fold_bare_fn_ty(f, fldop))
1351 ty_closure(ref f) => {
1352 let sig = fold_sig(&f.sig, fldop);
1353 ty_closure(ClosureTy {
1357 onceness: f.onceness,
1362 ty_rptr(r, ref tm) => {
1363 ty_rptr(r, mt {ty: fldop(tm.ty), mutbl: tm.mutbl})
1365 ty_struct(did, ref substs) => {
1366 ty_struct(did, fold_substs(substs, fldop))
1368 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1369 ty_estr(_) | ty_type | ty_opaque_closure_ptr(_) | ty_err |
1370 ty_opaque_box | ty_infer(_) | ty_param(*) | ty_self(_) => {
1376 // Folds types from the bottom up.
1377 pub fn fold_ty(cx: ctxt, t0: t, fldop: &fn(t) -> t) -> t {
1378 let sty = fold_sty(&get(t0).sty, |t| fold_ty(cx, fldop(t), |t| fldop(t)));
1379 fldop(mk_t(cx, sty))
1382 pub fn walk_regions_and_ty(
1385 walkr: &fn(r: Region),
1386 walkt: &fn(t: t) -> bool) {
1389 fold_regions_and_ty(
1391 |r| { walkr(r); r },
1392 |t| { walk_regions_and_ty(cx, t, |r| walkr(r), |t| walkt(t)); t },
1393 |t| { walk_regions_and_ty(cx, t, |r| walkr(r), |t| walkt(t)); t });
1397 pub fn fold_regions_and_ty(
1400 fldr: &fn(r: Region) -> Region,
1401 fldfnt: &fn(t: t) -> t,
1402 fldt: &fn(t: t) -> t) -> t {
1406 fldr: &fn(r: Region) -> Region,
1407 fldt: &fn(t: t) -> t)
1409 let regions = match substs.regions {
1410 ErasedRegions => ErasedRegions,
1411 NonerasedRegions(ref regions) => {
1412 NonerasedRegions(regions.map(|r| fldr(*r)))
1418 self_ty: substs.self_ty.map(|t| fldt(*t)),
1419 tps: substs.tps.map(|t| fldt(*t))
1423 let tb = ty::get(ty);
1425 ty::ty_rptr(r, mt) => {
1427 let m_t = fldt(mt.ty);
1428 ty::mk_rptr(cx, m_r, mt {ty: m_t, mutbl: mt.mutbl})
1430 ty_estr(vstore_slice(r)) => {
1432 ty::mk_estr(cx, vstore_slice(m_r))
1434 ty_evec(mt, vstore_slice(r)) => {
1436 let m_t = fldt(mt.ty);
1437 ty::mk_evec(cx, mt {ty: m_t, mutbl: mt.mutbl}, vstore_slice(m_r))
1439 ty_enum(def_id, ref substs) => {
1440 ty::mk_enum(cx, def_id, fold_substs(substs, fldr, fldt))
1442 ty_struct(def_id, ref substs) => {
1443 ty::mk_struct(cx, def_id, fold_substs(substs, fldr, fldt))
1445 ty_trait(def_id, ref substs, st, mutbl, bounds) => {
1447 RegionTraitStore(region) => RegionTraitStore(fldr(region)),
1450 ty::mk_trait(cx, def_id, fold_substs(substs, fldr, fldt), st, mutbl, bounds)
1452 ty_bare_fn(ref f) => {
1453 ty::mk_bare_fn(cx, BareFnTy {
1454 sig: fold_sig(&f.sig, fldfnt),
1456 abis: f.abis.clone(),
1459 ty_closure(ref f) => {
1460 ty::mk_closure(cx, ClosureTy {
1461 region: fldr(f.region),
1462 sig: fold_sig(&f.sig, fldfnt),
1465 onceness: f.onceness,
1470 fold_sty_to_ty(cx, sty, |t| fldt(t))
1475 // n.b. this function is intended to eventually replace fold_region() below,
1476 // that is why its name is so similar.
1477 pub fn fold_regions(
1480 fldr: &fn(r: Region, in_fn: bool) -> Region) -> t {
1481 fn do_fold(cx: ctxt, ty: t, in_fn: bool,
1482 fldr: &fn(Region, bool) -> Region) -> t {
1483 debug!("do_fold(ty=%s, in_fn=%b)", ty_to_str(cx, ty), in_fn);
1484 if !type_has_regions(ty) { return ty; }
1485 fold_regions_and_ty(
1488 |t| do_fold(cx, t, true, |r,b| fldr(r,b)),
1489 |t| do_fold(cx, t, in_fn, |r,b| fldr(r,b)))
1491 do_fold(cx, ty, false, fldr)
1494 // Substitute *only* type parameters. Used in trans where regions are erased.
1495 pub fn subst_tps(cx: ctxt, tps: &[t], self_ty_opt: Option<t>, typ: t) -> t {
1496 if tps.len() == 0u && self_ty_opt.is_none() { return typ; }
1497 let tb = ty::get(typ);
1498 if self_ty_opt.is_none() && !tbox_has_flag(tb, has_params) { return typ; }
1500 ty_param(p) => tps[p.idx],
1503 None => cx.sess.bug("ty_self unexpected here"),
1505 subst_tps(cx, tps, self_ty_opt, self_ty)
1510 fold_sty_to_ty(cx, sty, |t| subst_tps(cx, tps, self_ty_opt, t))
1515 pub fn substs_is_noop(substs: &substs) -> bool {
1516 let regions_is_noop = match substs.regions {
1517 ErasedRegions => false, // may be used to canonicalize
1518 NonerasedRegions(ref regions) => regions.is_empty()
1521 substs.tps.len() == 0u &&
1523 substs.self_ty.is_none()
1526 pub fn substs_to_str(cx: ctxt, substs: &substs) -> ~str {
1530 pub fn subst(cx: ctxt,
1534 typ.subst(cx, substs)
1539 pub fn type_is_nil(ty: t) -> bool { get(ty).sty == ty_nil }
1541 pub fn type_is_bot(ty: t) -> bool {
1542 (get(ty).flags & (has_ty_bot as uint)) != 0
1545 pub fn type_is_error(ty: t) -> bool {
1546 (get(ty).flags & (has_ty_err as uint)) != 0
1549 pub fn type_needs_subst(ty: t) -> bool {
1550 tbox_has_flag(get(ty), needs_subst)
1553 pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
1554 tref.substs.self_ty.iter().any(|&t| type_is_error(t)) ||
1555 tref.substs.tps.iter().any(|&t| type_is_error(t))
1558 pub fn type_is_ty_var(ty: t) -> bool {
1560 ty_infer(TyVar(_)) => true,
1565 pub fn type_is_bool(ty: t) -> bool { get(ty).sty == ty_bool }
1567 pub fn type_is_self(ty: t) -> bool {
1574 pub fn type_is_structural(ty: t) -> bool {
1576 ty_struct(*) | ty_tup(_) | ty_enum(*) | ty_closure(_) | ty_trait(*) |
1577 ty_evec(_, vstore_fixed(_)) | ty_estr(vstore_fixed(_)) |
1578 ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_))
1584 pub fn type_is_sequence(ty: t) -> bool {
1586 ty_estr(_) | ty_evec(_, _) => true,
1591 pub fn type_is_simd(cx: ctxt, ty: t) -> bool {
1593 ty_struct(did, _) => lookup_simd(cx, did),
1598 pub fn type_is_str(ty: t) -> bool {
1605 pub fn sequence_element_type(cx: ctxt, ty: t) -> t {
1607 ty_estr(_) => return mk_mach_uint(ast::ty_u8),
1608 ty_evec(mt, _) | ty_unboxed_vec(mt) => return mt.ty,
1609 _ => cx.sess.bug("sequence_element_type called on non-sequence value"),
1613 pub fn simd_type(cx: ctxt, ty: t) -> t {
1615 ty_struct(did, ref substs) => {
1616 let fields = lookup_struct_fields(cx, did);
1617 lookup_field_type(cx, did, fields[0].id, substs)
1619 _ => fail!("simd_type called on invalid type")
1623 pub fn simd_size(cx: ctxt, ty: t) -> uint {
1625 ty_struct(did, _) => {
1626 let fields = lookup_struct_fields(cx, did);
1629 _ => fail!("simd_size called on invalid type")
1633 pub fn get_element_type(ty: t, i: uint) -> t {
1635 ty_tup(ref ts) => return ts[i],
1636 _ => fail!("get_element_type called on invalid type")
1640 pub fn type_is_box(ty: t) -> bool {
1642 ty_box(_) => return true,
1647 pub fn type_is_boxed(ty: t) -> bool {
1649 ty_box(_) | ty_opaque_box |
1650 ty_evec(_, vstore_box) | ty_estr(vstore_box) => true,
1655 pub fn type_is_region_ptr(ty: t) -> bool {
1657 ty_rptr(_, _) => true,
1662 pub fn type_is_slice(ty: t) -> bool {
1664 ty_evec(_, vstore_slice(_)) | ty_estr(vstore_slice(_)) => true,
1669 pub fn type_is_unique_box(ty: t) -> bool {
1671 ty_uniq(_) => return true,
1676 pub fn type_is_unsafe_ptr(ty: t) -> bool {
1678 ty_ptr(_) => return true,
1683 pub fn type_is_vec(ty: t) -> bool {
1684 return match get(ty).sty {
1685 ty_evec(_, _) | ty_unboxed_vec(_) => true,
1691 pub fn type_is_unique(ty: t) -> bool {
1694 ty_evec(_, vstore_uniq) |
1695 ty_estr(vstore_uniq) |
1696 ty_opaque_closure_ptr(ast::OwnedSigil) => true,
1702 A scalar type is one that denotes an atomic datum, with no sub-components.
1703 (A ty_ptr is scalar because it represents a non-managed pointer, so its
1704 contents are abstract to rustc.)
1706 pub fn type_is_scalar(ty: t) -> bool {
1708 ty_nil | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
1709 ty_infer(IntVar(_)) | ty_infer(FloatVar(_)) | ty_type |
1710 ty_bare_fn(*) | ty_ptr(_) => true,
1715 fn type_is_newtype_immediate(cx: ctxt, ty: t) -> bool {
1717 ty_struct(def_id, ref substs) => {
1718 let fields = struct_fields(cx, def_id, substs);
1719 fields.len() == 1 &&
1720 fields[0].ident == token::special_idents::unnamed_field &&
1721 type_is_immediate(cx, fields[0].mt.ty)
1727 pub fn type_is_immediate(cx: ctxt, ty: t) -> bool {
1728 return type_is_scalar(ty) || type_is_boxed(ty) ||
1729 type_is_unique(ty) || type_is_region_ptr(ty) ||
1730 type_is_newtype_immediate(cx, ty) ||
1731 type_is_simd(cx, ty);
1734 pub fn type_needs_drop(cx: ctxt, ty: t) -> bool {
1735 type_contents(cx, ty).needs_drop(cx)
1738 // Some things don't need cleanups during unwinding because the
1739 // task can free them all at once later. Currently only things
1740 // that only contain scalars and shared boxes can avoid unwind
1742 pub fn type_needs_unwind_cleanup(cx: ctxt, ty: t) -> bool {
1743 match cx.needs_unwind_cleanup_cache.find(&ty) {
1744 Some(&result) => return result,
1748 let mut tycache = HashSet::new();
1749 let needs_unwind_cleanup =
1750 type_needs_unwind_cleanup_(cx, ty, &mut tycache, false);
1751 cx.needs_unwind_cleanup_cache.insert(ty, needs_unwind_cleanup);
1752 return needs_unwind_cleanup;
1755 fn type_needs_unwind_cleanup_(cx: ctxt, ty: t,
1756 tycache: &mut HashSet<t>,
1757 encountered_box: bool) -> bool {
1759 // Prevent infinite recursion
1760 if !tycache.insert(ty) {
1764 let mut encountered_box = encountered_box;
1765 let mut needs_unwind_cleanup = false;
1766 do maybe_walk_ty(ty) |ty| {
1767 let old_encountered_box = encountered_box;
1768 let result = match get(ty).sty {
1769 ty_box(_) | ty_opaque_box => {
1770 encountered_box = true;
1773 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
1774 ty_tup(_) | ty_ptr(_) => {
1777 ty_enum(did, ref substs) => {
1778 for v in (*enum_variants(cx, did)).iter() {
1779 for aty in v.args.iter() {
1780 let t = subst(cx, substs, *aty);
1781 needs_unwind_cleanup |=
1782 type_needs_unwind_cleanup_(cx, t, tycache,
1786 !needs_unwind_cleanup
1789 ty_estr(vstore_uniq) |
1790 ty_estr(vstore_box) |
1791 ty_evec(_, vstore_uniq) |
1792 ty_evec(_, vstore_box)
1794 // Once we're inside a box, the annihilator will find
1795 // it and destroy it.
1796 if !encountered_box {
1797 needs_unwind_cleanup = true;
1804 needs_unwind_cleanup = true;
1809 encountered_box = old_encountered_box;
1813 return needs_unwind_cleanup;
1817 * Type contents is how the type checker reasons about kinds.
1818 * They track what kinds of things are found within a type. You can
1819 * think of them as kind of an "anti-kind". They track the kinds of values
1820 * and thinks that are contained in types. Having a larger contents for
1821 * a type tends to rule that type *out* from various kinds. For example,
1822 * a type that contains a borrowed pointer is not sendable.
1824 * The reason we compute type contents and not kinds is that it is
1825 * easier for me (nmatsakis) to think about what is contained within
1826 * a type than to think about what is *not* contained within a type.
1828 pub struct TypeContents {
1833 pub fn meets_bounds(&self, cx: ctxt, bbs: BuiltinBounds) -> bool {
1834 bbs.iter().all(|bb| self.meets_bound(cx, bb))
1837 pub fn meets_bound(&self, cx: ctxt, bb: BuiltinBound) -> bool {
1839 BoundStatic => self.is_static(cx),
1840 BoundFreeze => self.is_freezable(cx),
1841 BoundSend => self.is_sendable(cx),
1842 BoundSized => self.is_sized(cx),
1846 pub fn intersects(&self, tc: TypeContents) -> bool {
1847 (self.bits & tc.bits) != 0
1850 pub fn noncopyable(_cx: ctxt) -> TypeContents {
1851 TC_DTOR + TC_BORROWED_MUT + TC_ONCE_CLOSURE + TC_NONCOPY_TRAIT +
1855 pub fn is_static(&self, cx: ctxt) -> bool {
1856 !self.intersects(TypeContents::nonstatic(cx))
1859 pub fn nonstatic(_cx: ctxt) -> TypeContents {
1863 pub fn is_sendable(&self, cx: ctxt) -> bool {
1864 !self.intersects(TypeContents::nonsendable(cx))
1867 pub fn nonsendable(_cx: ctxt) -> TypeContents {
1868 TC_MANAGED + TC_BORROWED_POINTER + TC_NON_SENDABLE
1871 pub fn contains_managed(&self) -> bool {
1872 self.intersects(TC_MANAGED)
1875 pub fn is_freezable(&self, cx: ctxt) -> bool {
1876 !self.intersects(TypeContents::nonfreezable(cx))
1879 pub fn nonfreezable(_cx: ctxt) -> TypeContents {
1883 pub fn is_sized(&self, cx: ctxt) -> bool {
1884 !self.intersects(TypeContents::dynamically_sized(cx))
1887 pub fn dynamically_sized(_cx: ctxt) -> TypeContents {
1891 pub fn moves_by_default(&self, cx: ctxt) -> bool {
1892 self.intersects(TypeContents::nonimplicitly_copyable(cx))
1895 pub fn nonimplicitly_copyable(cx: ctxt) -> TypeContents {
1896 TypeContents::noncopyable(cx) + TC_OWNED_POINTER + TC_OWNED_VEC
1899 pub fn needs_drop(&self, cx: ctxt) -> bool {
1900 if self.intersects(TC_NONCOPY_TRAIT) {
1901 // Currently all noncopyable existentials are 2nd-class types
1902 // behind owned pointers. With dynamically-sized types, remove
1904 assert!(self.intersects(TC_OWNED_POINTER) ||
1905 // (...or stack closures without a copy bound.)
1906 self.intersects(TC_BORROWED_POINTER));
1908 let tc = TC_MANAGED + TC_DTOR + TypeContents::sendable(cx);
1912 pub fn sendable(_cx: ctxt) -> TypeContents {
1913 //! Any kind of sendable contents.
1914 TC_OWNED_POINTER + TC_OWNED_VEC
1918 impl ops::Add<TypeContents,TypeContents> for TypeContents {
1919 fn add(&self, other: &TypeContents) -> TypeContents {
1920 TypeContents {bits: self.bits | other.bits}
1924 impl ops::Sub<TypeContents,TypeContents> for TypeContents {
1925 fn sub(&self, other: &TypeContents) -> TypeContents {
1926 TypeContents {bits: self.bits & !other.bits}
1930 impl ToStr for TypeContents {
1931 fn to_str(&self) -> ~str {
1932 fmt!("TypeContents(%s)", u32::to_str_radix(self.bits, 2))
1936 /// Constant for a type containing nothing of interest.
1937 static TC_NONE: TypeContents = TypeContents{bits: 0b0000_0000_0000};
1939 /// Contains a borrowed value with a lifetime other than static
1940 static TC_BORROWED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0001};
1942 /// Contains an owned pointer (~T) but not slice of some kind
1943 static TC_OWNED_POINTER: TypeContents = TypeContents{bits: 0b0000_0000_0010};
1945 /// Contains an owned vector ~[] or owned string ~str
1946 static TC_OWNED_VEC: TypeContents = TypeContents{bits: 0b0000_0000_0100};
1948 /// Contains a non-copyable ~fn() or a ~Trait (NOT a ~fn:Copy() or ~Trait:Copy).
1949 static TC_NONCOPY_TRAIT: TypeContents = TypeContents{bits: 0b0000_0000_1000};
1951 /// Type with a destructor
1952 static TC_DTOR: TypeContents = TypeContents{bits: 0b0000_0001_0000};
1954 /// Contains a managed value
1955 static TC_MANAGED: TypeContents = TypeContents{bits: 0b0000_0010_0000};
1957 /// &mut with any region
1958 static TC_BORROWED_MUT: TypeContents = TypeContents{bits: 0b0000_0100_0000};
1960 /// Mutable content, whether owned or by ref
1961 static TC_MUTABLE: TypeContents = TypeContents{bits: 0b0000_1000_0000};
1963 /// One-shot closure
1964 static TC_ONCE_CLOSURE: TypeContents = TypeContents{bits: 0b0001_0000_0000};
1966 /// An enum with no variants.
1967 static TC_EMPTY_ENUM: TypeContents = TypeContents{bits: 0b0010_0000_0000};
1969 /// Contains a type marked with `#[no_send]`
1970 static TC_NON_SENDABLE: TypeContents = TypeContents{bits: 0b0100_0000_0000};
1972 /// Is a bare vector, str, function, trait, etc (only relevant at top level).
1973 static TC_DYNAMIC_SIZE: TypeContents = TypeContents{bits: 0b1000_0000_0000};
1975 /// All possible contents.
1976 static TC_ALL: TypeContents = TypeContents{bits: 0b1111_1111_1111};
1978 pub fn type_is_static(cx: ctxt, t: ty::t) -> bool {
1979 type_contents(cx, t).is_static(cx)
1982 pub fn type_is_sendable(cx: ctxt, t: ty::t) -> bool {
1983 type_contents(cx, t).is_sendable(cx)
1986 pub fn type_is_freezable(cx: ctxt, t: ty::t) -> bool {
1987 type_contents(cx, t).is_freezable(cx)
1990 pub fn type_contents(cx: ctxt, ty: t) -> TypeContents {
1991 let ty_id = type_id(ty);
1992 match cx.tc_cache.find(&ty_id) {
1993 Some(tc) => { return *tc; }
1997 let mut cache = HashMap::new();
1998 let result = tc_ty(cx, ty, &mut cache);
1999 cx.tc_cache.insert(ty_id, result);
2004 cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2006 // Subtle: Note that we are *not* using cx.tc_cache here but rather a
2007 // private cache for this walk. This is needed in the case of cyclic
2010 // struct List { next: ~Option<List>, ... }
2012 // When computing the type contents of such a type, we wind up deeply
2013 // recursing as we go. So when we encounter the recursive reference
2014 // to List, we temporarily use TC_NONE as its contents. Later we'll
2015 // patch up the cache with the correct value, once we've computed it
2016 // (this is basically a co-inductive process, if that helps). So in
2017 // the end we'll compute TC_OWNED_POINTER, in this case.
2019 // The problem is, as we are doing the computation, we will also
2020 // compute an *intermediate* contents for, e.g., Option<List> of
2021 // TC_NONE. This is ok during the computation of List itself, but if
2022 // we stored this intermediate value into cx.tc_cache, then later
2023 // requests for the contents of Option<List> would also yield TC_NONE
2024 // which is incorrect. This value was computed based on the crutch
2025 // value for the type contents of list. The correct value is
2026 // TC_OWNED_POINTER. This manifested as issue #4821.
2027 let ty_id = type_id(ty);
2028 match cache.find(&ty_id) {
2029 Some(tc) => { return *tc; }
2032 match cx.tc_cache.find(&ty_id) { // Must check both caches!
2033 Some(tc) => { return *tc; }
2036 cache.insert(ty_id, TC_NONE);
2038 let _i = indenter();
2040 let result = match get(ty).sty {
2041 // Scalar and unique types are sendable, freezable, and durable
2042 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_uint(_) | ty_float(_) |
2043 ty_bare_fn(_) | ty_ptr(_) => {
2047 ty_estr(vstore_uniq) => {
2051 ty_closure(ref c) => {
2057 statically_sized(nonsendable(tc_mt(cx, mt, cache)))
2060 ty_trait(_, _, store, mutbl, bounds) => {
2061 trait_contents(store, mutbl, bounds)
2065 borrowed_contents(r, mt.mutbl) +
2066 statically_sized(nonsendable(tc_mt(cx, mt, cache)))
2070 TC_OWNED_POINTER + statically_sized(tc_mt(cx, mt, cache))
2073 ty_evec(mt, vstore_uniq) => {
2074 TC_OWNED_VEC + statically_sized(tc_mt(cx, mt, cache))
2077 ty_evec(mt, vstore_box) => {
2079 statically_sized(nonsendable(tc_mt(cx, mt, cache)))
2082 ty_evec(mt, vstore_slice(r)) => {
2083 borrowed_contents(r, mt.mutbl) +
2084 statically_sized(nonsendable(tc_mt(cx, mt, cache)))
2087 ty_evec(mt, vstore_fixed(_)) => {
2088 let contents = tc_mt(cx, mt, cache);
2089 // FIXME(#6308) Uncomment this when construction of such
2090 // vectors is prevented earlier in compilation.
2091 // if !contents.is_sized(cx) {
2092 // cx.sess.bug("Fixed-length vector of unsized type \
2093 // should be impossible");
2098 ty_estr(vstore_box) => {
2102 ty_estr(vstore_slice(r)) => {
2103 borrowed_contents(r, m_imm)
2106 ty_estr(vstore_fixed(_)) => {
2110 ty_struct(did, ref substs) => {
2111 let flds = struct_fields(cx, did, substs);
2112 let mut res = flds.iter().fold(
2114 |tc, f| tc + tc_mt(cx, f.mt, cache));
2115 if ty::has_dtor(cx, did) {
2116 res = res + TC_DTOR;
2118 apply_tc_attr(cx, did, res)
2121 ty_tup(ref tys) => {
2122 tys.iter().fold(TC_NONE, |tc, ty| tc + tc_ty(cx, *ty, cache))
2125 ty_enum(did, ref substs) => {
2126 let variants = substd_enum_variants(cx, did, substs);
2127 let res = if variants.is_empty() {
2128 // we somewhat arbitrary declare that empty enums
2132 variants.iter().fold(TC_NONE, |tc, variant| {
2133 variant.args.iter().fold(tc,
2134 |tc, arg_ty| tc + tc_ty(cx, *arg_ty, cache))
2137 apply_tc_attr(cx, did, res)
2141 // We only ever ask for the kind of types that are defined in
2142 // the current crate; therefore, the only type parameters that
2143 // could be in scope are those defined in the current crate.
2144 // If this assertion failures, it is likely because of a
2145 // failure in the cross-crate inlining code to translate a
2147 assert_eq!(p.def_id.crate, ast::LOCAL_CRATE);
2149 type_param_def_to_contents(
2150 cx, cx.ty_param_defs.get(&p.def_id.node))
2154 // Currently, self is not bounded, so we must assume the
2155 // worst. But in the future we should examine the super
2158 // FIXME(#4678)---self should just be a ty param
2163 // This occurs during coherence, but shouldn't occur at other
2168 ty_opaque_box => TC_MANAGED,
2169 ty_unboxed_vec(mt) => TC_DYNAMIC_SIZE + tc_mt(cx, mt, cache),
2170 ty_opaque_closure_ptr(sigil) => {
2172 ast::BorrowedSigil => TC_BORROWED_POINTER,
2173 ast::ManagedSigil => TC_MANAGED,
2174 // FIXME(#3569): Looks like noncopyability should depend
2175 // on the bounds, but I don't think this case ever comes up.
2176 ast::OwnedSigil => TC_NONCOPY_TRAIT + TC_OWNED_POINTER,
2183 cx.sess.bug("Asked to compute contents of fictitious type");
2187 cache.insert(ty_id, result);
2193 cache: &mut HashMap<uint, TypeContents>) -> TypeContents
2195 let mc = if mt.mutbl == m_mutbl {TC_MUTABLE} else {TC_NONE};
2196 mc + tc_ty(cx, mt.ty, cache)
2199 fn apply_tc_attr(cx: ctxt, did: def_id, mut tc: TypeContents) -> TypeContents {
2200 if has_attr(cx, did, "no_freeze") {
2201 tc = tc + TC_MUTABLE;
2203 if has_attr(cx, did, "no_send") {
2204 tc = tc + TC_NON_SENDABLE;
2209 fn borrowed_contents(region: ty::Region,
2210 mutbl: ast::mutability) -> TypeContents
2212 let mc = if mutbl == m_mutbl {
2213 TC_MUTABLE + TC_BORROWED_MUT
2217 let rc = if region != ty::re_static {
2225 fn nonsendable(pointee: TypeContents) -> TypeContents {
2228 * Given a non-owning pointer to some type `T` with
2229 * contents `pointee` (like `@T` or
2230 * `&T`), returns the relevant bits that
2231 * apply to the owner of the pointer.
2234 let mask = TC_MUTABLE.bits | TC_BORROWED_POINTER.bits;
2235 TypeContents {bits: pointee.bits & mask}
2238 fn statically_sized(pointee: TypeContents) -> TypeContents {
2240 * If a dynamically-sized type is found behind a pointer, we should
2241 * restore the 'Sized' kind to the pointer and things that contain it.
2243 TypeContents {bits: pointee.bits & !TC_DYNAMIC_SIZE.bits}
2246 fn closure_contents(cty: &ClosureTy) -> TypeContents {
2247 // Closure contents are just like trait contents, but with potentially
2249 let st = match cty.sigil {
2250 ast::BorrowedSigil =>
2251 trait_contents(RegionTraitStore(cty.region), m_imm, cty.bounds)
2252 + TC_BORROWED_POINTER, // might be an env packet even if static
2253 ast::ManagedSigil =>
2254 trait_contents(BoxTraitStore, m_imm, cty.bounds),
2256 trait_contents(UniqTraitStore, m_imm, cty.bounds),
2258 // FIXME(#3569): This borrowed_contents call should be taken care of in
2259 // trait_contents, after ~Traits and @Traits can have region bounds too.
2260 // This one here is redundant for &fns but important for ~fns and @fns.
2261 let rt = borrowed_contents(cty.region, m_imm);
2262 // This also prohibits "@once fn" from being copied, which allows it to
2263 // be called. Neither way really makes much sense.
2264 let ot = match cty.onceness {
2265 ast::Once => TC_ONCE_CLOSURE,
2266 ast::Many => TC_NONE
2268 // Prevent noncopyable types captured in the environment from being copied.
2269 let ct = if cty.sigil == ast::ManagedSigil {
2277 fn trait_contents(store: TraitStore, mutbl: ast::mutability,
2278 bounds: BuiltinBounds) -> TypeContents {
2279 let st = match store {
2280 UniqTraitStore => TC_OWNED_POINTER,
2281 BoxTraitStore => TC_MANAGED,
2282 RegionTraitStore(r) => borrowed_contents(r, mutbl),
2284 let mt = match mutbl { ast::m_mutbl => TC_MUTABLE, _ => TC_NONE };
2285 // We get additional "special type contents" for each bound that *isn't*
2286 // on the trait. So iterate over the inverse of the bounds that are set.
2287 // This is like with typarams below, but less "pessimistic" and also
2288 // dependent on the trait store.
2289 let mut bt = TC_NONE;
2290 do (AllBuiltinBounds() - bounds).each |bound| {
2291 bt = bt + match bound {
2292 BoundStatic if bounds.contains_elem(BoundSend)
2293 => TC_NONE, // Send bound implies static bound.
2294 BoundStatic => TC_BORROWED_POINTER, // Useful for "@Trait:'static"
2295 BoundSend => TC_NON_SENDABLE,
2296 BoundFreeze => TC_MUTABLE,
2297 BoundSized => TC_NONE, // don't care if interior is sized
2304 fn type_param_def_to_contents(cx: ctxt,
2305 type_param_def: &TypeParameterDef) -> TypeContents
2307 debug!("type_param_def_to_contents(%s)", type_param_def.repr(cx));
2308 let _i = indenter();
2310 let mut tc = TC_ALL;
2311 do type_param_def.bounds.builtin_bounds.each |bound| {
2312 debug!("tc = %s, bound = %?", tc.to_str(), bound);
2313 tc = tc - match bound {
2314 BoundStatic => TypeContents::nonstatic(cx),
2315 BoundSend => TypeContents::nonsendable(cx),
2316 BoundFreeze => TypeContents::nonfreezable(cx),
2317 // The dynamic-size bit can be removed at pointer-level, etc.
2318 BoundSized => TypeContents::dynamically_sized(cx),
2323 debug!("result = %s", tc.to_str());
2328 pub fn type_moves_by_default(cx: ctxt, ty: t) -> bool {
2329 type_contents(cx, ty).moves_by_default(cx)
2332 // True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
2333 pub fn is_instantiable(cx: ctxt, r_ty: t) -> bool {
2334 fn type_requires(cx: ctxt, seen: &mut ~[def_id],
2335 r_ty: t, ty: t) -> bool {
2336 debug!("type_requires(%s, %s)?",
2337 ::util::ppaux::ty_to_str(cx, r_ty),
2338 ::util::ppaux::ty_to_str(cx, ty));
2341 get(r_ty).sty == get(ty).sty ||
2342 subtypes_require(cx, seen, r_ty, ty)
2345 debug!("type_requires(%s, %s)? %b",
2346 ::util::ppaux::ty_to_str(cx, r_ty),
2347 ::util::ppaux::ty_to_str(cx, ty),
2352 fn subtypes_require(cx: ctxt, seen: &mut ~[def_id],
2353 r_ty: t, ty: t) -> bool {
2354 debug!("subtypes_require(%s, %s)?",
2355 ::util::ppaux::ty_to_str(cx, r_ty),
2356 ::util::ppaux::ty_to_str(cx, ty));
2358 let r = match get(ty).sty {
2374 ty_opaque_closure_ptr(_) |
2376 ty_unboxed_vec(_) => {
2381 ty_rptr(_, ref mt) => {
2382 type_requires(cx, seen, r_ty, mt.ty)
2386 false // unsafe ptrs can always be NULL
2389 ty_trait(_, _, _, _, _) => {
2393 ty_struct(ref did, _) if seen.contains(did) => {
2397 ty_struct(did, ref substs) => {
2399 let fields = struct_fields(cx, did, substs);
2400 let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
2406 ts.iter().any(|t| type_requires(cx, seen, r_ty, *t))
2409 ty_enum(ref did, _) if seen.contains(did) => {
2413 ty_enum(did, ref substs) => {
2415 let vs = enum_variants(cx, did);
2416 let r = !vs.is_empty() && do vs.iter().all |variant| {
2417 do variant.args.iter().any |aty| {
2418 let sty = subst(cx, substs, *aty);
2419 type_requires(cx, seen, r_ty, sty)
2427 debug!("subtypes_require(%s, %s)? %b",
2428 ::util::ppaux::ty_to_str(cx, r_ty),
2429 ::util::ppaux::ty_to_str(cx, ty),
2436 !subtypes_require(cx, &mut seen, r_ty, r_ty)
2439 pub fn type_structurally_contains(cx: ctxt,
2441 test: &fn(x: &sty) -> bool)
2443 let sty = &get(ty).sty;
2444 debug!("type_structurally_contains: %s",
2445 ::util::ppaux::ty_to_str(cx, ty));
2446 if test(sty) { return true; }
2448 ty_enum(did, ref substs) => {
2449 for variant in (*enum_variants(cx, did)).iter() {
2450 for aty in variant.args.iter() {
2451 let sty = subst(cx, substs, *aty);
2452 if type_structurally_contains(cx, sty, |x| test(x)) { return true; }
2457 ty_struct(did, ref substs) => {
2458 let r = lookup_struct_fields(cx, did);
2459 for field in r.iter() {
2460 let ft = lookup_field_type(cx, did, field.id, substs);
2461 if type_structurally_contains(cx, ft, |x| test(x)) { return true; }
2467 for tt in ts.iter() {
2468 if type_structurally_contains(cx, *tt, |x| test(x)) { return true; }
2472 ty_evec(ref mt, vstore_fixed(_)) => {
2473 return type_structurally_contains(cx, mt.ty, test);
2479 pub fn type_structurally_contains_uniques(cx: ctxt, ty: t) -> bool {
2480 return type_structurally_contains(cx, ty, |sty| {
2483 ty_evec(_, vstore_uniq) |
2484 ty_estr(vstore_uniq) => true,
2490 pub fn type_is_integral(ty: t) -> bool {
2492 ty_infer(IntVar(_)) | ty_int(_) | ty_uint(_) => true,
2497 pub fn type_is_char(ty: t) -> bool {
2499 ty_int(ty_char) => true,
2504 pub fn type_is_fp(ty: t) -> bool {
2506 ty_infer(FloatVar(_)) | ty_float(_) => true,
2511 pub fn type_is_numeric(ty: t) -> bool {
2512 return type_is_integral(ty) || type_is_fp(ty);
2515 pub fn type_is_signed(ty: t) -> bool {
2522 pub fn type_is_machine(ty: t) -> bool {
2524 ty_int(ast::ty_i) | ty_uint(ast::ty_u) | ty_float(ast::ty_f) => false,
2525 ty_int(*) | ty_uint(*) | ty_float(*) => true,
2530 // Whether a type is Plain Old Data -- meaning it does not contain pointers
2531 // that the cycle collector might care about.
2532 pub fn type_is_pod(cx: ctxt, ty: t) -> bool {
2533 let mut result = true;
2536 ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) |
2537 ty_type | ty_ptr(_) | ty_bare_fn(_) => result = true,
2539 ty_box(_) | ty_uniq(_) | ty_closure(_) |
2540 ty_estr(vstore_uniq) | ty_estr(vstore_box) |
2541 ty_evec(_, vstore_uniq) | ty_evec(_, vstore_box) |
2542 ty_trait(_, _, _, _, _) | ty_rptr(_,_) | ty_opaque_box => result = false,
2544 ty_enum(did, ref substs) => {
2545 let variants = enum_variants(cx, did);
2546 for variant in (*variants).iter() {
2547 // XXX(pcwalton): This is an inefficient way to do this. Don't
2548 // synthesize a tuple!
2550 // Perform any type parameter substitutions.
2551 let tup_ty = mk_tup(cx, variant.args.clone());
2552 let tup_ty = subst(cx, substs, tup_ty);
2553 if !type_is_pod(cx, tup_ty) { result = false; }
2556 ty_tup(ref elts) => {
2557 for elt in elts.iter() { if !type_is_pod(cx, *elt) { result = false; } }
2559 ty_estr(vstore_fixed(_)) => result = true,
2560 ty_evec(ref mt, vstore_fixed(_)) | ty_unboxed_vec(ref mt) => {
2561 result = type_is_pod(cx, mt.ty);
2563 ty_param(_) => result = false,
2564 ty_opaque_closure_ptr(_) => result = true,
2565 ty_struct(did, ref substs) => {
2566 let fields = lookup_struct_fields(cx, did);
2567 result = do fields.iter().all |f| {
2568 let fty = ty::lookup_item_type(cx, f.id);
2569 let sty = subst(cx, substs, fty.ty);
2570 type_is_pod(cx, sty)
2574 ty_estr(vstore_slice(*)) | ty_evec(_, vstore_slice(*)) => {
2578 ty_infer(*) | ty_self(*) | ty_err => {
2579 cx.sess.bug("non concrete type in type_is_pod");
2586 pub fn type_is_enum(ty: t) -> bool {
2588 ty_enum(_, _) => return true,
2593 // Is the type's representation size known at compile time?
2594 pub fn type_is_sized(cx: ctxt, ty: ty::t) -> bool {
2596 // FIXME(#6308) add trait, vec, str, etc here.
2598 let param_def = cx.ty_param_defs.get(&p.def_id.node);
2599 if param_def.bounds.builtin_bounds.contains_elem(BoundSized) {
2608 // Whether a type is enum like, that is a enum type with only nullary
2610 pub fn type_is_c_like_enum(cx: ctxt, ty: t) -> bool {
2612 ty_enum(did, _) => {
2613 let variants = enum_variants(cx, did);
2614 if variants.len() == 0 {
2617 variants.iter().all(|v| v.args.len() == 0)
2624 pub fn type_param(ty: t) -> Option<uint> {
2626 ty_param(p) => return Some(p.idx),
2627 _ => {/* fall through */ }
2632 // Returns the type and mutability of *t.
2634 // The parameter `explicit` indicates if this is an *explicit* dereference.
2635 // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
2636 pub fn deref(cx: ctxt, t: t, explicit: bool) -> Option<mt> {
2637 deref_sty(cx, &get(t).sty, explicit)
2640 pub fn deref_sty(cx: ctxt, sty: &sty, explicit: bool) -> Option<mt> {
2642 ty_rptr(_, mt) | ty_box(mt) | ty_uniq(mt) => {
2646 ty_ptr(mt) if explicit => {
2650 ty_enum(did, ref substs) => {
2651 let variants = enum_variants(cx, did);
2652 if (*variants).len() == 1u && variants[0].args.len() == 1u {
2653 let v_t = subst(cx, substs, variants[0].args[0]);
2654 Some(mt {ty: v_t, mutbl: ast::m_imm})
2660 ty_struct(did, ref substs) => {
2661 let fields = struct_fields(cx, did, substs);
2662 if fields.len() == 1 && fields[0].ident ==
2663 syntax::parse::token::special_idents::unnamed_field {
2664 Some(mt {ty: fields[0].mt.ty, mutbl: ast::m_imm})
2674 pub fn type_autoderef(cx: ctxt, t: t) -> t {
2677 match deref(cx, t, false) {
2679 Some(mt) => t = mt.ty
2684 // Returns the type and mutability of t[i]
2685 pub fn index(t: t) -> Option<mt> {
2686 index_sty(&get(t).sty)
2689 pub fn index_sty(sty: &sty) -> Option<mt> {
2691 ty_evec(mt, _) => Some(mt),
2692 ty_estr(_) => Some(mt {ty: mk_u8(), mutbl: ast::m_imm}),
2698 * Enforces an arbitrary but consistent total ordering over
2699 * free regions. This is needed for establishing a consistent
2700 * LUB in region_inference. */
2701 impl cmp::TotalOrd for FreeRegion {
2702 fn cmp(&self, other: &FreeRegion) -> Ordering {
2703 cmp::cmp2(&self.scope_id, &self.bound_region,
2704 &other.scope_id, &other.bound_region)
2708 impl cmp::TotalEq for FreeRegion {
2709 fn equals(&self, other: &FreeRegion) -> bool {
2715 * Enforces an arbitrary but consistent total ordering over
2716 * bound regions. This is needed for establishing a consistent
2717 * LUB in region_inference. */
2718 impl cmp::TotalOrd for bound_region {
2719 fn cmp(&self, other: &bound_region) -> Ordering {
2720 match (self, other) {
2721 (&ty::br_self, &ty::br_self) => cmp::Equal,
2722 (&ty::br_self, _) => cmp::Less,
2724 (&ty::br_anon(ref a1), &ty::br_anon(ref a2)) => a1.cmp(a2),
2725 (&ty::br_anon(*), _) => cmp::Less,
2727 (&ty::br_named(ref a1), &ty::br_named(ref a2)) => a1.name.cmp(&a2.name),
2728 (&ty::br_named(*), _) => cmp::Less,
2730 (&ty::br_cap_avoid(ref a1, @ref b1),
2731 &ty::br_cap_avoid(ref a2, @ref b2)) => cmp::cmp2(a1, b1, a2, b2),
2732 (&ty::br_cap_avoid(*), _) => cmp::Less,
2734 (&ty::br_fresh(ref a1), &ty::br_fresh(ref a2)) => a1.cmp(a2),
2735 (&ty::br_fresh(*), _) => cmp::Less,
2740 impl cmp::TotalEq for bound_region {
2741 fn equals(&self, other: &bound_region) -> bool {
2746 pub fn node_id_to_trait_ref(cx: ctxt, id: ast::NodeId) -> @ty::TraitRef {
2747 match cx.trait_refs.find(&id) {
2749 None => cx.sess.bug(
2750 fmt!("node_id_to_trait_ref: no trait ref for node `%s`",
2751 ast_map::node_id_to_str(cx.items, id,
2752 token::get_ident_interner())))
2756 pub fn node_id_to_type(cx: ctxt, id: ast::NodeId) -> t {
2757 //printfln!("%?/%?", id, cx.node_types.len());
2758 match cx.node_types.find(&(id as uint)) {
2760 None => cx.sess.bug(
2761 fmt!("node_id_to_type: no type for node `%s`",
2762 ast_map::node_id_to_str(cx.items, id,
2763 token::get_ident_interner())))
2767 // XXX(pcwalton): Makes a copy, bleh. Probably better to not do that.
2768 pub fn node_id_to_type_params(cx: ctxt, id: ast::NodeId) -> ~[t] {
2769 match cx.node_type_substs.find(&id) {
2771 Some(ts) => return (*ts).clone(),
2775 fn node_id_has_type_params(cx: ctxt, id: ast::NodeId) -> bool {
2776 cx.node_type_substs.contains_key(&id)
2779 pub fn ty_fn_sig(fty: t) -> FnSig {
2780 match get(fty).sty {
2781 ty_bare_fn(ref f) => f.sig.clone(),
2782 ty_closure(ref f) => f.sig.clone(),
2784 fail!("ty_fn_sig() called on non-fn type: %?", s)
2789 // Type accessors for substructures of types
2790 pub fn ty_fn_args(fty: t) -> ~[t] {
2791 match get(fty).sty {
2792 ty_bare_fn(ref f) => f.sig.inputs.clone(),
2793 ty_closure(ref f) => f.sig.inputs.clone(),
2795 fail!("ty_fn_args() called on non-fn type: %?", s)
2800 pub fn ty_closure_sigil(fty: t) -> Sigil {
2801 match get(fty).sty {
2802 ty_closure(ref f) => f.sigil,
2804 fail!("ty_closure_sigil() called on non-closure type: %?", s)
2809 pub fn ty_fn_purity(fty: t) -> ast::purity {
2810 match get(fty).sty {
2811 ty_bare_fn(ref f) => f.purity,
2812 ty_closure(ref f) => f.purity,
2814 fail!("ty_fn_purity() called on non-fn type: %?", s)
2819 pub fn ty_fn_ret(fty: t) -> t {
2820 match get(fty).sty {
2821 ty_bare_fn(ref f) => f.sig.output,
2822 ty_closure(ref f) => f.sig.output,
2824 fail!("ty_fn_ret() called on non-fn type: %?", s)
2829 pub fn is_fn_ty(fty: t) -> bool {
2830 match get(fty).sty {
2831 ty_bare_fn(_) => true,
2832 ty_closure(_) => true,
2837 pub fn ty_vstore(ty: t) -> vstore {
2839 ty_evec(_, vstore) => vstore,
2840 ty_estr(vstore) => vstore,
2841 ref s => fail!("ty_vstore() called on invalid sty: %?", s)
2845 pub fn ty_region(tcx: ctxt,
2850 ty_evec(_, vstore_slice(r)) => r,
2851 ty_estr(vstore_slice(r)) => r,
2855 fmt!("ty_region() invoked on in appropriate ty: %?", s));
2860 pub fn replace_fn_sig(cx: ctxt, fsty: &sty, new_sig: FnSig) -> t {
2862 ty_bare_fn(ref f) => mk_bare_fn(cx, BareFnTy {sig: new_sig, ..*f}),
2863 ty_closure(ref f) => mk_closure(cx, ClosureTy {sig: new_sig, ..*f}),
2866 fmt!("ty_fn_sig() called on non-fn type: %?", s));
2871 pub fn replace_closure_return_type(tcx: ctxt, fn_type: t, ret_type: t) -> t {
2874 * Returns a new function type based on `fn_type` but returning a value of
2875 * type `ret_type` instead. */
2877 match ty::get(fn_type).sty {
2878 ty::ty_closure(ref fty) => {
2879 ty::mk_closure(tcx, ClosureTy {
2880 sig: FnSig {output: ret_type, ..fty.sig.clone()},
2886 "replace_fn_ret() invoked with non-fn-type: %s",
2887 ty_to_str(tcx, fn_type)));
2892 // Returns a vec of all the input and output types of fty.
2893 pub fn tys_in_fn_sig(sig: &FnSig) -> ~[t] {
2894 vec::append_one(sig.inputs.map(|a| *a), sig.output)
2897 // Type accessors for AST nodes
2898 pub fn block_ty(cx: ctxt, b: &ast::Block) -> t {
2899 return node_id_to_type(cx, b.id);
2903 // Returns the type of a pattern as a monotype. Like @expr_ty, this function
2904 // doesn't provide type parameter substitutions.
2905 pub fn pat_ty(cx: ctxt, pat: &ast::pat) -> t {
2906 return node_id_to_type(cx, pat.id);
2910 // Returns the type of an expression as a monotype.
2912 // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression. That is, in
2913 // some cases, we insert `AutoAdjustment` annotations such as auto-deref or
2914 // auto-ref. The type returned by this function does not consider such
2915 // adjustments. See `expr_ty_adjusted()` instead.
2917 // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
2918 // ask for the type of "id" in "id(3)", it will return "fn(&int) -> int"
2919 // instead of "fn(t) -> T with T = int". If this isn't what you want, see
2920 // expr_ty_params_and_ty() below.
2921 pub fn expr_ty(cx: ctxt, expr: &ast::expr) -> t {
2922 return node_id_to_type(cx, expr.id);
2925 pub fn expr_ty_adjusted(cx: ctxt, expr: &ast::expr) -> t {
2928 * Returns the type of `expr`, considering any `AutoAdjustment`
2929 * entry recorded for that expression.
2931 * It would almost certainly be better to store the adjusted ty in with
2932 * the `AutoAdjustment`, but I opted not to do this because it would
2933 * require serializing and deserializing the type and, although that's not
2934 * hard to do, I just hate that code so much I didn't want to touch it
2935 * unless it was to fix it properly, which seemed a distraction from the
2936 * task at hand! -nmatsakis
2939 let unadjusted_ty = expr_ty(cx, expr);
2940 adjust_ty(cx, expr.span, unadjusted_ty, cx.adjustments.find_copy(&expr.id))
2943 pub fn adjust_ty(cx: ctxt,
2945 unadjusted_ty: ty::t,
2946 adjustment: Option<@AutoAdjustment>) -> ty::t
2948 /*! See `expr_ty_adjusted` */
2950 return match adjustment {
2951 None => unadjusted_ty,
2953 Some(@AutoAddEnv(r, s)) => {
2954 match ty::get(unadjusted_ty).sty {
2955 ty::ty_bare_fn(ref b) => {
2958 ty::ClosureTy {purity: b.purity,
2960 onceness: ast::Many,
2962 bounds: ty::AllBuiltinBounds(),
2963 sig: b.sig.clone()})
2967 fmt!("add_env adjustment on non-bare-fn: %?", b));
2972 Some(@AutoDerefRef(ref adj)) => {
2973 let mut adjusted_ty = unadjusted_ty;
2975 if (!ty::type_is_error(adjusted_ty)) {
2976 for i in range(0, adj.autoderefs) {
2977 match ty::deref(cx, adjusted_ty, true) {
2978 Some(mt) => { adjusted_ty = mt.ty; }
2982 fmt!("The %uth autoderef failed: %s",
2991 None => adjusted_ty,
2992 Some(ref autoref) => {
2995 mk_rptr(cx, r, mt {ty: adjusted_ty, mutbl: m})
2998 AutoBorrowVec(r, m) => {
2999 borrow_vec(cx, span, r, m, adjusted_ty)
3002 AutoBorrowVecRef(r, m) => {
3003 adjusted_ty = borrow_vec(cx, span, r, m, adjusted_ty);
3004 mk_rptr(cx, r, mt {ty: adjusted_ty, mutbl: ast::m_imm})
3007 AutoBorrowFn(r) => {
3008 borrow_fn(cx, span, r, adjusted_ty)
3012 mk_ptr(cx, mt {ty: adjusted_ty, mutbl: m})
3020 fn borrow_vec(cx: ctxt, span: span,
3021 r: Region, m: ast::mutability,
3022 ty: ty::t) -> ty::t {
3025 ty::mk_evec(cx, mt {ty: mt.ty, mutbl: m}, vstore_slice(r))
3029 ty::mk_estr(cx, vstore_slice(r))
3035 fmt!("borrow-vec associated with bad sty: %?",
3041 fn borrow_fn(cx: ctxt, span: span, r: Region, ty: ty::t) -> ty::t {
3043 ty_closure(ref fty) => {
3044 ty::mk_closure(cx, ClosureTy {
3045 sigil: BorrowedSigil,
3054 fmt!("borrow-fn associated with bad sty: %?",
3062 pub fn map_region(&self, f: &fn(Region) -> Region) -> AutoRef {
3064 ty::AutoPtr(r, m) => ty::AutoPtr(f(r), m),
3065 ty::AutoBorrowVec(r, m) => ty::AutoBorrowVec(f(r), m),
3066 ty::AutoBorrowVecRef(r, m) => ty::AutoBorrowVecRef(f(r), m),
3067 ty::AutoBorrowFn(r) => ty::AutoBorrowFn(f(r)),
3068 ty::AutoUnsafe(m) => ty::AutoUnsafe(m),
3073 pub struct ParamsTy {
3078 pub fn expr_ty_params_and_ty(cx: ctxt,
3082 params: node_id_to_type_params(cx, expr.id),
3083 ty: node_id_to_type(cx, expr.id)
3087 pub fn expr_has_ty_params(cx: ctxt, expr: &ast::expr) -> bool {
3088 return node_id_has_type_params(cx, expr.id);
3091 pub fn method_call_type_param_defs(tcx: ctxt,
3092 method_map: typeck::method_map,
3094 -> Option<@~[TypeParameterDef]> {
3095 do method_map.find(&id).map |method| {
3096 match method.origin {
3097 typeck::method_static(did) => {
3098 // n.b.: When we encode impl methods, the bounds
3099 // that we encode include both the impl bounds
3100 // and then the method bounds themselves...
3101 ty::lookup_item_type(tcx, did).generics.type_param_defs
3103 typeck::method_param(typeck::method_param {
3105 method_num: n_mth, _}) |
3106 typeck::method_trait(trt_id, n_mth, _) => {
3107 // ...trait methods bounds, in contrast, include only the
3108 // method bounds, so we must preprend the tps from the
3109 // trait itself. This ought to be harmonized.
3110 let trait_type_param_defs =
3111 ty::lookup_trait_def(tcx, trt_id).generics.type_param_defs;
3113 (*trait_type_param_defs).clone(),
3114 *ty::trait_method(tcx,
3116 n_mth).generics.type_param_defs)
3122 pub fn resolve_expr(tcx: ctxt, expr: &ast::expr) -> ast::def {
3123 match tcx.def_map.find(&expr.id) {
3126 tcx.sess.span_bug(expr.span, fmt!(
3127 "No def-map entry for expr %?", expr.id));
3132 pub fn expr_is_lval(tcx: ctxt,
3133 method_map: typeck::method_map,
3134 e: &ast::expr) -> bool {
3135 match expr_kind(tcx, method_map, e) {
3137 RvalueDpsExpr | RvalueDatumExpr | RvalueStmtExpr => false
3141 /// We categorize expressions into three kinds. The distinction between
3142 /// lvalue/rvalue is fundamental to the language. The distinction between the
3143 /// two kinds of rvalues is an artifact of trans which reflects how we will
3144 /// generate code for that kind of expression. See trans/expr.rs for more
3153 pub fn expr_kind(tcx: ctxt,
3154 method_map: typeck::method_map,
3155 expr: &ast::expr) -> ExprKind {
3156 if method_map.contains_key(&expr.id) {
3157 // Overloaded operations are generally calls, and hence they are
3158 // generated via DPS. However, assign_op (e.g., `x += y`) is an
3159 // exception, as its result is always unit.
3160 return match expr.node {
3161 ast::expr_assign_op(*) => RvalueStmtExpr,
3167 ast::expr_path(*) | ast::expr_self => {
3168 match resolve_expr(tcx, expr) {
3169 ast::def_variant(*) | ast::def_struct(*) => RvalueDpsExpr,
3171 // Fn pointers are just scalar values.
3172 ast::def_fn(*) | ast::def_static_method(*) => RvalueDatumExpr,
3174 // Note: there is actually a good case to be made that
3175 // def_args, particularly those of immediate type, ought to
3176 // considered rvalues.
3177 ast::def_static(*) |
3178 ast::def_binding(*) |
3182 ast::def_self(*) => LvalueExpr,
3185 tcx.sess.span_bug(expr.span, fmt!(
3186 "Uncategorized def for expr %?: %?",
3192 ast::expr_unary(_, ast::deref, _) |
3193 ast::expr_field(*) |
3194 ast::expr_index(*) => {
3199 ast::expr_method_call(*) |
3200 ast::expr_struct(*) |
3203 ast::expr_match(*) |
3204 ast::expr_fn_block(*) |
3205 ast::expr_do_body(*) |
3206 ast::expr_block(*) |
3207 ast::expr_repeat(*) |
3208 ast::expr_lit(@codemap::spanned {node: lit_str(_), _}) |
3209 ast::expr_vstore(_, ast::expr_vstore_slice) |
3210 ast::expr_vstore(_, ast::expr_vstore_mut_slice) |
3211 ast::expr_vec(*) => {
3215 ast::expr_cast(*) => {
3216 match tcx.node_types.find(&(expr.id as uint)) {
3218 if ty::type_is_immediate(tcx, t) {
3225 // Technically, it should not happen that the expr is not
3226 // present within the table. However, it DOES happen
3227 // during type check, because the final types from the
3228 // expressions are not yet recorded in the tcx. At that
3229 // time, though, we are only interested in knowing lvalue
3230 // vs rvalue. It would be better to base this decision on
3231 // the AST type in cast node---but (at the time of this
3232 // writing) it's not easy to distinguish casts to traits
3233 // from other casts based on the AST. This should be
3234 // easier in the future, when casts to traits would like
3235 // like @Foo, ~Foo, or &Foo.
3241 ast::expr_break(*) |
3242 ast::expr_again(*) |
3245 ast::expr_while(*) |
3247 ast::expr_assign(*) |
3248 ast::expr_inline_asm(*) |
3249 ast::expr_assign_op(*) => {
3253 ast::expr_for_loop(*) => fail!("non-desugared expr_for_loop"),
3255 ast::expr_lit(_) | // Note: lit_str is carved out above
3256 ast::expr_unary(*) |
3257 ast::expr_addr_of(*) |
3258 ast::expr_binary(*) |
3259 ast::expr_vstore(_, ast::expr_vstore_box) |
3260 ast::expr_vstore(_, ast::expr_vstore_mut_box) |
3261 ast::expr_vstore(_, ast::expr_vstore_uniq) => {
3265 ast::expr_paren(e) => expr_kind(tcx, method_map, e),
3267 ast::expr_mac(*) => {
3270 "macro expression remains after expansion");
3275 pub fn stmt_node_id(s: &ast::stmt) -> ast::NodeId {
3277 ast::stmt_decl(_, id) | stmt_expr(_, id) | stmt_semi(_, id) => {
3280 ast::stmt_mac(*) => fail!("unexpanded macro in trans")
3284 pub fn field_idx(id: ast::ident, fields: &[field]) -> Option<uint> {
3286 for f in fields.iter() { if f.ident == id { return Some(i); } i += 1u; }
3290 pub fn field_idx_strict(tcx: ty::ctxt, id: ast::ident, fields: &[field])
3293 for f in fields.iter() { if f.ident == id { return i; } i += 1u; }
3295 "No field named `%s` found in the list of fields `%?`",
3296 tcx.sess.str_of(id),
3297 fields.map(|f| tcx.sess.str_of(f.ident))));
3300 pub fn method_idx(id: ast::ident, meths: &[@Method]) -> Option<uint> {
3301 meths.iter().position(|m| m.ident == id)
3304 /// Returns a vector containing the indices of all type parameters that appear
3305 /// in `ty`. The vector may contain duplicates. Probably should be converted
3306 /// to a bitset or some other representation.
3307 pub fn param_tys_in_type(ty: t) -> ~[param_ty] {
3309 do walk_ty(ty) |ty| {
3320 pub fn occurs_check(tcx: ctxt, sp: span, vid: TyVid, rt: t) {
3321 // Returns a vec of all the type variables occurring in `ty`. It may
3322 // contain duplicates. (Integral type vars aren't counted.)
3323 fn vars_in_type(ty: t) -> ~[TyVid] {
3325 do walk_ty(ty) |ty| {
3327 ty_infer(TyVar(v)) => rslt.push(v),
3335 if !type_needs_infer(rt) { return; }
3338 if vars_in_type(rt).contains(&vid) {
3339 // Maybe this should be span_err -- however, there's an
3340 // assertion later on that the type doesn't contain
3341 // variables, so in this case we have to be sure to die.
3343 (sp, ~"type inference failed because I \
3344 could not find a type\n that's both of the form "
3345 + ::util::ppaux::ty_to_str(tcx, mk_var(tcx, vid)) +
3346 " and of the form " + ::util::ppaux::ty_to_str(tcx, rt) +
3347 " - such a type would have to be infinitely large.");
3351 pub fn ty_sort_str(cx: ctxt, t: t) -> ~str {
3353 ty_nil | ty_bot | ty_bool | ty_int(_) |
3354 ty_uint(_) | ty_float(_) | ty_estr(_) |
3355 ty_type | ty_opaque_box | ty_opaque_closure_ptr(_) => {
3356 ::util::ppaux::ty_to_str(cx, t)
3359 ty_enum(id, _) => fmt!("enum %s", item_path_str(cx, id)),
3360 ty_box(_) => ~"@-ptr",
3361 ty_uniq(_) => ~"~-ptr",
3362 ty_evec(_, _) => ~"vector",
3363 ty_unboxed_vec(_) => ~"unboxed vector",
3364 ty_ptr(_) => ~"*-ptr",
3365 ty_rptr(_, _) => ~"&-ptr",
3366 ty_bare_fn(_) => ~"extern fn",
3367 ty_closure(_) => ~"fn",
3368 ty_trait(id, _, _, _, _) => fmt!("trait %s", item_path_str(cx, id)),
3369 ty_struct(id, _) => fmt!("struct %s", item_path_str(cx, id)),
3370 ty_tup(_) => ~"tuple",
3371 ty_infer(TyVar(_)) => ~"inferred type",
3372 ty_infer(IntVar(_)) => ~"integral variable",
3373 ty_infer(FloatVar(_)) => ~"floating-point variable",
3374 ty_param(_) => ~"type parameter",
3375 ty_self(_) => ~"self",
3376 ty_err => ~"type error"
3380 pub fn type_err_to_str(cx: ctxt, err: &type_err) -> ~str {
3383 * Explains the source of a type err in a short,
3384 * human readable way. This is meant to be placed in
3385 * parentheses after some larger message. You should
3386 * also invoke `note_and_explain_type_err()` afterwards
3387 * to present additional details, particularly when
3388 * it comes to lifetime-related errors. */
3390 fn terr_vstore_kind_to_str(k: terr_vstore_kind) -> ~str {
3395 terr_trait => ~"trait"
3400 terr_mismatch => ~"types differ",
3401 terr_purity_mismatch(values) => {
3402 fmt!("expected %s fn but found %s fn",
3403 values.expected.to_str(), values.found.to_str())
3405 terr_abi_mismatch(values) => {
3406 fmt!("expected %s fn but found %s fn",
3407 values.expected.to_str(), values.found.to_str())
3409 terr_onceness_mismatch(values) => {
3410 fmt!("expected %s fn but found %s fn",
3411 values.expected.to_str(), values.found.to_str())
3413 terr_sigil_mismatch(values) => {
3414 fmt!("expected %s closure, found %s closure",
3415 values.expected.to_str(),
3416 values.found.to_str())
3418 terr_mutability => ~"values differ in mutability",
3419 terr_box_mutability => ~"boxed values differ in mutability",
3420 terr_vec_mutability => ~"vectors differ in mutability",
3421 terr_ptr_mutability => ~"pointers differ in mutability",
3422 terr_ref_mutability => ~"references differ in mutability",
3423 terr_ty_param_size(values) => {
3424 fmt!("expected a type with %? type params \
3425 but found one with %? type params",
3426 values.expected, values.found)
3428 terr_tuple_size(values) => {
3429 fmt!("expected a tuple with %? elements \
3430 but found one with %? elements",
3431 values.expected, values.found)
3433 terr_record_size(values) => {
3434 fmt!("expected a record with %? fields \
3435 but found one with %? fields",
3436 values.expected, values.found)
3438 terr_record_mutability => {
3439 ~"record elements differ in mutability"
3441 terr_record_fields(values) => {
3442 fmt!("expected a record with field `%s` but found one with field \
3444 cx.sess.str_of(values.expected),
3445 cx.sess.str_of(values.found))
3447 terr_arg_count => ~"incorrect number of function parameters",
3448 terr_regions_does_not_outlive(*) => {
3449 fmt!("lifetime mismatch")
3451 terr_regions_not_same(*) => {
3452 fmt!("lifetimes are not the same")
3454 terr_regions_no_overlap(*) => {
3455 fmt!("lifetimes do not intersect")
3457 terr_regions_insufficiently_polymorphic(br, _) => {
3458 fmt!("expected bound lifetime parameter %s, \
3459 but found concrete lifetime",
3460 bound_region_ptr_to_str(cx, br))
3462 terr_regions_overly_polymorphic(br, _) => {
3463 fmt!("expected concrete lifetime, \
3464 but found bound lifetime parameter %s",
3465 bound_region_ptr_to_str(cx, br))
3467 terr_vstores_differ(k, ref values) => {
3468 fmt!("%s storage differs: expected %s but found %s",
3469 terr_vstore_kind_to_str(k),
3470 vstore_to_str(cx, (*values).expected),
3471 vstore_to_str(cx, (*values).found))
3473 terr_trait_stores_differ(_, ref values) => {
3474 fmt!("trait storage differs: expected %s but found %s",
3475 trait_store_to_str(cx, (*values).expected),
3476 trait_store_to_str(cx, (*values).found))
3478 terr_in_field(err, fname) => {
3479 fmt!("in field `%s`, %s", cx.sess.str_of(fname),
3480 type_err_to_str(cx, err))
3482 terr_sorts(values) => {
3483 fmt!("expected %s but found %s",
3484 ty_sort_str(cx, values.expected),
3485 ty_sort_str(cx, values.found))
3487 terr_traits(values) => {
3488 fmt!("expected trait %s but found trait %s",
3489 item_path_str(cx, values.expected),
3490 item_path_str(cx, values.found))
3492 terr_builtin_bounds(values) => {
3493 if values.expected.is_empty() {
3494 fmt!("expected no bounds but found `%s`",
3495 values.found.user_string(cx))
3496 } else if values.found.is_empty() {
3497 fmt!("expected bounds `%s` but found no bounds",
3498 values.expected.user_string(cx))
3500 fmt!("expected bounds `%s` but found bounds `%s`",
3501 values.expected.user_string(cx),
3502 values.found.user_string(cx))
3505 terr_integer_as_char => {
3506 fmt!("expected an integral type but found char")
3508 terr_int_mismatch(ref values) => {
3509 fmt!("expected %s but found %s",
3510 values.expected.to_str(),
3511 values.found.to_str())
3513 terr_float_mismatch(ref values) => {
3514 fmt!("expected %s but found %s",
3515 values.expected.to_str(),
3516 values.found.to_str())
3521 pub fn note_and_explain_type_err(cx: ctxt, err: &type_err) {
3523 terr_regions_does_not_outlive(subregion, superregion) => {
3524 note_and_explain_region(cx, "", subregion, "...");
3525 note_and_explain_region(cx, "...does not necessarily outlive ",
3528 terr_regions_not_same(region1, region2) => {
3529 note_and_explain_region(cx, "", region1, "...");
3530 note_and_explain_region(cx, "...is not the same lifetime as ",
3533 terr_regions_no_overlap(region1, region2) => {
3534 note_and_explain_region(cx, "", region1, "...");
3535 note_and_explain_region(cx, "...does not overlap ",
3538 terr_regions_insufficiently_polymorphic(_, conc_region) => {
3539 note_and_explain_region(cx,
3540 "concrete lifetime that was found is ",
3543 terr_regions_overly_polymorphic(_, conc_region) => {
3544 note_and_explain_region(cx,
3545 "expected concrete lifetime is ",
3552 pub fn def_has_ty_params(def: ast::def) -> bool {
3554 ast::def_fn(_, _) | ast::def_variant(_, _) | ast::def_struct(_)
3560 pub fn provided_source(cx: ctxt, id: ast::def_id)
3561 -> Option<ast::def_id> {
3562 cx.provided_method_sources.find(&id).map(|x| **x)
3565 pub fn provided_trait_methods(cx: ctxt, id: ast::def_id) -> ~[@Method] {
3567 match cx.items.find(&id.node) {
3568 Some(&ast_map::node_item(@ast::item {
3569 node: item_trait(_, _, ref ms),
3572 match ast_util::split_trait_methods(*ms) {
3573 (_, p) => p.map(|m| method(cx, ast_util::local_def(m.id)))
3575 _ => cx.sess.bug(fmt!("provided_trait_methods: %? is not a trait",
3579 csearch::get_provided_trait_methods(cx, id)
3583 pub fn trait_supertraits(cx: ctxt,
3584 id: ast::def_id) -> @~[@TraitRef]
3587 match cx.supertraits.find(&id) {
3588 Some(&trait_refs) => { return trait_refs; }
3589 None => {} // Continue.
3592 // Not in the cache. It had better be in the metadata, which means it
3593 // shouldn't be local.
3594 assert!(!is_local(id));
3596 // Get the supertraits out of the metadata and create the
3597 // TraitRef for each.
3598 let result = @csearch::get_supertraits(cx, id);
3599 cx.supertraits.insert(id, result);
3603 pub fn trait_ref_supertraits(cx: ctxt, trait_ref: &ty::TraitRef) -> ~[@TraitRef] {
3604 let supertrait_refs = trait_supertraits(cx, trait_ref.def_id);
3605 supertrait_refs.map(
3606 |supertrait_ref| supertrait_ref.subst(cx, &trait_ref.substs))
3609 fn lookup_locally_or_in_crate_store<V:Clone>(
3611 def_id: ast::def_id,
3612 map: &mut HashMap<ast::def_id, V>,
3613 load_external: &fn() -> V) -> V
3617 * Helper for looking things up in the various maps
3618 * that are populated during typeck::collect (e.g.,
3619 * `cx.methods`, `cx.tcache`, etc). All of these share
3620 * the pattern that if the id is local, it should have
3621 * been loaded into the map by the `typeck::collect` phase.
3622 * If the def-id is external, then we have to go consult
3623 * the crate loading code (and cache the result for the future).
3626 match map.find(&def_id) {
3627 Some(&ref v) => { return (*v).clone(); }
3631 if def_id.crate == ast::LOCAL_CRATE {
3632 fail!("No def'n found for %? in tcx.%s", def_id, descr);
3634 let v = load_external();
3635 map.insert(def_id, v.clone());
3639 pub fn trait_method(cx: ctxt, trait_did: ast::def_id, idx: uint) -> @Method {
3640 let method_def_id = ty::trait_method_def_ids(cx, trait_did)[idx];
3641 ty::method(cx, method_def_id)
3645 pub fn trait_methods(cx: ctxt, trait_did: ast::def_id) -> @~[@Method] {
3646 match cx.trait_methods_cache.find(&trait_did) {
3647 Some(&methods) => methods,
3649 let def_ids = ty::trait_method_def_ids(cx, trait_did);
3650 let methods = @def_ids.map(|d| ty::method(cx, *d));
3651 cx.trait_methods_cache.insert(trait_did, methods);
3657 pub fn method(cx: ctxt, id: ast::def_id) -> @Method {
3658 lookup_locally_or_in_crate_store(
3659 "methods", id, cx.methods,
3660 || @csearch::get_method(cx, id))
3663 pub fn trait_method_def_ids(cx: ctxt, id: ast::def_id) -> @~[def_id] {
3664 lookup_locally_or_in_crate_store(
3665 "methods", id, cx.trait_method_def_ids,
3666 || @csearch::get_trait_method_def_ids(cx.cstore, id))
3669 pub fn impl_trait_ref(cx: ctxt, id: ast::def_id) -> Option<@TraitRef> {
3670 match cx.impl_trait_cache.find(&id) {
3671 Some(&ret) => { return ret; }
3674 let ret = if id.crate == ast::LOCAL_CRATE {
3675 debug!("(impl_trait_ref) searching for trait impl %?", id);
3676 match cx.items.find(&id.node) {
3677 Some(&ast_map::node_item(@ast::item {
3678 node: ast::item_impl(_, ref opt_trait, _, _),
3682 &Some(ref t) => Some(ty::node_id_to_trait_ref(cx, t.ref_id)),
3689 csearch::get_impl_trait(cx, id)
3691 cx.impl_trait_cache.insert(id, ret);
3695 pub fn ty_to_def_id(ty: t) -> Option<ast::def_id> {
3697 ty_trait(id, _, _, _, _) | ty_struct(id, _) | ty_enum(id, _) => Some(id),
3702 /// Returns the def ID of the constructor for the given tuple-like struct, or
3703 /// None if the struct is not tuple-like. Fails if the given def ID does not
3704 /// refer to a struct at all.
3705 fn struct_ctor_id(cx: ctxt, struct_did: ast::def_id) -> Option<ast::def_id> {
3706 if struct_did.crate != ast::LOCAL_CRATE {
3707 // XXX: Cross-crate functionality.
3708 cx.sess.unimpl("constructor ID of cross-crate tuple structs");
3711 match cx.items.find(&struct_did.node) {
3712 Some(&ast_map::node_item(item, _)) => {
3714 ast::item_struct(struct_def, _) => {
3715 struct_def.ctor_id.map(|ctor_id|
3716 ast_util::local_def(*ctor_id))
3718 _ => cx.sess.bug("called struct_ctor_id on non-struct")
3721 _ => cx.sess.bug("called struct_ctor_id on non-struct")
3727 pub struct VariantInfo {
3729 arg_names: Option<~[ast::ident]>,
3739 /// Creates a new VariantInfo from the corresponding ast representation.
3741 /// Does not do any caching of the value in the type context.
3742 pub fn from_ast_variant(cx: ctxt,
3743 ast_variant: &ast::variant,
3744 discriminant: uint) -> VariantInfo {
3746 let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
3748 match ast_variant.node.kind {
3749 ast::tuple_variant_kind(ref args) => {
3750 let arg_tys = if args.len() > 0 { ty_fn_args(ctor_ty).map(|a| *a) } else { ~[] };
3752 return VariantInfo {
3756 name: ast_variant.node.name,
3757 id: ast_util::local_def(ast_variant.node.id),
3758 disr_val: discriminant,
3759 vis: ast_variant.node.vis
3762 ast::struct_variant_kind(ref struct_def) => {
3764 let fields: &[@struct_field] = struct_def.fields;
3766 assert!(fields.len() > 0);
3768 let arg_tys = ty_fn_args(ctor_ty).map(|a| *a);
3769 let arg_names = do fields.map |field| {
3770 match field.node.kind {
3771 named_field(ident, _) => ident,
3772 unnamed_field => cx.sess.bug(
3773 "enum_variants: all fields in struct must have a name")
3777 return VariantInfo {
3779 arg_names: Some(arg_names),
3781 name: ast_variant.node.name,
3782 id: ast_util::local_def(ast_variant.node.id),
3783 disr_val: discriminant,
3784 vis: ast_variant.node.vis
3791 pub fn substd_enum_variants(cx: ctxt,
3794 -> ~[@VariantInfo] {
3795 do enum_variants(cx, id).iter().transform |variant_info| {
3796 let substd_args = variant_info.args.iter()
3797 .transform(|aty| subst(cx, substs, *aty)).collect();
3799 let substd_ctor_ty = subst(cx, substs, variant_info.ctor_ty);
3803 ctor_ty: substd_ctor_ty,
3804 ..(**variant_info).clone()
3809 pub fn item_path_str(cx: ctxt, id: ast::def_id) -> ~str {
3810 ast_map::path_to_str(item_path(cx, id), token::get_ident_interner())
3815 TraitDtor(def_id, bool)
3819 pub fn is_not_present(&self) -> bool {
3826 pub fn is_present(&self) -> bool {
3827 !self.is_not_present()
3830 pub fn has_drop_flag(&self) -> bool {
3833 &TraitDtor(_, flag) => flag
3838 /* If struct_id names a struct with a dtor, return Some(the dtor's id).
3839 Otherwise return none. */
3840 pub fn ty_dtor(cx: ctxt, struct_id: def_id) -> DtorKind {
3841 match cx.destructor_for_type.find(&struct_id) {
3842 Some(&method_def_id) => {
3843 let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag");
3845 TraitDtor(method_def_id, flag)
3851 pub fn has_dtor(cx: ctxt, struct_id: def_id) -> bool {
3852 ty_dtor(cx, struct_id).is_present()
3855 pub fn item_path(cx: ctxt, id: ast::def_id) -> ast_map::path {
3856 if id.crate != ast::LOCAL_CRATE {
3857 csearch::get_item_path(cx, id)
3859 // FIXME (#5521): uncomment this code and don't have a catch-all at the
3860 // end of the match statement. Favor explicitly listing
3862 // let node = cx.items.get(&id.node);
3864 match *cx.items.get(&id.node) {
3865 ast_map::node_item(item, path) => {
3866 let item_elt = match item.node {
3867 item_mod(_) | item_foreign_mod(_) => {
3868 ast_map::path_mod(item.ident)
3871 ast_map::path_name(item.ident)
3874 vec::append_one((*path).clone(), item_elt)
3877 ast_map::node_foreign_item(nitem, _, _, path) => {
3878 vec::append_one((*path).clone(),
3879 ast_map::path_name(nitem.ident))
3882 ast_map::node_method(method, _, path) => {
3883 vec::append_one((*path).clone(),
3884 ast_map::path_name(method.ident))
3886 ast_map::node_trait_method(trait_method, _, path) => {
3887 let method = ast_util::trait_method_to_ty_method(&*trait_method);
3888 vec::append_one((*path).clone(),
3889 ast_map::path_name(method.ident))
3892 ast_map::node_variant(ref variant, _, path) => {
3893 vec::append_one(path.init().to_owned(),
3894 ast_map::path_name((*variant).node.name))
3897 ast_map::node_struct_ctor(_, item, path) => {
3898 vec::append_one((*path).clone(), ast_map::path_name(item.ident))
3902 cx.sess.bug(fmt!("cannot find item_path for node %?", node));
3908 pub fn enum_is_univariant(cx: ctxt, id: ast::def_id) -> bool {
3909 enum_variants(cx, id).len() == 1
3912 pub fn type_is_empty(cx: ctxt, t: t) -> bool {
3913 match ty::get(t).sty {
3914 ty_enum(did, _) => (*enum_variants(cx, did)).is_empty(),
3919 pub fn enum_variants(cx: ctxt, id: ast::def_id) -> @~[@VariantInfo] {
3920 match cx.enum_var_cache.find(&id) {
3921 Some(&variants) => return variants,
3922 _ => { /* fallthrough */ }
3925 let result = if ast::LOCAL_CRATE != id.crate {
3926 @csearch::get_enum_variants(cx, id)
3929 Although both this code and check_enum_variants in typeck/check
3930 call eval_const_expr, it should never get called twice for the same
3931 expr, since check_enum_variants also updates the enum_var_cache
3933 match cx.items.get_copy(&id.node) {
3934 ast_map::node_item(@ast::item {
3935 node: ast::item_enum(ref enum_definition, _),
3938 let mut last_discriminant: Option<uint> = None;
3939 @enum_definition.variants.iter().transform(|variant| {
3941 let mut discriminant = match last_discriminant {
3942 Some(val) => val + 1,
3943 None => INITIAL_DISCRIMINANT_VALUE
3946 match variant.node.disr_expr {
3947 Some(e) => match const_eval::eval_const_expr_partial(&cx, e) {
3948 Ok(const_eval::const_int(val)) => discriminant = val as uint,
3949 Ok(const_eval::const_uint(val)) => discriminant = val as uint,
3951 cx.sess.span_err(e.span, "expected signed integer constant");
3954 cx.sess.span_err(e.span, fmt!("expected constant: %s", (*err)));
3960 let variant_info = @VariantInfo::from_ast_variant(cx, variant, discriminant);
3961 last_discriminant = Some(discriminant);
3966 _ => cx.sess.bug("enum_variants: id not bound to an enum")
3969 cx.enum_var_cache.insert(id, result);
3974 // Returns information about the enum variant with the given ID:
3975 pub fn enum_variant_with_id(cx: ctxt,
3976 enum_id: ast::def_id,
3977 variant_id: ast::def_id)
3979 let variants = enum_variants(cx, enum_id);
3981 while i < variants.len() {
3982 let variant = variants[i];
3983 if variant.id == variant_id { return variant; }
3986 cx.sess.bug("enum_variant_with_id(): no variant exists with that ID");
3990 // If the given item is in an external crate, looks up its type and adds it to
3991 // the type cache. Returns the type parameters and type.
3992 pub fn lookup_item_type(cx: ctxt,
3994 -> ty_param_bounds_and_ty {
3995 lookup_locally_or_in_crate_store(
3996 "tcache", did, cx.tcache,
3997 || csearch::get_type(cx, did))
4000 pub fn lookup_impl_vtables(cx: ctxt,
4002 -> typeck::impl_res {
4003 lookup_locally_or_in_crate_store(
4004 "impl_vtables", did, cx.impl_vtables,
4005 || csearch::get_impl_vtables(cx, did) )
4008 /// Given the did of a trait, returns its canonical trait ref.
4009 pub fn lookup_trait_def(cx: ctxt, did: ast::def_id) -> @ty::TraitDef {
4010 match cx.trait_defs.find(&did) {
4011 Some(&trait_def) => {
4012 // The item is in this crate. The caller should have added it to the
4013 // type cache already
4017 assert!(did.crate != ast::LOCAL_CRATE);
4018 let trait_def = @csearch::get_trait_def(cx, did);
4019 cx.trait_defs.insert(did, trait_def);
4025 /// Determine whether an item is annotated with an attribute
4026 pub fn has_attr(tcx: ctxt, did: def_id, attr: &str) -> bool {
4028 match tcx.items.find(&did.node) {
4030 &ast_map::node_item(@ast::item {
4033 }, _)) => attr::contains_name(*attrs, attr),
4034 _ => tcx.sess.bug(fmt!("has_attr: %? is not an item",
4038 let mut ret = false;
4039 do csearch::get_item_attrs(tcx.cstore, did) |meta_items| {
4040 ret = ret || attr::contains_name(meta_items, attr);
4046 /// Determine whether an item is annotated with `#[packed]`
4047 pub fn lookup_packed(tcx: ctxt, did: def_id) -> bool {
4048 has_attr(tcx, did, "packed")
4051 /// Determine whether an item is annotated with `#[simd]`
4052 pub fn lookup_simd(tcx: ctxt, did: def_id) -> bool {
4053 has_attr(tcx, did, "simd")
4056 // Look up a field ID, whether or not it's local
4057 // Takes a list of type substs in case the struct is generic
4058 pub fn lookup_field_type(tcx: ctxt,
4063 let t = if id.crate == ast::LOCAL_CRATE {
4064 node_id_to_type(tcx, id.node)
4067 match tcx.tcache.find(&id) {
4068 Some(&ty_param_bounds_and_ty {ty, _}) => ty,
4070 let tpt = csearch::get_field_type(tcx, struct_id, id);
4071 tcx.tcache.insert(id, tpt);
4076 subst(tcx, substs, t)
4079 // Look up the list of field names and IDs for a given struct
4080 // Fails if the id is not bound to a struct.
4081 pub fn lookup_struct_fields(cx: ctxt, did: ast::def_id) -> ~[field_ty] {
4082 if did.crate == ast::LOCAL_CRATE {
4083 match cx.items.find(&did.node) {
4084 Some(&ast_map::node_item(i,_)) => {
4086 ast::item_struct(struct_def, _) => {
4087 struct_field_tys(struct_def.fields)
4089 _ => cx.sess.bug("struct ID bound to non-struct")
4092 Some(&ast_map::node_variant(ref variant, _, _)) => {
4093 match (*variant).node.kind {
4094 ast::struct_variant_kind(struct_def) => {
4095 struct_field_tys(struct_def.fields)
4098 cx.sess.bug("struct ID bound to enum variant that isn't \
4105 fmt!("struct ID not bound to an item: %s",
4106 ast_map::node_id_to_str(cx.items, did.node,
4107 token::get_ident_interner())));
4112 return csearch::get_struct_fields(cx.sess.cstore, did);
4116 pub fn lookup_struct_field(cx: ctxt,
4117 parent: ast::def_id,
4118 field_id: ast::def_id)
4120 let r = lookup_struct_fields(cx, parent);
4121 match r.iter().find_(
4122 |f| f.id.node == field_id.node) {
4124 None => cx.sess.bug("struct ID not found in parent's fields")
4128 fn struct_field_tys(fields: &[@struct_field]) -> ~[field_ty] {
4129 do fields.map |field| {
4130 match field.node.kind {
4131 named_field(ident, visibility) => {
4134 id: ast_util::local_def(field.node.id),
4141 syntax::parse::token::special_idents::unnamed_field,
4142 id: ast_util::local_def(field.node.id),
4150 // Returns a list of fields corresponding to the struct's items. trans uses
4151 // this. Takes a list of substs with which to instantiate field types.
4152 pub fn struct_fields(cx: ctxt, did: ast::def_id, substs: &substs)
4154 do lookup_struct_fields(cx, did).map |f| {
4158 ty: lookup_field_type(cx, did, f.id, substs),
4165 pub fn is_binopable(cx: ctxt, ty: t, op: ast::binop) -> bool {
4166 static tycat_other: int = 0;
4167 static tycat_bool: int = 1;
4168 static tycat_int: int = 2;
4169 static tycat_float: int = 3;
4170 static tycat_struct: int = 4;
4171 static tycat_bot: int = 5;
4173 static opcat_add: int = 0;
4174 static opcat_sub: int = 1;
4175 static opcat_mult: int = 2;
4176 static opcat_shift: int = 3;
4177 static opcat_rel: int = 4;
4178 static opcat_eq: int = 5;
4179 static opcat_bit: int = 6;
4180 static opcat_logic: int = 7;
4182 fn opcat(op: ast::binop) -> int {
4184 ast::add => opcat_add,
4185 ast::subtract => opcat_sub,
4186 ast::mul => opcat_mult,
4187 ast::div => opcat_mult,
4188 ast::rem => opcat_mult,
4189 ast::and => opcat_logic,
4190 ast::or => opcat_logic,
4191 ast::bitxor => opcat_bit,
4192 ast::bitand => opcat_bit,
4193 ast::bitor => opcat_bit,
4194 ast::shl => opcat_shift,
4195 ast::shr => opcat_shift,
4196 ast::eq => opcat_eq,
4197 ast::ne => opcat_eq,
4198 ast::lt => opcat_rel,
4199 ast::le => opcat_rel,
4200 ast::ge => opcat_rel,
4201 ast::gt => opcat_rel
4205 fn tycat(cx: ctxt, ty: t) -> int {
4206 if type_is_simd(cx, ty) {
4207 return tycat(cx, simd_type(cx, ty))
4210 ty_bool => tycat_bool,
4211 ty_int(_) | ty_uint(_) | ty_infer(IntVar(_)) => tycat_int,
4212 ty_float(_) | ty_infer(FloatVar(_)) => tycat_float,
4213 ty_tup(_) | ty_enum(_, _) => tycat_struct,
4214 ty_bot => tycat_bot,
4219 static t: bool = true;
4220 static f: bool = false;
4226 /*other*/ ~[f, f, f, f, f, f, f, f],
4227 /*bool*/ ~[f, f, f, f, t, t, t, t],
4228 /*int*/ ~[t, t, t, t, t, t, t, f],
4229 /*float*/ ~[t, t, t, f, t, t, f, f],
4230 /*bot*/ ~[f, f, f, f, f, f, f, f],
4231 /*struct*/ ~[t, t, t, t, f, f, t, t]];
4233 return tbl[tycat(cx, ty)][opcat(op)];
4236 pub fn ty_params_to_tys(tcx: ty::ctxt, generics: &ast::Generics) -> ~[t] {
4237 vec::from_fn(generics.ty_params.len(), |i| {
4238 let id = generics.ty_params.get(i).id;
4239 ty::mk_param(tcx, i, ast_util::local_def(id))
4243 /// Returns an equivalent type with all the typedefs and self regions removed.
4244 pub fn normalize_ty(cx: ctxt, t: t) -> t {
4245 fn normalize_mt(cx: ctxt, mt: mt) -> mt {
4246 mt { ty: normalize_ty(cx, mt.ty), mutbl: mt.mutbl }
4248 fn normalize_vstore(vstore: vstore) -> vstore {
4250 vstore_fixed(*) | vstore_uniq | vstore_box => vstore,
4251 vstore_slice(_) => vstore_slice(re_static)
4255 match cx.normalized_cache.find(&t) {
4256 Some(&t) => return t,
4260 let t = match get(t).sty {
4261 ty_evec(mt, vstore) =>
4262 // This type has a vstore. Get rid of it
4263 mk_evec(cx, normalize_mt(cx, mt), normalize_vstore(vstore)),
4266 // This type has a vstore. Get rid of it
4267 mk_estr(cx, normalize_vstore(vstore)),
4270 // This type has a region. Get rid of it
4271 mk_rptr(cx, re_static, normalize_mt(cx, mt)),
4273 ty_closure(ref closure_ty) => {
4274 mk_closure(cx, ClosureTy {
4275 region: ty::re_static,
4276 ..(*closure_ty).clone()
4280 ty_enum(did, ref r) => {
4281 match (*r).regions {
4282 NonerasedRegions(_) => {
4283 // trans doesn't care about regions
4284 mk_enum(cx, did, substs {regions: ty::ErasedRegions,
4286 tps: (*r).tps.clone()})
4294 ty_struct(did, ref r) => {
4295 match (*r).regions {
4296 NonerasedRegions(_) => {
4298 mk_struct(cx, did, substs {regions: ty::ErasedRegions,
4300 tps: (*r).tps.clone()})
4312 let sty = fold_sty(&get(t).sty, |t| { normalize_ty(cx, t) });
4313 let t_norm = mk_t(cx, sty);
4314 cx.normalized_cache.insert(t, t_norm);
4318 pub trait ExprTyProvider {
4319 pub fn expr_ty(&self, ex: &ast::expr) -> t;
4320 pub fn ty_ctxt(&self) -> ctxt;
4323 impl ExprTyProvider for ctxt {
4324 pub fn expr_ty(&self, ex: &ast::expr) -> t {
4328 pub fn ty_ctxt(&self) -> ctxt {
4333 // Returns the repeat count for a repeating vector expression.
4334 pub fn eval_repeat_count<T: ExprTyProvider>(tcx: &T, count_expr: &ast::expr) -> uint {
4335 match const_eval::eval_const_expr_partial(tcx, count_expr) {
4336 Ok(ref const_val) => match *const_val {
4337 const_eval::const_int(count) => if count < 0 {
4338 tcx.ty_ctxt().sess.span_err(count_expr.span,
4339 "expected positive integer for \
4340 repeat count but found negative integer");
4343 return count as uint
4345 const_eval::const_uint(count) => return count as uint,
4346 const_eval::const_float(count) => {
4347 tcx.ty_ctxt().sess.span_err(count_expr.span,
4348 "expected positive integer for \
4349 repeat count but found float");
4350 return count as uint;
4352 const_eval::const_str(_) => {
4353 tcx.ty_ctxt().sess.span_err(count_expr.span,
4354 "expected positive integer for \
4355 repeat count but found string");
4358 const_eval::const_bool(_) => {
4359 tcx.ty_ctxt().sess.span_err(count_expr.span,
4360 "expected positive integer for \
4361 repeat count but found boolean");
4366 tcx.ty_ctxt().sess.span_err(count_expr.span,
4367 "expected constant integer for repeat count \
4368 but found variable");
4374 // Determine what purity to check a nested function under
4375 pub fn determine_inherited_purity(parent: (ast::purity, ast::NodeId),
4376 child: (ast::purity, ast::NodeId),
4377 child_sigil: ast::Sigil)
4378 -> (ast::purity, ast::NodeId) {
4379 // If the closure is a stack closure and hasn't had some non-standard
4380 // purity inferred for it, then check it under its parent's purity.
4381 // Otherwise, use its own
4383 ast::BorrowedSigil if child.first() == ast::impure_fn => parent,
4388 // Iterate over a type parameter's bounded traits and any supertraits
4389 // of those traits, ignoring kinds.
4390 // Here, the supertraits are the transitive closure of the supertrait
4391 // relation on the supertraits from each bounded trait's constraint
4393 pub fn each_bound_trait_and_supertraits(tcx: ctxt,
4394 bounds: &[@TraitRef],
4395 f: &fn(@TraitRef) -> bool) -> bool {
4396 for &bound_trait_ref in bounds.iter() {
4397 let mut supertrait_set = HashMap::new();
4398 let mut trait_refs = ~[];
4401 // Seed the worklist with the trait from the bound
4402 supertrait_set.insert(bound_trait_ref.def_id, ());
4403 trait_refs.push(bound_trait_ref);
4405 // Add the given trait ty to the hash map
4406 while i < trait_refs.len() {
4407 debug!("each_bound_trait_and_supertraits(i=%?, trait_ref=%s)",
4408 i, trait_refs[i].repr(tcx));
4410 if !f(trait_refs[i]) {
4414 // Add supertraits to supertrait_set
4415 let supertrait_refs = trait_ref_supertraits(tcx, trait_refs[i]);
4416 for &supertrait_ref in supertrait_refs.iter() {
4417 debug!("each_bound_trait_and_supertraits(supertrait_ref=%s)",
4418 supertrait_ref.repr(tcx));
4420 let d_id = supertrait_ref.def_id;
4421 if !supertrait_set.contains_key(&d_id) {
4422 // FIXME(#5527) Could have same trait multiple times
4423 supertrait_set.insert(d_id, ());
4424 trait_refs.push(supertrait_ref);
4434 pub fn count_traits_and_supertraits(tcx: ctxt,
4435 type_param_defs: &[TypeParameterDef]) -> uint {
4437 for type_param_def in type_param_defs.iter() {
4438 do each_bound_trait_and_supertraits(
4439 tcx, type_param_def.bounds.trait_bounds) |_| {
4447 pub fn get_tydesc_ty(tcx: ctxt) -> Result<t, ~str> {
4448 do tcx.lang_items.require(TyDescStructLangItem).map |tydesc_lang_item| {
4449 tcx.intrinsic_defs.find_copy(tydesc_lang_item)
4450 .expect("Failed to resolve TyDesc")
4454 pub fn get_opaque_ty(tcx: ctxt) -> Result<t, ~str> {
4455 do tcx.lang_items.require(OpaqueStructLangItem).map |opaque_lang_item| {
4456 tcx.intrinsic_defs.find_copy(opaque_lang_item)
4457 .expect("Failed to resolve Opaque")
4461 pub fn visitor_object_ty(tcx: ctxt) -> Result<(@TraitRef, t), ~str> {
4462 let trait_lang_item = match tcx.lang_items.require(TyVisitorTraitLangItem) {
4464 Err(s) => { return Err(s); }
4466 let substs = substs {
4467 regions: ty::NonerasedRegions(opt_vec::Empty),
4471 let trait_ref = @TraitRef { def_id: trait_lang_item, substs: substs };
4472 let mut static_trait_bound = EmptyBuiltinBounds();
4473 static_trait_bound.add(BoundStatic);
4477 trait_ref.substs.clone(),
4480 static_trait_bound)))